Merge branches/gramps35 with trunk
svn: r20164
This commit is contained in:
parent
3158247c90
commit
55685f32b6
@ -17,6 +17,8 @@
|
||||
<script type="text/javascript" src="/styles/javascript/jquery-ui-1.7.2.custom.min.js"></script>
|
||||
<script type="text/javascript" src="/styles/jhtmlarea/scripts/jHtmlArea-0.7.0.js"></script>
|
||||
<link rel="Stylesheet" type="text/css" href="/styles/jhtmlarea/style/jHtmlArea.css" />
|
||||
<script type="text/javascript" src="/styles/javascript/jquery.flexbox.min.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="/styles/css/jquery.flexbox.css" />
|
||||
{% endblock %}
|
||||
|
||||
<style type="text/css">
|
||||
@ -239,8 +241,7 @@ function optClick(theOption) {
|
||||
document.location.href=theOption;
|
||||
}
|
||||
|
||||
function setHasData(classname, value)
|
||||
{
|
||||
function setHasData(classname, value) {
|
||||
var elems = document.getElementsByTagName('*'), i;
|
||||
for (i in elems) {
|
||||
if((" " + elems[i].className + " ").indexOf(" " + classname + " ") > -1) {
|
||||
@ -254,6 +255,18 @@ function setHasData(classname, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setReturnValues() {
|
||||
var elems = document.getElementsByTagName('*'), i;
|
||||
for (i in elems) {
|
||||
if ((" " + elems[i].name + " ").indexOf("_return ") > -1) {
|
||||
var pos = (" " + elems[i].name + " ").indexOf("_return ");
|
||||
var s = elems[i].name.substring(0, pos - 1);
|
||||
var v = document.getElementsByName(s)[0];
|
||||
elems[i].value = v.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-->
|
||||
</SCRIPT>
|
||||
|
||||
@ -273,7 +286,9 @@ function setHasData(classname, value)
|
||||
-->
|
||||
</STYLE>
|
||||
</head>
|
||||
<body onclick="hideMenus()" onload="if (document.getElementById('get_focus')) {document.getElementById('get_focus').focus();}">
|
||||
<body onclick="hideMenus()"
|
||||
onload="if (document.getElementById('get_focus')) {document.getElementById('get_focus').focus();}"
|
||||
>
|
||||
<div id="header" style="padding-top: 1em; background-position:0px -32px;">
|
||||
<h1 id="SiteTitle" style="margin-left: 0em;">{% block heading %}{{sitename}}{% endblock %}</h1>
|
||||
</div>
|
||||
@ -348,11 +363,11 @@ function setHasData(classname, value)
|
||||
</div>
|
||||
<div class="grampsweb">
|
||||
{% for message in messages %}
|
||||
<font color="red">{{message}}</font>
|
||||
<font color="red">{{message}}</font><br/>
|
||||
{% endfor %}
|
||||
{% if message %}
|
||||
<div id="system_message" class="{{ message_type }}">
|
||||
<font color="red">{{message}}</font>
|
||||
<font color="red">{{message}}</font><br/>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
@ -363,11 +378,12 @@ function setHasData(classname, value)
|
||||
<div id="footer">
|
||||
{% block footer %}
|
||||
<p id="createdate">
|
||||
<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps-Connect">Gramps Connect, version {{gramps_version}}</a>.
|
||||
<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps-Connect">Gramps-Connect, version {{gramps_version}}</a>.
|
||||
</p>
|
||||
<p id="copyright">© 2009-2012 <a href="http://www.gramps-project.org/">www.gramps-project.org</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -17,12 +17,16 @@
|
||||
{% for source in page.object_list %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
|
||||
>
|
||||
<span class="grampsid">[{{source.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.title|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.pubinfo|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.author|nbsp}}</a>
|
||||
{% if user.is_authenticated or source.public %}
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
|
||||
>{{source.title|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
|
||||
>{{source.pubinfo|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
|
||||
>{{source.author|nbsp}}</a>
|
||||
{% else %}
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
@ -26,24 +26,49 @@
|
||||
<div id="error">{{eventform.errors}}</div>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<form method="post">{% csrf_token %}
|
||||
<form method="post" onsubmit="setReturnValues()">{% csrf_token %}
|
||||
<tr>
|
||||
<td class="ColumnAttribute">{{eventform.event_type.label}}:</td>
|
||||
<td class="ColumnValue" id="data"> {% render eventform.event_type user action %}</td>
|
||||
<td class="ColumnAttribute">{{eventform.text.label}}:</td>
|
||||
<td class="ColumnValue" id="data">{% render eventform.text user action %}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Description:</td>
|
||||
<td class="ColumnValue" id="data" colspan="3">{% render eventform.description user action %}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">ID:</td>
|
||||
<td class="ColumnValue" id="data" colspan="3">{% render eventform.gramps_id user action %}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Place:</td>
|
||||
<td class="ColumnValue" id="data" colspan="3">{% render eventform.place user action %}</td>
|
||||
<td class="ColumnValue" id="data" colspan="3">
|
||||
{% if action != "view" %}
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#place').flexbox('/json/?field=place', {
|
||||
watermark: 'Place',
|
||||
width: 600,
|
||||
paging: {
|
||||
pageSize: 10
|
||||
},
|
||||
initialValue: '{{event.place.get_selection_string}}',
|
||||
initialId: '{{event.place.handle}}'
|
||||
});
|
||||
});
|
||||
// </script>
|
||||
<div id="place"></div>
|
||||
{% else %}
|
||||
<a href="/place/?search={{event.place}}">{{event.place}}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<td class="ColumnValue" id="data" colspan="3">{% render eventform.private user action %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@ -82,6 +107,7 @@
|
||||
{% if user.is_superuser %}
|
||||
{% if action == "edit" %}
|
||||
{% make_button "Cancel" "/event/%s" event.handle args %}
|
||||
<input type="hidden" id="place_return" name="place_return" value=""/>
|
||||
<input type="hidden" name="action" value="save"/>
|
||||
<input type="hidden" name="search" value="{{search}}"/>
|
||||
<input type="hidden" name="page" value="{{page}}"/>
|
||||
@ -89,6 +115,7 @@
|
||||
{% else %}
|
||||
{% ifequal action "add" %}
|
||||
{% make_button "Cancel" "/event/" args %}
|
||||
<input type="hidden" id="place_return" name="place_return" value=""/>
|
||||
<input type="hidden" name="action" value="create"/>
|
||||
<input type="hidden" name="search" value="{{search}}"/>
|
||||
<input type="hidden" name="page" value="{{page}}"/>
|
||||
|
@ -21,20 +21,17 @@
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<span class="grampsid">[{{event.gramps_id}}]</span></a>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
|
||||
{% if user.is_authenticated or event.public %}
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.event_type|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.description|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event|date_as_text:user}}</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.place.title|nbsp}}</a>
|
||||
|
||||
{% else %}
|
||||
<td>[Private]</td>
|
||||
<td>[Private]</td>
|
||||
<td>[Private]</td>
|
||||
<td>[Private]</td>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
|
||||
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -16,14 +16,44 @@
|
||||
<tbody>
|
||||
{% for family in page.object_list %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{ forloop.counter|row_count:page }}</a></td>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"><span class="grampsid">[{{family.gramps_id}}]</span></a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.father|make_name:user|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.mother|make_name:user|nbsp}}</a>
|
||||
{% if user.is_authenticated %}
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.family_rel_type|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{ forloop.counter|row_count:page }}</a></td>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
><span class="grampsid">[{{family.gramps_id}}]</span></a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{family.father|make_name:user|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{family.mother|make_name:user|nbsp}}</a>
|
||||
{% if user.is_authenticated or family.public %}
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{family.family_rel_type|escape|nbsp}}</a>
|
||||
{% else %}
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">[Private]</a>
|
||||
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if family.tags.all %}
|
||||
style="color: {{family.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>
|
||||
{% if not family.public %}
|
||||
[Private]
|
||||
{% else %}
|
||||
{{family.family_rel_type}}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -28,7 +28,7 @@
|
||||
<div id="error">{{familyform.errors}}</div>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<form method="post">{% csrf_token %}
|
||||
<form method="post" onsubmit="setReturnValues()">{% csrf_token %}
|
||||
<tr>
|
||||
<th colspan="2">Father</th>
|
||||
<th colspan="2">Mother</th>
|
||||
@ -36,16 +36,55 @@
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Name:</td>
|
||||
{% if user.is_authenticated or father.probably_alive %}
|
||||
<td class="ColumnValue" id="data">{% render familyform.father user action %}</td>
|
||||
<td class="ColumnValue" id="data">
|
||||
{% if action != "view" %}
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#father').flexbox('/json/?field=father', {
|
||||
watermark: 'Father',
|
||||
width: 300,
|
||||
paging: {
|
||||
pageSize: 10
|
||||
},
|
||||
initialValue: '{{family.father.get_selection_string}}',
|
||||
initialId: '{{family.father.handle}}'
|
||||
});
|
||||
});
|
||||
// </script>
|
||||
<div id="father"></div>
|
||||
{% else %}
|
||||
<td class="ColumnValue" id="data">{{family.father|render_name:user}}</td>
|
||||
{{family.father|render_name:user}}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
{{family.father|render_name:user}}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="ColumnAttribute">Name:</td>
|
||||
{% if user.is_authenticated or family.mother.probably_alive %}
|
||||
<td class="ColumnValue" id="data">{% render familyform.mother user action %}</td>
|
||||
<td class="ColumnValue" id="data">
|
||||
{% if action != "view" %}
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#mother').flexbox('/json/?field=mother', {
|
||||
watermark: 'Mother',
|
||||
width: 300,
|
||||
paging: {
|
||||
pageSize: 10
|
||||
},
|
||||
initialValue: '{{family.mother.get_selection_string}}',
|
||||
initialId: '{{family.mother.handle}}'
|
||||
});
|
||||
});
|
||||
// </script>
|
||||
<div id="mother"></div>
|
||||
{% else %}
|
||||
<td class="ColumnValue" id="data">{{family.mother|render_name:user}}</td>
|
||||
{{family.mother|render_name:user}}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{family.mother|render_name:user}}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if user.is_authenticated or not familyform.father.probably_alive %}
|
||||
<tr>
|
||||
@ -135,6 +174,8 @@
|
||||
{% if user.is_superuser %}
|
||||
{% if action == "edit" %}
|
||||
{% make_button "Cancel" "/family/%s" family.handle args %}
|
||||
<input type="hidden" id="father_return" name="father_return" value=""/>
|
||||
<input type="hidden" id="mother_return" name="mother_return" value=""/>
|
||||
<input type="hidden" name="action" value="save"/>
|
||||
<input type="hidden" name="search" value="{{search}}"/>
|
||||
<input type="hidden" name="page" value="{{page}}"/>
|
||||
@ -142,6 +183,8 @@
|
||||
{% else %}
|
||||
{% ifequal action "add" %}
|
||||
{% make_button "Cancel" "/family/" args %}
|
||||
<input type="hidden" id="father_return" name="father_return" value=""/>
|
||||
<input type="hidden" id="mother_return" name="mother_return" value=""/>
|
||||
<input type="hidden" name="action" value="create"/>
|
||||
<input type="hidden" name="search" value="{{search}}"/>
|
||||
<input type="hidden" name="page" value="{{page}}"/>
|
||||
|
@ -16,11 +16,23 @@
|
||||
{% for media in page.object_list %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="noThumb browsecell"
|
||||
{% if media.tags.all %}
|
||||
style="color: {{media.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>
|
||||
<span class="grampsid">[{{media.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell">{{media.desc|escape}}</a>
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell">{{media.path|escape}}</a>
|
||||
{% if user.is_authenticated or media.public %}
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if media.tags.all %}
|
||||
style="color: {{media.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{media.desc|escape}}</a>
|
||||
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if media.tags.all %}
|
||||
style="color: {{media.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{media.path|escape}}</a>
|
||||
{% else %}
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
@ -16,14 +16,26 @@
|
||||
{% for note in page.object_list %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="noThumb browsecell"
|
||||
{% if note.tags.all %}
|
||||
style="color: {{note.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>
|
||||
<span class="grampsid">[{{note.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell">{{note.note_type|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell">{{note.text|preview:70|nbsp}}</a>
|
||||
{% if user.is_authenticated or note.public %}
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if note.tags.all %}
|
||||
style="color: {{note.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{note.note_type|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell"
|
||||
{% if note.tags.all %}
|
||||
style="color: {{note.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{note.text|preview:70|nbsp}}</a>
|
||||
{% else %}
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>[Private]</td>
|
||||
<td>[Private]</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -16,16 +16,40 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for name in page.object_list %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<tr class="{% cycle odd,even %}" style="">
|
||||
{% if name.person %}
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{ forloop.counter|row_count:page }}</a>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{ forloop.counter|row_count:page }}</a>
|
||||
</td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name|make_name:user}} </a>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{name|make_name:user}} </a>
|
||||
</td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="grampsid browsecell">[{{name.person.gramps_id}}]</a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.gender_type}} </a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.birth|date_as_text:user}} </a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.death|date_as_text:user}} </a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="grampsid browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>[{{name.person.gramps_id}}]</a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{name.person.gender_type}} </a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{name.person.birth|date_as_text:user}} </a></td>
|
||||
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
|
||||
{% if name.person.tags.all %}
|
||||
style="color: {{name.person.tags.all.0.color|format_color}};"
|
||||
{% endif %}
|
||||
>{{name.person.death|date_as_text:user}} </a></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -60,7 +60,39 @@
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-history" href="#tab-history">History</a></li>
|
||||
</ul>
|
||||
<div class="ui-tab-panel ui-widget-content ui-corner-bottom" id="tab-locations" style="background-color: #f4f0ec;">
|
||||
<!-- place.location_set -->
|
||||
|
||||
<table class="infolist" style="width:90%;">
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Street:</td>
|
||||
<td class="Columnvalue" id="data" colspan="3"> FIXME </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Locality:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
<td class="ColumnAttribute">Church parish:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">City:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
<td class="ColumnAttribute">State:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">County:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
<td class="ColumnAttribute">ZIP/Postal code:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="ColumnAttribute">Country:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
<td class="ColumnAttribute">Phone:</td>
|
||||
<td class="Columnvalue" id="data"> FIXME </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="ui-tab-panel ui-widget-content ui-corner-bottom ui-tab-hide" id="tab-alternatelocations" style="background-color: #f4f0ec;">
|
||||
{% location_table place user action "/location/$act/place/%s" place.handle %}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{place.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<span class="grampsid">[{{place.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_authenticated or place.public %}
|
||||
<td><a href="/{{view}}/{{place.handle|escape}}{{args}}" class="browsecell">{{place.title|escape|nbsp}}</a>
|
||||
{% else %}
|
||||
<td></td>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<span class="grampsid">[{{repository.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_authenticated or repository.public %}
|
||||
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="browsecell">{{repository.repository_type|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="browsecell">{{repository.name|escape|nbsp}}</a>
|
||||
{% else %}
|
||||
|
@ -54,11 +54,11 @@
|
||||
<div class="ui-tabs ui-widget ui-widget-content ui-corner-all" id="tabs" style="border: none;">
|
||||
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
|
||||
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a class="tab-notes" href="#tab-notes">Note</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="#tab-media" href="#tab-media">Media</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="#tab-data" href="#tab-data">Data</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="#tab-repositories" href="#tab-repositories">Repository</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="#tab-references" href="#tab-references">Reference</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="#tab-history" href="#tab-history">History</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-media" href="#tab-media">Media</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-data" href="#tab-data">Data</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-repositories" href="#tab-repositories">Repository</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-references" href="#tab-references">Reference</a></li>
|
||||
<li class="ui-corner-top ui-state-default"><a class="tab-history" href="#tab-history">History</a></li>
|
||||
</ul>
|
||||
<div class="ui-tabs-panel ui-widget-content ui-corner-bottom" id="tab-notes" style="background-color: #f4f0ec;">
|
||||
{% note_table source user action "/note/$act/source/%s" source.handle %}
|
||||
|
@ -19,7 +19,7 @@
|
||||
<td>{{ forloop.counter|row_count:page }}</td>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="noThumb browsecell">
|
||||
<span class="grampsid">[{{source.gramps_id}}]</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_authenticated or source.public %}
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.title|escape|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.pubinfo|nbsp}}</a>
|
||||
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.author|nbsp}}</a>
|
||||
|
65
src/gen/utils/svn.py
Normal file
65
src/gen/utils/svn.py
Normal file
@ -0,0 +1,65 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2012 Doug Blank <doug.blank@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: $
|
||||
|
||||
"""
|
||||
Based on the version from Django, a Python ORM.
|
||||
"""
|
||||
|
||||
import re
|
||||
import os
|
||||
|
||||
def get_svn_revision(path=None):
|
||||
"""
|
||||
Returns the SVN revision in the form SVN-XXXX,
|
||||
where XXXX is the revision number.
|
||||
|
||||
Returns "" if anything goes wrong, such as an unexpected
|
||||
format of internal SVN files.
|
||||
|
||||
If path is provided, it should be a directory whose SVN info you
|
||||
want to inspect. If it's not provided, this will use the directory
|
||||
where this file resides.
|
||||
"""
|
||||
rev = None
|
||||
if path is None:
|
||||
path = os.path.dirname(__file__)
|
||||
entries_path = '%s/.svn/entries' % path
|
||||
try:
|
||||
entries = open(entries_path, 'r').read()
|
||||
except IOError:
|
||||
pass
|
||||
else:
|
||||
# Versions >= 7 of the entries file are flat text. The first line is
|
||||
# the version number. The next set of digits after 'dir' is the revision
|
||||
if re.match('(\d+)', entries):
|
||||
rev_match = re.search('\d+\s+dir\s+(\d+)', entries)
|
||||
if rev_match:
|
||||
rev = rev_match.groups()[0]
|
||||
# Older XML versions of the file specify revision as an attribute of
|
||||
# the first entries node.
|
||||
else:
|
||||
from xml.dom import minidom
|
||||
dom = minidom.parse(entries_path)
|
||||
rev = dom.getElementsByTagName('entry')[0].getAttribute('revision')
|
||||
if rev:
|
||||
return u'SVN-%s' % rev
|
||||
return u''
|
BIN
src/plugins/webstuff/img/Thumbs.db
Normal file
BIN
src/plugins/webstuff/img/Thumbs.db
Normal file
Binary file not shown.
BIN
src/plugins/webstuff/img/sel_classic.gif
Normal file
BIN
src/plugins/webstuff/img/sel_classic.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1009 B |
BIN
src/plugins/webstuff/img/sel_vista.gif
Normal file
BIN
src/plugins/webstuff/img/sel_vista.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
src/plugins/webstuff/img/sel_win7.gif
Normal file
BIN
src/plugins/webstuff/img/sel_win7.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
859
src/plugins/webstuff/javascript/jquery.flexbox.js
Normal file
859
src/plugins/webstuff/javascript/jquery.flexbox.js
Normal file
@ -0,0 +1,859 @@
|
||||
/*!
|
||||
* jQuery FlexBox $Version: 0.9.6 $
|
||||
*
|
||||
* Copyright (c) 2008-2010 Noah Heldman and Fairway Technologies (http://www.fairwaytech.com/flexbox)
|
||||
* Licensed under Ms-PL (http://www.codeplex.com/flexbox/license)
|
||||
*
|
||||
* $Date: 2010-11-24 01:02:00 PM $
|
||||
* $Rev: 0.9.6.1 $
|
||||
*/
|
||||
(function($) {
|
||||
$.flexbox = function(div, o) {
|
||||
|
||||
// TODO: in straight type-ahead mode (showResults: false), if noMatchingResults, dropdown appears after new match
|
||||
// TODO: consider having options.mode (select, which replaces html select; combobox; suggest; others?)
|
||||
// TODO: on resize (at least when wrapping within a table), the arrow is pushed down to the next line
|
||||
// TODO: check for boundary/value problems (such as minChars of -1) and alert them
|
||||
// TODO: add options for advanced paging template
|
||||
// TODO: general cleanup and refactoring, commenting
|
||||
// TODO: detailed Exception handling, logging
|
||||
// TODO: FF2, up arrow from bottom has erratic scroll behavior (if multiple flexboxes on page)
|
||||
// TODO: FF2 (and maybe IE7): if maxVisibleRows == number of returned rows, height is a bit off (maybe set to auto?)
|
||||
// TODO: escape key only works from input box (this might be okay)
|
||||
// TODO: make .getJSON parameters (object and callback function) configurable (e.g. when calling yahoo image search)
|
||||
// TODO: escape key reverts to previous value (FF only?) (is this a good thing?)
|
||||
|
||||
// TEST: highlightMatches uses the case of whatever you typed in to replace the match string, which can look funny
|
||||
// TEST: handle pageDown and pageUp keys when scrolling through results
|
||||
// TEST: allow client-side paging (return all data initially, set paging:{pageSize:#}, and ensure maxCacheBytes is > 0)
|
||||
// TEST: accept json object as first parameter to flexbox instead of page source, and have it work like a combobox
|
||||
// TEST: implement no results template
|
||||
// TEST: implement noResultsText and class
|
||||
// TEST: watermark color should be configurable (and so should default input color)
|
||||
// TEST: exception handling and alerts for common mistakes
|
||||
// TEST: first example should use defaults ONLY
|
||||
// TEST: add property initialValue, so you can set it when the flexbox loads
|
||||
// TEST: handle hidden input value for form submissions
|
||||
// TEST: how can we allow programmatically setting the field value (and therefore hidden value). add jquery function?
|
||||
// TEST: use pageSize parameter as threshold to switch from no paging to paging based on results
|
||||
// TEST: if you type in an input value that matches the html, it might display html code (try typing "class" in the input box)
|
||||
// TEST: don't require all paging subprops (let default override)
|
||||
// TEST: when tabbing from one ffb to another, the previous ffb results flash...
|
||||
// TEST: IE7: when two non-paging ffbs right after each other, with only a clear-both div between them, the bottom ffb jumps down when selecting a value, then jumps back up on mouseover
|
||||
// TEST: FF2, make sure we scroll to top before showing results (maxVisibleRows only)
|
||||
// TEST: if maxVisibleRows is hiding the value the user types in to the input, scroll to that value (is this even possible?)
|
||||
// TEST: make sure caching supports multiple ffbs uniquely
|
||||
// TEST: when entering a number in the paging input box, the results are displayed twice
|
||||
|
||||
var timeout = false, // hold timeout ID for suggestion results to appear
|
||||
cache = [], // simple array with cacheData key values, MRU is the first element
|
||||
cacheData = [], // associative array holding actual cached data
|
||||
cacheSize = 0, // size of cache in bytes (cache up to o.maxCacheBytes bytes)
|
||||
delim = '\u25CA', // use an obscure unicode character (lozenge) as the cache key delimiter
|
||||
scrolling = false,
|
||||
pageSize = o.paging && o.paging.pageSize ? o.paging.pageSize : 0,
|
||||
retrievingRemoteData = false,
|
||||
$div = $(div).css('position', 'relative').css('z-index', 0);
|
||||
|
||||
// The hiddenField MUST be appended to the div before the input, or IE7 does not shift the dropdown below the input field (it overlaps)
|
||||
var $hdn = $('<input type="hidden"/>')
|
||||
.attr('id', $div.attr('id') + '_hidden')
|
||||
.attr('name', $div.attr('id'))
|
||||
.val(o.initialId)
|
||||
.appendTo($div);
|
||||
var $input = $('<input/>')
|
||||
.attr('id', $div.attr('id') + '_input')
|
||||
.attr('autocomplete', 'off')
|
||||
.addClass(o.inputClass)
|
||||
.css('width', o.width + 'px')
|
||||
.appendTo($div)
|
||||
.click(function(e) {
|
||||
if (o.watermark !== '' && this.value === o.watermark)
|
||||
this.value = '';
|
||||
else
|
||||
this.select();
|
||||
})
|
||||
.focus(function(e) {
|
||||
$(this).removeClass('watermark');
|
||||
})
|
||||
.blur(function(e) {
|
||||
if (this.value === '') $hdn.val('');
|
||||
setTimeout(function() { if (!$input.data('active')) hideResults(); }, 200);
|
||||
})
|
||||
.keydown(processKeyDown);
|
||||
|
||||
if (o.initialValue !== '')
|
||||
$input.val(o.initialValue).removeClass('watermark');
|
||||
else
|
||||
$input.val(o.watermark).addClass('watermark');
|
||||
|
||||
var arrowWidth = 0;
|
||||
if (o.showArrow && o.showResults) {
|
||||
var arrowClick = function() {
|
||||
if ($ctr.is(':visible')) {
|
||||
hideResults();
|
||||
}
|
||||
else {
|
||||
$input.focus();
|
||||
if (o.watermark !== '' && $input.val() === o.watermark)
|
||||
$input.val('');
|
||||
else
|
||||
$input.select();
|
||||
if (timeout)
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() { flexbox(1, true, o.arrowQuery); }, o.queryDelay);
|
||||
}
|
||||
};
|
||||
var $arrow = $('<span></span>')
|
||||
.attr('id', $div.attr('id') + '_arrow')
|
||||
.addClass(o.arrowClass)
|
||||
.addClass('out')
|
||||
.hover(function() {
|
||||
$(this).removeClass('out').addClass('over');
|
||||
}, function() {
|
||||
$(this).removeClass('over').addClass('out');
|
||||
})
|
||||
.mousedown(function() {
|
||||
$(this).removeClass('over').addClass('active');
|
||||
})
|
||||
.mouseup(function() {
|
||||
$(this).removeClass('active').addClass('over');
|
||||
})
|
||||
.click(arrowClick)
|
||||
.appendTo($div);
|
||||
arrowWidth = $arrow.width();
|
||||
$input.css('width', (o.width - arrowWidth) + 'px');
|
||||
}
|
||||
if (!o.allowInput) { o.selectFirstMatch = false; $input.click(arrowClick); } // simulate <select> behavior
|
||||
|
||||
// Handle presence of CSS Universal Selector (*) that defines padding by verifying what the browser thinks the outerHeight is.
|
||||
// In FF, the outerHeight() will not pick up the correct input field padding
|
||||
var inputPad = $input.outerHeight() - $input.height() - 2;
|
||||
var inputWidth = $input.outerWidth() - 2;
|
||||
var top = $input.outerHeight();
|
||||
|
||||
if (inputPad === 0) {
|
||||
inputWidth += 4;
|
||||
top += 4;
|
||||
}
|
||||
else if (inputPad !== 4) {
|
||||
inputWidth += inputPad;
|
||||
top += inputPad;
|
||||
}
|
||||
|
||||
var $ctr = $('<div></div>')
|
||||
.attr('id', $div.attr('id') + '_ctr')
|
||||
.css('width', inputWidth + arrowWidth)
|
||||
.css('top', top)
|
||||
.css('left', 0)
|
||||
.addClass(o.containerClass)
|
||||
.appendTo($div)
|
||||
.mousedown(function(e) {
|
||||
$input.data('active', true);
|
||||
})
|
||||
.hide();
|
||||
|
||||
var $content = $('<div></div>')
|
||||
.addClass(o.contentClass)
|
||||
.appendTo($ctr)
|
||||
.scroll(function() {
|
||||
scrolling = true;
|
||||
});
|
||||
|
||||
var $paging = $('<div></div>').appendTo($ctr);
|
||||
$div.css('height', $input.outerHeight());
|
||||
|
||||
function processKeyDown(e) {
|
||||
// handle modifiers
|
||||
var mod = 0;
|
||||
if (typeof (e.ctrlKey) !== 'undefined') {
|
||||
if (e.ctrlKey) mod |= 1;
|
||||
if (e.shiftKey) mod |= 2;
|
||||
} else {
|
||||
if (e.modifiers & Event.CONTROL_MASK) mod |= 1;
|
||||
if (e.modifiers & Event.SHIFT_MASK) mod |= 2;
|
||||
}
|
||||
// if the keyCode is one of the modifiers, bail out (we'll catch it on the next keypress)
|
||||
if (/16$|17$/.test(e.keyCode)) return; // 16 = Shift, 17 = Ctrl
|
||||
|
||||
var tab = e.keyCode === 9, esc = e.keyCode === 27;
|
||||
var tabWithModifiers = e.keyCode === 9 && mod > 0;
|
||||
var backspace = e.keyCode === 8; // we will end up extending the delay time for backspaces...
|
||||
|
||||
// tab is a special case, since we want to bubble events...
|
||||
if (tab) if (getCurr()) selectCurr();
|
||||
|
||||
// handling up/down/escape/right arrow/left arrow requires results to be visible
|
||||
// handling enter requires that AND a result to be selected
|
||||
if ((/27$|38$|33$|34$/.test(e.keyCode) && $ctr.is(':visible')) ||
|
||||
(/13$|40$/.test(e.keyCode)) || !o.allowInput) {
|
||||
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
if (e.stopPropagation) e.stopPropagation();
|
||||
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 38: // up arrow
|
||||
prevResult();
|
||||
break;
|
||||
case 40: // down arrow
|
||||
if ($ctr.is(':visible')) nextResult();
|
||||
else flexboxDelay(true);
|
||||
break;
|
||||
case 13: // enter
|
||||
if (getCurr()) selectCurr();
|
||||
else flexboxDelay(true);
|
||||
break;
|
||||
case 27: // escape
|
||||
hideResults();
|
||||
break;
|
||||
case 34: // page down
|
||||
if (!retrievingRemoteData) {
|
||||
if (o.paging) $('#' + $div.attr('id') + 'n').click();
|
||||
else nextPage();
|
||||
}
|
||||
break;
|
||||
case 33: // page up
|
||||
if (!retrievingRemoteData) {
|
||||
if (o.paging) $('#' + $div.attr('id') + 'p').click();
|
||||
else prevPage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!o.allowInput) { return; }
|
||||
}
|
||||
} else if (!esc && !tab && !tabWithModifiers) { // skip esc and tab key and any modifiers
|
||||
flexboxDelay(false, backspace);
|
||||
}
|
||||
}
|
||||
|
||||
function flexboxDelay(simulateArrowClick, increaseDelay) {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
var delay = increaseDelay ? o.queryDelay * 5 : o.queryDelay;
|
||||
timeout = setTimeout(function() { flexbox(1, simulateArrowClick, ''); }, delay);
|
||||
}
|
||||
|
||||
function flexbox(p, arrowOrPagingClicked, prevQuery) {
|
||||
if (arrowOrPagingClicked) prevQuery = '';
|
||||
var q = prevQuery && prevQuery.length > 0 ? prevQuery : $.trim($input.val());
|
||||
|
||||
if (q.length >= o.minChars || arrowOrPagingClicked) {
|
||||
// If we are getting data from the server, set the height of the content box so it doesn't shrink when navigating between pages, due to the $content.html('') below...
|
||||
if ($content.outerHeight() > 0)
|
||||
$content.css('height', $content.outerHeight());
|
||||
$content.html('').attr('scrollTop', 0);
|
||||
|
||||
var cached = checkCache(q, p);
|
||||
if (cached) {
|
||||
$content.css('height', 'auto');
|
||||
displayItems(cached.data, q);
|
||||
showPaging(p, cached.t);
|
||||
}
|
||||
else {
|
||||
var params = { q: q, p: p, s: pageSize, contentType: 'application/json; charset=utf-8' };
|
||||
var callback = function(data, overrideQuery) {
|
||||
if (overrideQuery === true) q = overrideQuery; // must compare to boolean because by default, the string value "success" is passed when the jQuery $.getJSON method's callback is called
|
||||
var totalResults = parseInt(data[o.totalProperty]);
|
||||
|
||||
// Handle client-side paging, if any paging configuration options were specified
|
||||
if (isNaN(totalResults) && o.paging) {
|
||||
if (o.maxCacheBytes <= 0) alert('The "maxCacheBytes" configuration option must be greater\nthan zero when implementing client-side paging.');
|
||||
totalResults = data[o.resultsProperty].length;
|
||||
|
||||
var pages = totalResults / pageSize;
|
||||
if (totalResults % pageSize > 0) pages = parseInt(++pages);
|
||||
|
||||
for (var i = 1; i <= pages; i++) {
|
||||
var pageData = {};
|
||||
pageData[o.totalProperty] = totalResults;
|
||||
pageData[o.resultsProperty] = data[o.resultsProperty].splice(0, pageSize);
|
||||
if (i === 1) totalSize = displayItems(pageData, q);
|
||||
updateCache(q, i, pageSize, totalResults, pageData, totalSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var totalSize = displayItems(data, q);
|
||||
updateCache(q, p, pageSize, totalResults, data, totalSize);
|
||||
}
|
||||
showPaging(p, totalResults);
|
||||
$content.css('height', 'auto');
|
||||
retrievingRemoteData = false;
|
||||
};
|
||||
if (typeof (o.source) === 'object') {
|
||||
if (o.allowInput) callback(filter(o.source, params));
|
||||
else callback(o.source);
|
||||
}
|
||||
else {
|
||||
retrievingRemoteData = true;
|
||||
if (o.method.toUpperCase() == 'POST') $.post(o.source, params, callback, 'json');
|
||||
else $.getJSON(o.source, params, callback);
|
||||
}
|
||||
}
|
||||
} else
|
||||
hideResults();
|
||||
}
|
||||
|
||||
function filter(data, params) {
|
||||
var filtered = {};
|
||||
filtered[o.resultsProperty] = [];
|
||||
filtered[o.totalProperty] = 0;
|
||||
var index = 0;
|
||||
|
||||
for (var i=0; i < data[o.resultsProperty].length; i++) {
|
||||
var indexOfMatch = data[o.resultsProperty][i][o.displayValue].toLowerCase().indexOf(params.q.toLowerCase());
|
||||
if ((o.matchAny && indexOfMatch !== -1) || (!o.matchAny && indexOfMatch === 0)) {
|
||||
filtered[o.resultsProperty][index++] = data[o.resultsProperty][i];
|
||||
filtered[o.totalProperty] += 1;
|
||||
}
|
||||
}
|
||||
if (o.paging) {
|
||||
var start = (params.p - 1) * params.s;
|
||||
var howMany = (start + params.s) > filtered[o.totalProperty] ? filtered[o.totalProperty] - start : params.s;
|
||||
filtered[o.resultsProperty] = filtered[o.resultsProperty].splice(start, howMany);
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
function showPaging(p, totalResults) {
|
||||
$paging.html('').removeClass(o.paging.cssClass); // clear out for threshold scenarios
|
||||
if (o.showResults && o.paging && totalResults > pageSize) {
|
||||
var pages = totalResults / pageSize;
|
||||
if (totalResults % pageSize > 0) pages = parseInt(++pages);
|
||||
outputPagingLinks(pages, p, totalResults);
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyPress(e, page, totalPages) {
|
||||
if (/^13$|^39$|^37$/.test(e.keyCode)) {
|
||||
if (e.preventDefault)
|
||||
e.preventDefault();
|
||||
if (e.stopPropagation)
|
||||
e.stopPropagation();
|
||||
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 13: // Enter
|
||||
if (/^\d+$/.test(page) && page > 0 && page <= totalPages)
|
||||
flexbox(page, true);
|
||||
else
|
||||
alert('Please enter a page number between 1 and ' + totalPages);
|
||||
// TODO: make this alert a function call, and a customizable parameter
|
||||
break;
|
||||
case 39: // right arrow
|
||||
$('#' + $div.attr('id') + 'n').click();
|
||||
break;
|
||||
case 37: // left arrow
|
||||
$('#' + $div.attr('id') + 'p').click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handlePagingClick(e) {
|
||||
flexbox(parseInt($(this).attr('page')), true, $input.attr('pq')); // pq == previous query
|
||||
return false;
|
||||
}
|
||||
|
||||
function outputPagingLinks(totalPages, currentPage, totalResults) {
|
||||
// TODO: make these configurable images
|
||||
var first = '<<',
|
||||
prev = '<',
|
||||
next = '>',
|
||||
last = '>>',
|
||||
more = '...';
|
||||
|
||||
$paging.addClass(o.paging.cssClass);
|
||||
|
||||
// set up our base page link element
|
||||
var $link = $('<a/>')
|
||||
.attr('href', '#')
|
||||
.addClass('page')
|
||||
.click(handlePagingClick),
|
||||
$span = $('<span></span>').addClass('page'),
|
||||
divId = $div.attr('id');
|
||||
|
||||
// show first page
|
||||
if (currentPage > 1) {
|
||||
$link.clone(true).attr('id', divId + 'f').attr('page', 1).html(first).appendTo($paging);
|
||||
$link.clone(true).attr('id', divId + 'p').attr('page', currentPage - 1).html(prev).appendTo($paging);
|
||||
}
|
||||
else {
|
||||
$span.clone(true).html(first).appendTo($paging);
|
||||
$span.clone(true).html(prev).appendTo($paging);
|
||||
}
|
||||
|
||||
if (o.paging.style === 'links') {
|
||||
var maxPageLinks = o.paging.maxPageLinks;
|
||||
// show page numbers
|
||||
if (totalPages <= maxPageLinks) {
|
||||
for (var i = 1; i <= totalPages; i++) {
|
||||
if (i === currentPage) {
|
||||
$span.clone(true).html(currentPage).appendTo($paging);
|
||||
}
|
||||
else {
|
||||
$link.clone(true).attr('page', i).html(i).appendTo($paging);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((currentPage + parseInt(maxPageLinks / 2)) > totalPages) {
|
||||
startPage = totalPages - maxPageLinks + 1;
|
||||
}
|
||||
else {
|
||||
startPage = currentPage - parseInt(maxPageLinks / 2);
|
||||
}
|
||||
|
||||
if (startPage > 1) {
|
||||
$link.clone(true).attr('page', startPage - 1).html(more).appendTo($paging);
|
||||
}
|
||||
else {
|
||||
startPage = 1;
|
||||
}
|
||||
|
||||
for (var i = startPage; i < startPage + maxPageLinks; i++) {
|
||||
if (i === currentPage) {
|
||||
$span.clone(true).html(i).appendTo($paging);
|
||||
}
|
||||
else {
|
||||
$link.clone(true).attr('page', i).html(i).appendTo($paging);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalPages > (startPage + maxPageLinks)) {
|
||||
$link.clone(true).attr('page', i).html(more).appendTo($paging);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (o.paging.style === 'input') {
|
||||
var $pagingBox = $('<input/>')
|
||||
.addClass('box')
|
||||
.click(function(e) {
|
||||
this.select();
|
||||
})
|
||||
.keypress(function(e) {
|
||||
return handleKeyPress(e, this.value, totalPages);
|
||||
})
|
||||
.val(currentPage)
|
||||
.appendTo($paging);
|
||||
}
|
||||
|
||||
if (currentPage < totalPages) {
|
||||
$link.clone(true).attr('id', divId + 'n').attr('page', +currentPage + 1).html(next).appendTo($paging);
|
||||
$link.clone(true).attr('id', divId + 'l').attr('page', totalPages).html(last).appendTo($paging);
|
||||
}
|
||||
else {
|
||||
$span.clone(true).html(next).appendTo($paging);
|
||||
$span.clone(true).html(last).appendTo($paging);
|
||||
}
|
||||
var startingResult = (currentPage - 1) * pageSize + 1;
|
||||
var endingResult = (startingResult > (totalResults - pageSize)) ? totalResults : startingResult + pageSize - 1;
|
||||
|
||||
if (o.paging.showSummary) {
|
||||
var summaryData = {
|
||||
"start": startingResult,
|
||||
"end": endingResult,
|
||||
"total": totalResults,
|
||||
"page": currentPage,
|
||||
"pages": totalPages
|
||||
};
|
||||
var html = o.paging.summaryTemplate.applyTemplate(summaryData);
|
||||
$('<br/>').appendTo($paging);
|
||||
$('<span></span>')
|
||||
.addClass(o.paging.summaryClass)
|
||||
.html(html)
|
||||
.appendTo($paging);
|
||||
}
|
||||
}
|
||||
|
||||
function checkCache(q, p) {
|
||||
var key = q + delim + p; // use null character as delimiter
|
||||
if (cacheData[key]) {
|
||||
for (var i = 0; i < cache.length; i++) { // TODO: is it possible to not loop here?
|
||||
if (cache[i] === key) {
|
||||
// pull out the matching element (splice), and add it to the beginning of the array (unshift)
|
||||
cache.unshift(cache.splice(i, 1)[0]);
|
||||
return cacheData[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateCache(q, p, s, t, data, size) {
|
||||
if (o.maxCacheBytes > 0) {
|
||||
while (cache.length && (cacheSize + size > o.maxCacheBytes)) {
|
||||
var cached = cache.pop();
|
||||
cacheSize -= cached.size;
|
||||
}
|
||||
var key = q + delim + p; // use null character as delimiter
|
||||
cacheData[key] = {
|
||||
q: q,
|
||||
p: p,
|
||||
s: s,
|
||||
t: t,
|
||||
size: size,
|
||||
data: data
|
||||
}; // add the data to the cache at the hash key location
|
||||
cache.push(key); // add the key to the MRU list
|
||||
cacheSize += size;
|
||||
}
|
||||
}
|
||||
|
||||
function displayItems(d, q) {
|
||||
var totalSize = 0, itemCount = 0;
|
||||
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
$hdn.val($input.val());
|
||||
if (parseInt(d[o.totalProperty]) === 0 && o.noResultsText && o.noResultsText.length > 0) {
|
||||
$content.addClass(o.noResultsClass).html(o.noResultsText);
|
||||
$ctr.show();
|
||||
return;
|
||||
} else $content.removeClass(o.noResultsClass);
|
||||
|
||||
for (var i = 0; i < d[o.resultsProperty].length; i++) {
|
||||
var data = d[o.resultsProperty][i],
|
||||
result = o.resultTemplate.applyTemplate(data),
|
||||
exactMatch = q === result,
|
||||
selectedMatch = false,
|
||||
hasHtmlTags = false,
|
||||
match = data[o.displayValue];
|
||||
|
||||
if (!exactMatch && o.highlightMatches && q !== '') {
|
||||
var pattern = q,
|
||||
highlightStart = match.toLowerCase().indexOf(q.toLowerCase()),
|
||||
replaceString = '<span class="' + o.matchClass + '">' + match.substr(highlightStart,q.length) + '</span>';
|
||||
if (result.match('<(.|\n)*?>')) { // see if the content contains html tags
|
||||
hasHtmlTags = true;
|
||||
pattern = '(>)([^<]*?)(' + q + ')((.|\n)*?)(<)'; // TODO: look for a better way
|
||||
replaceString = '$1$2<span class="' + o.matchClass + '">$3</span>$4$6';
|
||||
}
|
||||
result = result.replace(new RegExp(pattern.replace("[", "\\["), o.highlightMatchesRegExModifier), replaceString);
|
||||
}
|
||||
|
||||
// write the value of the first match to the input box, and select the remainder,
|
||||
// but only if autoCompleteFirstMatch is set, and there are no html tags in the response
|
||||
if (o.autoCompleteFirstMatch && !hasHtmlTags && i === 0) {
|
||||
if (q.length > 0 && match.toLowerCase().indexOf(q.toLowerCase()) === 0) {
|
||||
$input.attr('pq', q); // pq == previous query
|
||||
$hdn.val(data[o.hiddenValue]);
|
||||
$input.val(data[o.displayValue]);
|
||||
selectedMatch = selectRange(q.length, $input.val().length);
|
||||
}
|
||||
}
|
||||
|
||||
if (!o.showResults) return;
|
||||
|
||||
$row = $('<div></div>')
|
||||
.attr('id', data[o.hiddenValue])
|
||||
.attr('val', data[o.displayValue])
|
||||
.addClass('row')
|
||||
.html(result)
|
||||
.appendTo($content);
|
||||
|
||||
if (exactMatch || (++itemCount == 1 && o.selectFirstMatch) || selectedMatch) {
|
||||
$row.addClass(o.selectClass);
|
||||
}
|
||||
totalSize += result.length;
|
||||
}
|
||||
|
||||
if (totalSize === 0) {
|
||||
hideResults();
|
||||
return;
|
||||
}
|
||||
|
||||
$ctr.parent().css('z-index', 11000);
|
||||
$ctr.show();
|
||||
|
||||
$content
|
||||
.children('div')
|
||||
.mouseover(function() {
|
||||
$content.children('div').removeClass(o.selectClass);
|
||||
$(this).addClass(o.selectClass);
|
||||
})
|
||||
.mouseup(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
selectCurr();
|
||||
});
|
||||
|
||||
if (o.maxVisibleRows > 0) {
|
||||
var maxHeight = $row.outerHeight() * o.maxVisibleRows;
|
||||
$content.css('max-height', maxHeight);
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
function selectRange(s, l) {
|
||||
var tb = $input[0];
|
||||
if (tb.createTextRange) {
|
||||
var r = tb.createTextRange();
|
||||
r.moveStart('character', s);
|
||||
r.moveEnd('character', l - tb.value.length);
|
||||
r.select();
|
||||
} else if (tb.setSelectionRange) {
|
||||
tb.setSelectionRange(s, l);
|
||||
}
|
||||
tb.focus();
|
||||
return true;
|
||||
}
|
||||
|
||||
String.prototype.applyTemplate = function(d) {
|
||||
try {
|
||||
if (d === '') return this;
|
||||
return this.replace(/{([^{}]*)}/g,
|
||||
function(a, b) {
|
||||
var r;
|
||||
if (b.indexOf('.') !== -1) { // handle dot notation in {}, such as {Thumbnail.Url}
|
||||
var ary = b.split('.');
|
||||
var obj = d;
|
||||
for (var i = 0; i < ary.length; i++)
|
||||
obj = obj[ary[i]];
|
||||
r = obj;
|
||||
}
|
||||
else
|
||||
r = d[b];
|
||||
if (typeof r === 'string' || typeof r === 'number') return r; else throw (a);
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
alert('Invalid JSON property ' + ex + ' found when trying to apply resultTemplate or paging.summaryTemplate.\nPlease check your spelling and try again.');
|
||||
}
|
||||
};
|
||||
|
||||
function hideResults() {
|
||||
$input.data('active', false); // for input blur
|
||||
$div.css('z-index', 0);
|
||||
$ctr.hide();
|
||||
}
|
||||
|
||||
function getCurr() {
|
||||
if (!$ctr.is(':visible'))
|
||||
return false;
|
||||
|
||||
var $curr = $content.children('div.' + o.selectClass);
|
||||
|
||||
if (!$curr.length)
|
||||
$curr = false;
|
||||
|
||||
return $curr;
|
||||
}
|
||||
|
||||
function selectCurr() {
|
||||
$curr = getCurr();
|
||||
|
||||
if ($curr) {
|
||||
$hdn.val($curr.attr('id'));
|
||||
$input.val($curr.attr('val')).focus();
|
||||
hideResults();
|
||||
|
||||
if (o.onSelect) {
|
||||
o.onSelect.apply($input[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function supportsGetBoxObjectFor() {
|
||||
try {
|
||||
document.getBoxObjectFor(document.body);
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function supportsGetBoundingClientRect() {
|
||||
try {
|
||||
document.body.getBoundingClientRect();
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
$curr = getCurr();
|
||||
|
||||
if ($curr && $curr.next().length > 0) {
|
||||
$curr.removeClass(o.selectClass);
|
||||
|
||||
for (var i = 0; i < o.maxVisibleRows; i++) {
|
||||
if ($curr.next().length > 0) {
|
||||
$curr = $curr.next();
|
||||
}
|
||||
}
|
||||
|
||||
$curr.addClass(o.selectClass);
|
||||
var scrollPos = $content.attr('scrollTop');
|
||||
$content.attr('scrollTop', scrollPos + $content.height());
|
||||
}
|
||||
else if (!$curr)
|
||||
$content.children('div:first-child').addClass(o.selectClass);
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
$curr = getCurr();
|
||||
|
||||
if ($curr && $curr.prev().length > 0) {
|
||||
$curr.removeClass(o.selectClass);
|
||||
|
||||
for (var i = 0; i < o.maxVisibleRows; i++) {
|
||||
if ($curr.prev().length > 0) {
|
||||
$curr = $curr.prev();
|
||||
}
|
||||
}
|
||||
|
||||
$curr.addClass(o.selectClass);
|
||||
var scrollPos = $content.attr('scrollTop');
|
||||
$content.attr('scrollTop', scrollPos - $content.height());
|
||||
}
|
||||
else if (!$curr)
|
||||
$content.children('div:last-child').addClass(o.selectClass);
|
||||
}
|
||||
|
||||
function nextResult() {
|
||||
$curr = getCurr();
|
||||
|
||||
if ($curr && $curr.next().length > 0) {
|
||||
$curr.removeClass(o.selectClass).next().addClass(o.selectClass);
|
||||
var scrollPos = $content.attr('scrollTop'),
|
||||
curr = $curr[0], parentBottom, bottom, height;
|
||||
if (supportsGetBoxObjectFor()) {
|
||||
parentBottom = document.getBoxObjectFor($content[0]).y + $content.attr('offsetHeight');
|
||||
bottom = document.getBoxObjectFor(curr).y + $curr.attr('offsetHeight');
|
||||
height = document.getBoxObjectFor(curr).height;
|
||||
}
|
||||
else if (supportsGetBoundingClientRect()) {
|
||||
parentBottom = $content[0].getBoundingClientRect().bottom;
|
||||
var rect = curr.getBoundingClientRect();
|
||||
bottom = rect.bottom;
|
||||
height = bottom - rect.top;
|
||||
}
|
||||
if (bottom >= parentBottom)
|
||||
$content.attr('scrollTop', scrollPos + height);
|
||||
}
|
||||
else if (!$curr)
|
||||
$content.children('div:first-child').addClass(o.selectClass);
|
||||
}
|
||||
|
||||
function prevResult() {
|
||||
$curr = getCurr();
|
||||
|
||||
if ($curr && $curr.prev().length > 0) {
|
||||
$curr.removeClass(o.selectClass).prev().addClass(o.selectClass);
|
||||
var scrollPos = $content.attr('scrollTop'),
|
||||
curr = $curr[0],
|
||||
parent = $curr.parent()[0],
|
||||
parentTop, top, height;
|
||||
if (supportsGetBoxObjectFor()) {
|
||||
height = document.getBoxObjectFor(curr).height;
|
||||
parentTop = document.getBoxObjectFor($content[0]).y - (height * 2); // TODO: this is not working when i add another control...
|
||||
top = document.getBoxObjectFor(curr).y - document.getBoxObjectFor($content[0]).y;
|
||||
}
|
||||
else if (supportsGetBoundingClientRect()) {
|
||||
parentTop = parent.getBoundingClientRect().top;
|
||||
var rect = curr.getBoundingClientRect();
|
||||
top = rect.top;
|
||||
height = rect.bottom - top;
|
||||
}
|
||||
if (top <= parentTop)
|
||||
$content.attr('scrollTop', scrollPos - height);
|
||||
}
|
||||
else if (!$curr)
|
||||
$content.children('div:last-child').addClass(o.selectClass);
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.flexbox = function(source, options) {
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
try {
|
||||
var defaults = $.fn.flexbox.defaults;
|
||||
var o = $.extend({}, defaults, options);
|
||||
|
||||
for (var prop in o) {
|
||||
if (defaults[prop] === undefined) throw ('Invalid option specified: ' + prop + '\nPlease check your spelling and try again.');
|
||||
}
|
||||
o.source = source;
|
||||
|
||||
if (options) {
|
||||
o.paging = (options.paging || options.paging == null) ? $.extend({}, defaults.paging, options.paging) : false;
|
||||
|
||||
for (var prop in o.paging) {
|
||||
if (defaults.paging[prop] === undefined) throw ('Invalid option specified: ' + prop + '\nPlease check your spelling and try again.');
|
||||
}
|
||||
|
||||
if (options.displayValue && !options.hiddenValue) {
|
||||
o.hiddenValue = options.displayValue;
|
||||
}
|
||||
}
|
||||
|
||||
this.each(function() {
|
||||
new $.flexbox(this, o);
|
||||
});
|
||||
|
||||
return this;
|
||||
} catch (ex) {
|
||||
if (typeof ex === 'object') alert(ex.message); else alert(ex);
|
||||
}
|
||||
};
|
||||
|
||||
// plugin defaults - added as a property on our plugin function so they can be set independently
|
||||
$.fn.flexbox.defaults = {
|
||||
method: 'GET', // One of 'GET' or 'POST'
|
||||
queryDelay: 100, // num of milliseconds before query is run.
|
||||
allowInput: true, // set to false to disallow the user from typing in queries
|
||||
containerClass: 'ffb',
|
||||
contentClass: 'content',
|
||||
selectClass: 'ffb-sel',
|
||||
inputClass: 'ffb-input',
|
||||
arrowClass: 'ffb-arrow',
|
||||
matchClass: 'ffb-match',
|
||||
noResultsText: 'No matching results', // text to show when no results match the query
|
||||
noResultsClass: 'ffb-no-results', // class to apply to noResultsText
|
||||
showResults: true, // whether to show results at all, or just typeahead
|
||||
selectFirstMatch: true, // whether to highlight the first matching value
|
||||
autoCompleteFirstMatch: false, // whether to complete the first matching value in the input box
|
||||
highlightMatches: true, // whether all matches within the string should be highlighted with matchClass
|
||||
highlightMatchesRegExModifier: 'i', // 'i' for case-insensitive, 'g' for global (all occurrences), or combine
|
||||
matchAny: true, // for client-side filtering ONLY, match any occurrence of the search term in the result (e.g. "ar" would find "area" and "cart")
|
||||
minChars: 1, // the minimum number of characters the user must enter before a search is executed
|
||||
showArrow: true, // set to false to simulate google suggest
|
||||
arrowQuery: '', // the query to run when the arrow is clicked
|
||||
onSelect: false, // function to run when a result is selected
|
||||
maxCacheBytes: 32768, // in bytes, 0 means caching is disabled
|
||||
resultTemplate: '{name}', // html template for each row (put json properties in curly braces)
|
||||
displayValue: 'name', // json element whose value is displayed on select
|
||||
hiddenValue: 'id', // json element whose value is submitted when form is submitted
|
||||
initialValue: '', // what should the value of the input field be when the form is loaded?
|
||||
initialId: '', // what should the value of the hidden field be when the form is loaded?
|
||||
watermark: '', // text that appears when flexbox is loaded, if no initialValue is specified. style with css class '.ffb-input.watermark'
|
||||
width: 200, // total width of flexbox. auto-adjusts based on showArrow value
|
||||
resultsProperty: 'results', // json property in response that references array of results
|
||||
totalProperty: 'total', // json property in response that references the total results (for paging)
|
||||
maxVisibleRows: 0, // default is 0, which means it is ignored. use either this, or paging.pageSize
|
||||
paging: {
|
||||
style: 'input', // or 'links'
|
||||
cssClass: 'paging', // prefix with containerClass (e.g. .ffb .paging)
|
||||
pageSize: 10, // acts as a threshold. if <= pageSize results, paging doesn't appear
|
||||
maxPageLinks: 5, // used only if style is 'links'
|
||||
showSummary: true, // whether to show 'displaying 1-10 of 200 results' text
|
||||
summaryClass: 'summary', // class for 'displaying 1-10 of 200 results', prefix with containerClass
|
||||
summaryTemplate: 'Displaying {start}-{end} of {total} results' // can use {page} and {pages} as well
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.setValue = function(val) {
|
||||
var id = '#' + this.attr('id');
|
||||
$(id + '_hidden,' + id + '_input').val(val).removeClass('watermark');
|
||||
};
|
||||
})(jQuery);
|
10
src/plugins/webstuff/javascript/jquery.flexbox.min.js
vendored
Normal file
10
src/plugins/webstuff/javascript/jquery.flexbox.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -228,6 +228,7 @@ class DbDjango(DbWriteBase, DbReadBase):
|
||||
self.dji.add_tag_detail(obj.serialize())
|
||||
self.use_import_cache = False
|
||||
self.import_cache = {}
|
||||
self.dji.update_publics()
|
||||
|
||||
def transaction_commit(self, txn):
|
||||
pass
|
||||
@ -236,8 +237,8 @@ class DbDjango(DbWriteBase, DbReadBase):
|
||||
pass
|
||||
|
||||
def request_rebuild(self):
|
||||
#self.dji.rebuild_caches()
|
||||
pass
|
||||
# caches are ok, but let's compute public's
|
||||
self.dji.update_publics()
|
||||
|
||||
def get_undodb(self):
|
||||
return None
|
||||
|
@ -228,8 +228,8 @@ CREATE TABLE "auth_user" (
|
||||
"last_login" datetime NOT NULL,
|
||||
"date_joined" datetime NOT NULL
|
||||
);
|
||||
INSERT INTO "auth_user" VALUES(1,'admin','','','bugs@gramps-project.org','sha1$0aac2$c94ddc40e2dfd41bd5453230a3e53a6a925572b2',1,1,1,'2012-07-28 09:32:02.407417','2012-07-28 09:32:02.407417');
|
||||
INSERT INTO "auth_user" VALUES(2,'admin1','','','bugs@gramps-project.org','sha1$887ff$3829f603618766d49287f3b98b036d6b06c3f440',1,1,1,'2012-07-28 09:32:07.068033','2012-07-28 09:32:07.068033');
|
||||
INSERT INTO "auth_user" VALUES(1,'admin','','','bugs@gramps-project.org','sha1$248cf$71082f5ec314e2706d1cc9e44a0d63b953ba1d08',1,1,1,'2012-07-31 07:58:28.096063','2012-07-31 07:58:28.096063');
|
||||
INSERT INTO "auth_user" VALUES(2,'admin1','','','bugs@gramps-project.org','sha1$bd368$2e83f9d34578f66402e62b698950adae05f4d6bf',1,1,1,'2012-07-31 07:58:37.492571','2012-07-31 07:58:37.492571');
|
||||
CREATE TABLE "auth_message" (
|
||||
"id" integer NOT NULL PRIMARY KEY,
|
||||
"user_id" integer NOT NULL REFERENCES "auth_user" ("id"),
|
||||
@ -648,7 +648,7 @@ CREATE TABLE "grampsdb_config" (
|
||||
);
|
||||
INSERT INTO "grampsdb_config" VALUES(1,'sitename','site name of family tree','str','Gramps-Connect');
|
||||
INSERT INTO "grampsdb_config" VALUES(2,'db_version','database scheme version','str','0.6.1');
|
||||
INSERT INTO "grampsdb_config" VALUES(3,'db_created','database creation date/time','str','2012-07-28 09:30');
|
||||
INSERT INTO "grampsdb_config" VALUES(3,'db_created','database creation date/time','str','2012-07-31 07:56');
|
||||
INSERT INTO "grampsdb_config" VALUES(4,'htmlview.url-handler',NULL,'bool','False');
|
||||
INSERT INTO "grampsdb_config" VALUES(5,'htmlview.start-url',NULL,'str','http://gramps-project.org');
|
||||
INSERT INTO "grampsdb_config" VALUES(6,'paths.recent-export-dir',NULL,'str','');
|
||||
@ -863,6 +863,7 @@ CREATE TABLE "grampsdb_person" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"gender_type_id" integer NOT NULL REFERENCES "grampsdb_gendertype" ("id"),
|
||||
"probably_alive" bool NOT NULL,
|
||||
@ -885,6 +886,7 @@ CREATE TABLE "grampsdb_family" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"father_id" integer REFERENCES "grampsdb_person" ("id"),
|
||||
"mother_id" integer REFERENCES "grampsdb_person" ("id"),
|
||||
@ -912,6 +914,7 @@ CREATE TABLE "grampsdb_citation" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"confidence" integer,
|
||||
"page" varchar(50),
|
||||
@ -925,6 +928,7 @@ CREATE TABLE "grampsdb_source" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"title" varchar(50),
|
||||
"author" varchar(50),
|
||||
@ -953,6 +957,7 @@ CREATE TABLE "grampsdb_event" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"event_type_id" integer NOT NULL REFERENCES "grampsdb_eventtype" ("id"),
|
||||
"description" varchar(50) NOT NULL,
|
||||
@ -966,6 +971,7 @@ CREATE TABLE "grampsdb_repository" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"repository_type_id" integer NOT NULL REFERENCES "grampsdb_repositorytype" ("id"),
|
||||
"name" text NOT NULL
|
||||
@ -978,6 +984,7 @@ CREATE TABLE "grampsdb_place" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"title" text NOT NULL,
|
||||
"long" text NOT NULL,
|
||||
@ -1011,6 +1018,7 @@ CREATE TABLE "grampsdb_media" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"path" text NOT NULL,
|
||||
"mime" text,
|
||||
@ -1030,6 +1038,7 @@ CREATE TABLE "grampsdb_note" (
|
||||
"last_changed" datetime,
|
||||
"last_changed_by" text,
|
||||
"private" bool NOT NULL,
|
||||
"public" bool NOT NULL,
|
||||
"cache" text,
|
||||
"note_type_id" integer NOT NULL REFERENCES "grampsdb_notetype" ("id"),
|
||||
"text" text NOT NULL,
|
||||
@ -1120,13 +1129,15 @@ CREATE TABLE "grampsdb_sourcedatamap" (
|
||||
"id" integer NOT NULL PRIMARY KEY,
|
||||
"key" varchar(80) NOT NULL,
|
||||
"value" varchar(80) NOT NULL,
|
||||
"source_id" integer NOT NULL REFERENCES "grampsdb_source" ("id")
|
||||
"source_id" integer NOT NULL REFERENCES "grampsdb_source" ("id"),
|
||||
"order" integer unsigned NOT NULL
|
||||
);
|
||||
CREATE TABLE "grampsdb_citationdatamap" (
|
||||
"id" integer NOT NULL PRIMARY KEY,
|
||||
"key" varchar(80) NOT NULL,
|
||||
"value" varchar(80) NOT NULL,
|
||||
"citation_id" integer NOT NULL REFERENCES "grampsdb_citation" ("id")
|
||||
"citation_id" integer NOT NULL REFERENCES "grampsdb_citation" ("id"),
|
||||
"order" integer unsigned NOT NULL
|
||||
);
|
||||
CREATE TABLE "grampsdb_address" (
|
||||
"id" integer NOT NULL PRIMARY KEY,
|
||||
|
70135
src/webapp/example.sql
70135
src/webapp/example.sql
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@
|
||||
from django import forms
|
||||
from django.forms.models import inlineformset_factory
|
||||
from django.forms.models import BaseModelFormSet
|
||||
from django.forms.widgets import TextInput
|
||||
from django.forms.widgets import TextInput, HiddenInput
|
||||
|
||||
# Gramps Modules:
|
||||
from webapp.grampsdb.models import *
|
||||
@ -132,22 +132,14 @@ class SurnameForm(forms.ModelForm):
|
||||
class FamilyForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Family
|
||||
exclude = ["handle", "cache"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FamilyForm, self).__init__(*args, **kwargs)
|
||||
self.fields['father'].queryset = Person.objects.filter(
|
||||
gender_type=get_type_from_name(GenderType, "Male")) \
|
||||
.order_by("name__surname__surname", "name__first_name")
|
||||
self.fields['mother'].queryset = Person.objects.filter(
|
||||
gender_type=get_type_from_name(GenderType, "Female")) \
|
||||
.order_by("name__surname__surname", "name__first_name")
|
||||
exclude = ["handle", "cache", "mother", "father"]
|
||||
|
||||
class EventForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Event
|
||||
exclude = ["handle", "sortval", "month1", "year1", "day1",
|
||||
"newyear", "calendar", "modifier", "quality", "cache"]
|
||||
"newyear", "calendar", "modifier", "quality", "cache",
|
||||
"place"]
|
||||
|
||||
def clean(self):
|
||||
from webapp.utils import dp
|
||||
|
@ -448,6 +448,7 @@ class PrimaryObject(models.Model):
|
||||
last_changed_by = models.TextField(blank=True, null=True)
|
||||
|
||||
private = models.BooleanField('private')
|
||||
public = models.BooleanField('public', default=True)
|
||||
#attributes = models.ManyToManyField("Attribute", blank=True, null=True)
|
||||
cache = models.TextField(blank=True, null=True)
|
||||
|
||||
@ -513,6 +514,9 @@ class Person(PrimaryObject):
|
||||
def make_tag_list(self):
|
||||
return tuple()
|
||||
|
||||
def get_selection_string(self):
|
||||
return self.name_set.get(preferred=True).get_selection_string()
|
||||
|
||||
class Family(PrimaryObject):
|
||||
father = models.ForeignKey('Person', related_name="father_ref",
|
||||
null=True, blank=True)
|
||||
@ -609,6 +613,9 @@ class Place(PrimaryObject):
|
||||
lat = models.TextField(blank=True)
|
||||
#url_list = models.ManyToManyField('Url', null=True, blank=True)
|
||||
|
||||
def get_selection_string(self):
|
||||
return "%s [%s]" % (self.title, self.gramps_id)
|
||||
|
||||
def __unicode__(self):
|
||||
return str(self.title)
|
||||
|
||||
@ -719,6 +726,14 @@ class Name(DateObject, SecondaryObject):
|
||||
surname = "[No primary surname]"
|
||||
return "%s, %s" % (surname,
|
||||
self.first_name)
|
||||
|
||||
def get_selection_string(self):
|
||||
try:
|
||||
surname = self.surname_set.get(primary=True)
|
||||
except:
|
||||
surname = "[No primary surname]"
|
||||
return "%s, %s [%s]" % (surname, self.first_name, self.person.gramps_id)
|
||||
|
||||
@staticmethod
|
||||
def get_dummy():
|
||||
name = Name()
|
||||
@ -791,11 +806,13 @@ class SourceDatamap(models.Model):
|
||||
key = models.CharField(max_length=80, blank=True)
|
||||
value = models.CharField(max_length=80, blank=True)
|
||||
source = models.ForeignKey("Source")
|
||||
order = models.PositiveIntegerField()
|
||||
|
||||
class CitationDatamap(models.Model):
|
||||
key = models.CharField(max_length=80, blank=True)
|
||||
value = models.CharField(max_length=80, blank=True)
|
||||
citation = models.ForeignKey("Citation")
|
||||
order = models.PositiveIntegerField()
|
||||
|
||||
class Address(DateObject, SecondaryObject):
|
||||
#locations = models.ManyToManyField('Location', null=True)
|
||||
|
@ -186,6 +186,11 @@ def make_args(search, page):
|
||||
make_args.is_safe = True
|
||||
register.simple_tag(make_args)
|
||||
|
||||
def format_color(color):
|
||||
return color[0:3] + color[5:7] + color[9:11]
|
||||
format_color.is_safe = True
|
||||
register.filter("format_color", format_color)
|
||||
|
||||
def currentSection(view1, view2): # tview, menu
|
||||
if view1.strip().lower() in [view[1] for view in VIEWS] and view2 == "browse":
|
||||
return "class=CurrentSection"
|
||||
|
@ -47,6 +47,7 @@ from django.shortcuts import get_object_or_404, render_to_response, redirect
|
||||
from django.template import Context, RequestContext
|
||||
from django.db.models import Q
|
||||
from django.forms.models import modelformset_factory
|
||||
from django.utils import simplejson
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -60,7 +61,8 @@ from webapp.grampsdb.view import *
|
||||
from webapp.dbdjango import DbDjango
|
||||
import cli.user
|
||||
import gen.proxy
|
||||
from gen.const import VERSION
|
||||
from gen.const import VERSION_TUPLE
|
||||
from gen.utils.svn import get_svn_revision
|
||||
|
||||
# Menu: (<Nice name>, /<path>/, <Model> | None, Need authentication )
|
||||
MENU = [
|
||||
@ -95,7 +97,7 @@ def context_processor(request):
|
||||
else:
|
||||
context["css_theme"] = "Web_Mainz.css"
|
||||
# Other things for all environments:
|
||||
context["gramps_version"] = VERSION
|
||||
context["gramps_version"] = ".".join([str(v) for v in VERSION_TUPLE]) + " " + get_svn_revision()
|
||||
context["views"] = VIEWS
|
||||
context["menu"] = MENU
|
||||
context["None"] = None
|
||||
@ -582,7 +584,6 @@ def process_report(request, context, handle, act):
|
||||
context["tviews"] = _("Reports")
|
||||
|
||||
def build_string_query(field, value, exact=False, startswith=False, endswith=False):
|
||||
print field, value
|
||||
retval = None
|
||||
if exact:
|
||||
retval = Q(**{"%s" % field: value})
|
||||
@ -601,9 +602,10 @@ def build_person_query(request, search):
|
||||
"""
|
||||
protect = not request.user.is_authenticated()
|
||||
### Build the order:
|
||||
terms = ["surname", "given", "tag"]
|
||||
terms = ["surname", "given", "id", "tag", "public", "private"]
|
||||
if protect:
|
||||
# Do this to get the names sorted by private/alive
|
||||
# NOTE: names can be private
|
||||
query = Q(private=False) & Q(person__private=False)
|
||||
order = ["surname__surname", "private", "person__probably_alive",
|
||||
"first_name"]
|
||||
@ -612,6 +614,9 @@ def build_person_query(request, search):
|
||||
order = ["surname__surname", "first_name"]
|
||||
### Build the query:
|
||||
if search:
|
||||
if "[" in search: # "Surname, Given [I0002]" to match Flexbox and obj.get_select_string()
|
||||
search = search.replace("[", ", id=^")
|
||||
search = search.replace("]", "$")
|
||||
if "," in search or "=" in search:
|
||||
for term in [term.strip() for term in search.split(",")]:
|
||||
startswith = False
|
||||
@ -645,6 +650,9 @@ def build_person_query(request, search):
|
||||
elif field == "private":
|
||||
if not protect:
|
||||
query &= Q(person__private=boolean(value))
|
||||
elif field == "public":
|
||||
if not protect:
|
||||
query &= Q(person__public=boolean(value))
|
||||
elif field == "birth":
|
||||
if protect:
|
||||
query &= Q(person__birth__year1=safe_int(value)) & Q(person__probably_alive=False)
|
||||
@ -685,7 +693,8 @@ def build_family_query(request, search):
|
||||
Build and return a Django QuerySet and sort order for the Family
|
||||
table.
|
||||
"""
|
||||
terms = ["father", "mother", "id", "type", "surnames", "father.name.first_name", "mother.name.first_name", "tag"]
|
||||
terms = ["father", "mother", "id", "type", "surnames", "father.name.first_name",
|
||||
"mother.name.first_name", "tag", "public", "private"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = (Q(private=False) & Q(father__private=False) &
|
||||
@ -740,6 +749,10 @@ def build_family_query(request, search):
|
||||
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
|
||||
elif field == "tag":
|
||||
query &= build_string_query("tags__name", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
make_message(request, message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -759,7 +772,7 @@ def build_family_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_media_query(request, search):
|
||||
terms = ["id", "path", "description", "mime", "tag"]
|
||||
terms = ["id", "path", "description", "mime", "tag", "public", "private"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -801,6 +814,10 @@ def build_media_query(request, search):
|
||||
query &= build_string_query("mime", value, exact, startswith, endswith)
|
||||
elif field == "tag":
|
||||
query &= build_string_query("tags__name", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -819,7 +836,7 @@ def build_media_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_note_query(request, search):
|
||||
terms = ["id", "type", "text", "tag"]
|
||||
terms = ["id", "type", "text", "tag", "public", "private"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -859,6 +876,10 @@ def build_note_query(request, search):
|
||||
query &= build_string_query("text", value, exact, startswith, endswith)
|
||||
elif field == "tag":
|
||||
query &= build_string_query("tags__name", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -875,7 +896,7 @@ def build_note_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_place_query(request, search):
|
||||
terms = ["id", "title"]
|
||||
terms = ["title", "id", "public", "private"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -884,8 +905,11 @@ def build_place_query(request, search):
|
||||
query = Q()
|
||||
order = ["gramps_id"]
|
||||
if search:
|
||||
if "," in search or "=" in search:
|
||||
for term in [term.strip() for term in search.split(",")]:
|
||||
if "[" in search: # "Place [I0002]" to match Flexbox and obj.get_select_string()
|
||||
search = search.replace("[", "; id=^")
|
||||
search = search.replace("]", "$")
|
||||
if ";" in search or "=" in search:
|
||||
for term in [term.strip() for term in search.split(";")]:
|
||||
startswith = False
|
||||
endswith = False
|
||||
exact = False
|
||||
@ -911,6 +935,10 @@ def build_place_query(request, search):
|
||||
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
|
||||
elif field == "title":
|
||||
query &= build_string_query("title", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -925,7 +953,7 @@ def build_place_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_repository_query(request, search):
|
||||
terms = ["id", "name", "type"]
|
||||
terms = ["id", "name", "type", "public", "private"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -963,6 +991,10 @@ def build_repository_query(request, search):
|
||||
query &= build_string_query("name", value, exact, startswith, endswith)
|
||||
elif field == "type":
|
||||
query &= build_string_query("repository_type__name", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -981,7 +1013,7 @@ def build_repository_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_citation_query(request, search):
|
||||
terms = ["id"]
|
||||
terms = ["id", "private", "public"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -1015,6 +1047,10 @@ def build_citation_query(request, search):
|
||||
query &= build_string_query(field.replace(".", "__"), value, exact, startswith, endswith)
|
||||
elif field == "id":
|
||||
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -1027,7 +1063,7 @@ def build_citation_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_source_query(request, search):
|
||||
terms = ["id"]
|
||||
terms = ["id", "private", "public"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -1061,6 +1097,10 @@ def build_source_query(request, search):
|
||||
query &= build_string_query(field.replace(".", "__"), value, exact, startswith, endswith)
|
||||
elif field == "id":
|
||||
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
@ -1166,7 +1206,7 @@ def build_report_query(request, search):
|
||||
return query, order, terms
|
||||
|
||||
def build_event_query(request, search):
|
||||
terms = ["id", "type", "place", "description"]
|
||||
terms = ["id", "type", "place", "description", "private", "public"]
|
||||
protect = not request.user.is_authenticated()
|
||||
if protect:
|
||||
query = Q(private=False) # general privacy
|
||||
@ -1201,22 +1241,26 @@ def build_event_query(request, search):
|
||||
elif field == "id":
|
||||
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
|
||||
elif field == "description":
|
||||
query &= build_string_query("desc", value, exact, startswith, endswith)
|
||||
query &= build_string_query("description", value, exact, startswith, endswith)
|
||||
elif field == "type":
|
||||
query &= build_string_query("event_type__name", value, exact, startswith, endswith)
|
||||
elif field == "place":
|
||||
query &= build_string_query("place__title", value, exact, startswith, endswith)
|
||||
elif field == "private":
|
||||
query &= Q(private=boolean(value))
|
||||
elif field == "public":
|
||||
query &= Q(public=boolean(value))
|
||||
else:
|
||||
request.user.message_set.create(message="Invalid query field '%s'" % field)
|
||||
else: # no search fields, just raw search
|
||||
if protect:
|
||||
query &= (Q(gramps_id__icontains=search) |
|
||||
Q(desc__icontains=search) |
|
||||
Q(description__icontains=search) |
|
||||
Q(event_type__name__icontains=search) |
|
||||
Q(place__title__icontains=search))
|
||||
else:
|
||||
query &= (Q(gramps_id__icontains=search) |
|
||||
Q(desc__icontains=search) |
|
||||
Q(description__icontains=search) |
|
||||
Q(event_type__name__icontains=search) |
|
||||
Q(place__title__icontains=search))
|
||||
else: # no search
|
||||
@ -1314,13 +1358,14 @@ def process_list_item(request, view, handle, act, item, index):
|
||||
# /citation/872323636232635/down/attribute/2
|
||||
index = int(index)
|
||||
tab = {
|
||||
"eventref": "#tab-events",
|
||||
"citationref": "#tab-citations",
|
||||
"attribute": "#tab-attributes",
|
||||
"media": "#tab-media",
|
||||
"lds": "#tab-lds",
|
||||
"parentfamily": "#tab-references",
|
||||
"family": "#tab-references",
|
||||
"eventref": "#tab-events",
|
||||
"citationref": "#tab-citations",
|
||||
"repositoryref": "#tab-repositories",
|
||||
"attribute": "#tab-attributes",
|
||||
"media": "#tab-media",
|
||||
"lds": "#tab-lds",
|
||||
"parentfamily": "#tab-references",
|
||||
"family": "#tab-references",
|
||||
}
|
||||
if view == "person":
|
||||
obj = dji.Person.get(handle=handle)
|
||||
@ -1330,6 +1375,10 @@ def process_list_item(request, view, handle, act, item, index):
|
||||
obj = dji.Family.get(handle=handle)
|
||||
elif view == "citation":
|
||||
obj = dji.Citation.get(handle=handle)
|
||||
elif view == "source":
|
||||
obj = dji.Source.get(handle=handle)
|
||||
else:
|
||||
raise Exception("add '%s' to list" % view)
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
# Next, get reference
|
||||
if item == "eventref":
|
||||
@ -1338,10 +1387,15 @@ def process_list_item(request, view, handle, act, item, index):
|
||||
elif item == "citationref":
|
||||
refs = dji.CitationRef.filter(object_id=obj.id,
|
||||
object_type=obj_type).order_by("order")
|
||||
elif item == "repositoryref":
|
||||
refs = dji.RepositoryRef.filter(object_id=obj.id,
|
||||
object_type=obj_type).order_by("order")
|
||||
elif item == "parentfamily":
|
||||
refs = dji.PersonParentFamilyOrder.filter(person=obj).order_by("order")
|
||||
refs = dji.MyParentFamilies.filter(person=obj).order_by("order")
|
||||
elif item == "family":
|
||||
refs = dji.PersonFamilyOrder.filter(person=obj).order_by("order")
|
||||
refs = dji.MyFamilies.filter(person=obj).order_by("order")
|
||||
else:
|
||||
raise Exception("add '%s' to reference list" % item)
|
||||
# Next, perform action:
|
||||
if act == "remove":
|
||||
count = 1
|
||||
@ -1376,3 +1430,56 @@ def process_list_item(request, view, handle, act, item, index):
|
||||
count += 1
|
||||
dji.rebuild_cache(obj)
|
||||
return redirect("/%s/%s/%s" % (view, handle, tab[item]))
|
||||
|
||||
def process_json_request(request):
|
||||
"""
|
||||
Process an Ajax/Json query request.
|
||||
"""
|
||||
if not request.user.is_authenticated():
|
||||
response_data = {"results": [], "total": 0}
|
||||
return HttpResponse(simplejson.dumps(response_data), mimetype="application/json")
|
||||
field = request.GET.get("field", None)
|
||||
query = request.GET.get("q", "")
|
||||
page = int(request.GET.get("p", "1"))
|
||||
size = int(request.GET.get("s", "10"))
|
||||
if field == "mother":
|
||||
q, order, terms = build_person_query(request, query)
|
||||
q &= Q(person__gender_type__name="Female")
|
||||
matches = Name.objects.filter(q).order_by(*order)
|
||||
response_data = {"results": [], "total": len(matches)}
|
||||
for match in matches[(page - 1) * size:page * size]:
|
||||
response_data["results"].append(
|
||||
{"id": match.person.handle,
|
||||
"name": match.get_selection_string(),
|
||||
})
|
||||
elif field == "father":
|
||||
q, order, terms = build_person_query(request, query)
|
||||
q &= Q(person__gender_type__name="Male")
|
||||
matches = Name.objects.filter(q).order_by(*order)
|
||||
response_data = {"results": [], "total": len(matches)}
|
||||
for match in matches[(page - 1) * size:page * size]:
|
||||
response_data["results"].append(
|
||||
{"id": match.person.handle,
|
||||
"name": match.get_selection_string(),
|
||||
})
|
||||
elif field == "person":
|
||||
q, order, terms = build_person_query(request, query)
|
||||
matches = Name.objects.filter(q).order_by(*order)
|
||||
response_data = {"results": [], "total": len(matches)}
|
||||
for match in matches[(page - 1) * size:page * size]:
|
||||
response_data["results"].append(
|
||||
{"id": match.person.handle,
|
||||
"name": match.get_selection_string(),
|
||||
})
|
||||
elif field == "place":
|
||||
q, order, terms = build_place_query(request, query)
|
||||
matches = Place.objects.filter(q).order_by(*order)
|
||||
response_data = {"results": [], "total": len(matches)}
|
||||
for match in matches[(page - 1) * size:page * size]:
|
||||
response_data["results"].append(
|
||||
{"id": match.handle,
|
||||
"name": match.get_selection_string(),
|
||||
})
|
||||
else:
|
||||
raise Exception("""Invalid field: '%s'; Example: /json/?field=mother&q=Smith&p=1&size=10""" % field)
|
||||
return HttpResponse(simplejson.dumps(response_data), mimetype="application/json")
|
||||
|
@ -211,10 +211,10 @@ class DjangoInterface(object):
|
||||
return map(self.pack_name, names)
|
||||
|
||||
def get_source_datamap(self, source):
|
||||
return dict([map.key, map.value] for map in source.sourcedatamap_set.all())
|
||||
return dict([map.key, map.value] for map in source.sourcedatamap_set.all().order_by("order"))
|
||||
|
||||
def get_citation_datamap(self, citation):
|
||||
return dict([map.key, map.value] for map in citation.citationdatamap_set.all())
|
||||
return dict([map.key, map.value] for map in citation.citationdatamap_set.all().order_by("order"))
|
||||
|
||||
def get_media_list(self, obj):
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
@ -1021,18 +1021,22 @@ class DjangoInterface(object):
|
||||
## Export individual objects:
|
||||
|
||||
def add_source_datamap_dict(self, source, datamap_dict):
|
||||
count = 1
|
||||
for key in datamap_dict:
|
||||
value = datamap_dict[key]
|
||||
datamap = models.SourceDatamap(key=key, value=value)
|
||||
datamap = models.SourceDatamap(key=key, value=value, order=count)
|
||||
datamap.source = source
|
||||
datamap.save()
|
||||
count += 1
|
||||
|
||||
def add_citation_datamap_dict(self, citation, datamap_dict):
|
||||
count = 1
|
||||
for key in datamap_dict:
|
||||
value = datamap_dict[key]
|
||||
datamap = models.CitationDatamap(key=key, value=value)
|
||||
datamap = models.CitationDatamap(key=key, value=value, order=count)
|
||||
datamap.citation = citation
|
||||
datamap.save()
|
||||
count += 1
|
||||
|
||||
def add_lds(self, field, obj, data, order):
|
||||
(lcitation_list, lnote_list, date, type, place_handle,
|
||||
@ -1697,6 +1701,7 @@ class DjangoInterface(object):
|
||||
"""
|
||||
Resets the cache version of an object, and saves it to the database.
|
||||
"""
|
||||
self.update_public(item, save=False)
|
||||
self.reset_cache(item)
|
||||
item.save()
|
||||
|
||||
@ -1721,66 +1726,53 @@ class DjangoInterface(object):
|
||||
self.Citation.all().count() +
|
||||
self.Tag.all().count())
|
||||
|
||||
for item in self.Note.all():
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Person.all():
|
||||
raw = self.get_person(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Family.all():
|
||||
raw = self.get_family(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Source.all():
|
||||
raw = self.get_source(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Event.all():
|
||||
raw = self.get_event(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Repository.all():
|
||||
raw = self.get_repository(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Place.all():
|
||||
raw = self.get_place(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Media.all():
|
||||
raw = self.get_media(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Citation.all():
|
||||
raw = self.get_citation(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Tag.all():
|
||||
raw = self.get_tag(item)
|
||||
item.cache = base64.encodestring(cPickle.dumps(raw))
|
||||
item.save()
|
||||
self.rebuild_cache(item)
|
||||
count += 1
|
||||
callback(100)
|
||||
|
||||
@ -1804,6 +1796,13 @@ class DjangoInterface(object):
|
||||
self.Citation.all().count() +
|
||||
self.Tag.all().count())
|
||||
|
||||
for item in self.Note.all():
|
||||
raw = self.get_note(item)
|
||||
if item.cache == base64.encodestring(cPickle.dumps(raw)):
|
||||
print "Different!", item
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Person.all():
|
||||
raw = self.get_person(item)
|
||||
if item.cache == base64.encodestring(cPickle.dumps(raw)):
|
||||
@ -1868,6 +1867,9 @@ class DjangoInterface(object):
|
||||
callback(100)
|
||||
|
||||
def check_families(self):
|
||||
"""
|
||||
Check family structures.
|
||||
"""
|
||||
for family in self.Family.all():
|
||||
if family.mother:
|
||||
if not family in family.mother.families.all():
|
||||
@ -1885,3 +1887,152 @@ class DjangoInterface(object):
|
||||
for family in person.parent_families.all():
|
||||
if person not in family.get_children():
|
||||
print "Child not in family", person, family
|
||||
|
||||
def is_public(self, obj, objref):
|
||||
"""
|
||||
Returns whether or not an item is "public", and the reason
|
||||
why/why not.
|
||||
|
||||
@param obj - an instance of any Primary object
|
||||
@param objref - one of the PrimaryRef.objects
|
||||
@return - a tuple containing a boolean (public?) and reason.
|
||||
|
||||
There are three reasons why an item might not be public:
|
||||
1) The item itself is private.
|
||||
2) The item is referenced by a living Person.
|
||||
3) The item is referenced by some other private item.
|
||||
"""
|
||||
# If it is private, then no:
|
||||
if obj.private:
|
||||
return (False, "It is marked private.")
|
||||
elif hasattr(obj, "probably_alive") and obj.probably_alive:
|
||||
return (False, "It is marked probaby alive.")
|
||||
elif hasattr(obj, "mother") and obj.mother:
|
||||
public, reason = self.is_public(obj.mother, self.PersonRef)
|
||||
if not public:
|
||||
return public, reason
|
||||
elif hasattr(obj, "father") and obj.father:
|
||||
public, reason = self.is_public(obj.father, self.PersonRef)
|
||||
if not public:
|
||||
return public, reason
|
||||
# FIXME: what about Associations... anything else? Check PrivateProxy
|
||||
if objref:
|
||||
obj_ref_list = objref.filter(ref_object=obj)
|
||||
for reference in obj_ref_list:
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
item = None
|
||||
try:
|
||||
item = ref_from_class.objects.get(id=reference.object_id)
|
||||
except:
|
||||
print "Warning: Corrupt reference: %s" % reference
|
||||
continue
|
||||
# If it is linked to by someone alive? public = False
|
||||
if hasattr(item, "probably_alive") and item.probably_alive:
|
||||
return (False, "It is referenced by someone who is probaby alive.")
|
||||
# If it is linked to by something private? public = False
|
||||
elif item.private:
|
||||
return (False, "It is referenced by an item which is marked private.")
|
||||
return (True, "It is visible to the public.")
|
||||
|
||||
def update_public(self, obj, save=True):
|
||||
"""
|
||||
>>> dji.update_public(event)
|
||||
|
||||
Given an Event or other instance, update the event's public
|
||||
status, or any event referenced to by the instance.
|
||||
|
||||
For example, if a person is found to be alive, then the
|
||||
referenced events should be marked not public (public = False).
|
||||
|
||||
"""
|
||||
if obj.__class__.__name__ == "Event":
|
||||
objref = self.EventRef
|
||||
elif obj.__class__.__name__ == "Person":
|
||||
objref = self.PersonRef
|
||||
elif obj.__class__.__name__ == "Note":
|
||||
objref = self.NoteRef
|
||||
elif obj.__class__.__name__ == "Repository":
|
||||
objref = self.RepositoryRef
|
||||
elif obj.__class__.__name__ == "Citation":
|
||||
objref = self.CitationRef
|
||||
elif obj.__class__.__name__ == "Media":
|
||||
objref = self.MediaRef
|
||||
elif obj.__class__.__name__ == "Place": # no need for dependency
|
||||
objref = None
|
||||
elif obj.__class__.__name__ == "Source": # no need for dependency
|
||||
objref = None
|
||||
elif obj.__class__.__name__ == "Family":
|
||||
objref = self.ChildRef # correct?
|
||||
else:
|
||||
raise Exception("Can't compute public of type '%s'" % obj)
|
||||
public, reason = self.is_public(obj, objref) # correct?
|
||||
# Ok, update, if needed:
|
||||
if obj.public != public:
|
||||
obj.public = public
|
||||
if save:
|
||||
obj.save()
|
||||
|
||||
def update_publics(self, callback=None):
|
||||
"""
|
||||
Call this to check the caches for all primary models.
|
||||
"""
|
||||
if not callable(callback):
|
||||
callback = lambda (percent): None # dummy
|
||||
|
||||
callback(0)
|
||||
count = 0.0
|
||||
total = (self.Note.all().count() +
|
||||
self.Person.all().count() +
|
||||
self.Event.all().count() +
|
||||
self.Family.all().count() +
|
||||
self.Repository.all().count() +
|
||||
self.Place.all().count() +
|
||||
self.Media.all().count() +
|
||||
self.Source.all().count() +
|
||||
self.Citation.all().count())
|
||||
|
||||
for item in self.Note.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Person.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Family.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Source.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Event.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Repository.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Place.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Media.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
for item in self.Citation.all():
|
||||
self.update_public(item)
|
||||
count += 1
|
||||
callback(100 * (count/total if total else 0))
|
||||
|
||||
|
@ -64,6 +64,7 @@ urlpatterns += patterns('',
|
||||
(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to',
|
||||
{'url': '/styles/images/favicon.ico'}),
|
||||
(r'^user/$', user_page),
|
||||
(r'^json/$', process_json_request),
|
||||
(r'^user/(\w+)/$', user_page),
|
||||
(r'^browse/$', browse_page),
|
||||
(r'^login/$', 'django.contrib.auth.views.login'),
|
||||
|
@ -90,12 +90,11 @@ util_tags = [
|
||||
"attribute_table",
|
||||
"data_table",
|
||||
"address_table",
|
||||
"location_table",
|
||||
"media_table",
|
||||
"internet_table",
|
||||
"association_table",
|
||||
"location_table",
|
||||
"lds_table",
|
||||
"reference_table",
|
||||
"repository_table",
|
||||
"person_reference_table",
|
||||
"note_reference_table",
|
||||
@ -311,7 +310,7 @@ def event_table(obj, user, act, url, args):
|
||||
_("Place"),
|
||||
_("Role"))
|
||||
table.column_widths = [10, 20, 10, 7, 20, 23, 10]
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
event_ref_list = models.EventRef.objects.filter(
|
||||
object_id=obj.id,
|
||||
@ -357,7 +356,7 @@ def history_table(obj, user, act):
|
||||
_("Action"),
|
||||
_("Comment"),
|
||||
)
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
for entry in models.Log.objects.filter(
|
||||
object_id=obj.id,
|
||||
@ -388,7 +387,7 @@ def name_table(obj, user, act, url=None, *args):
|
||||
_("Group As"),
|
||||
_("Source"),
|
||||
_("Note Preview"))
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
links = []
|
||||
for name in obj.name_set.all().order_by("order"):
|
||||
obj_type = ContentType.objects.get_for_model(name)
|
||||
@ -429,7 +428,7 @@ def surname_table(obj, user, act, url=None, *args):
|
||||
cssid = "tab-surnames"
|
||||
table = Table("surname_table")
|
||||
table.columns(_("Order"), _("Surname"),)
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
try:
|
||||
name = obj.name_set.filter(order=order)[0]
|
||||
except:
|
||||
@ -450,16 +449,18 @@ def surname_table(obj, user, act, url=None, *args):
|
||||
return retval
|
||||
|
||||
def citation_table(obj, user, act, url=None, *args):
|
||||
# FIXME: how can citation_table and source_table both be on same
|
||||
# page? This causes problems with form names, tab names, etc.
|
||||
retval = ""
|
||||
has_data = False
|
||||
cssid = "tab-citations"
|
||||
cssid = "tab-sources"
|
||||
table = Table("citation_table")
|
||||
table.columns("",
|
||||
_("ID"),
|
||||
_("Confidence"),
|
||||
_("Page"))
|
||||
table.column_widths = [10, 10, 50, 30]
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
citation_refs = dji.CitationRef.filter(object_type=obj_type,
|
||||
object_id=obj.id).order_by("order")
|
||||
@ -501,14 +502,37 @@ def repository_table(obj, user, act, url=None, *args):
|
||||
cssid = "tab-repositories"
|
||||
table = Table("repository_table")
|
||||
table.columns(
|
||||
"",
|
||||
_("ID"),
|
||||
_("Title"),
|
||||
_("Call number"),
|
||||
_("Type"),
|
||||
_("Note"))
|
||||
if user.is_authenticated():
|
||||
pass
|
||||
retval += table.get_html()
|
||||
## FIXME: missing table
|
||||
## has_data = True
|
||||
)
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
refs = dji.RepositoryRef.filter(object_type=obj_type,
|
||||
object_id=obj.id)
|
||||
count = 1
|
||||
for repo_ref in refs:
|
||||
repository = repo_ref.ref_object
|
||||
table.row(
|
||||
Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser else "",
|
||||
repository.gramps_id,
|
||||
repository.name,
|
||||
repo_ref.call_number,
|
||||
str(repository.repository_type),
|
||||
)
|
||||
has_data = True
|
||||
count += 1
|
||||
text = table.get_html()
|
||||
count = 1
|
||||
for repo_ref in refs:
|
||||
item = obj.__class__.__name__.lower()
|
||||
text = text.replace("[[x%d]]" % count, make_button("x", "/%s/%s/remove/repositoryref/%d" % (item, obj.handle, count)))
|
||||
text = text.replace("[[^%d]]" % count, make_button("^", "/%s/%s/up/repositoryref/%d" % (item, obj.handle, count)))
|
||||
text = text.replace("[[v%d]]" % count, make_button("v", "/%s/%s/down/repositoryref/%d" % (item, obj.handle, count)))
|
||||
count += 1
|
||||
retval += text
|
||||
if user.is_superuser and url and act == "view":
|
||||
retval += make_button(_("Add New Repository"), (url % args).replace("$act", "add"))
|
||||
retval += make_button(_("Add Existing Repository"), (url % args).replace("$act", "share"))
|
||||
@ -527,16 +551,15 @@ def note_table(obj, user, act, url=None, *args):
|
||||
_("ID"),
|
||||
_("Type"),
|
||||
_("Note"))
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
note_refs = dji.NoteRef.filter(object_type=obj_type,
|
||||
object_id=obj.id)
|
||||
for note_ref in note_refs:
|
||||
note = table.db.get_note_from_handle(
|
||||
note_ref.ref_object.handle)
|
||||
table.row(table.db.get_note_from_handle(note.handle),
|
||||
str(note_ref.ref_object.note_type),
|
||||
note_ref.ref_object.text[:50])
|
||||
note = note_ref.ref_object
|
||||
table.row(note,
|
||||
str(note.note_type),
|
||||
note.text[:50])
|
||||
has_data = True
|
||||
retval += table.get_html()
|
||||
if user.is_superuser and url and act == "view":
|
||||
@ -551,18 +574,43 @@ def note_table(obj, user, act, url=None, *args):
|
||||
def data_table(obj, user, act, url=None, *args):
|
||||
retval = ""
|
||||
has_data = False
|
||||
cssid = "has_data"
|
||||
cssid = "tab-data"
|
||||
table = Table("data_table")
|
||||
table.columns(_("Type"),
|
||||
_("Value"),
|
||||
)
|
||||
if user.is_authenticated():
|
||||
pass
|
||||
## FIXME: missing table
|
||||
## has_data = True
|
||||
retval += table.get_html()
|
||||
table.columns(
|
||||
"",
|
||||
_("Type"),
|
||||
_("Value"),
|
||||
)
|
||||
if user.is_authenticated() or obj.public:
|
||||
item_class = obj.__class__.__name__.lower()
|
||||
if item_class == "citation":
|
||||
refs = models.CitationDatamap.objects.filter(citation=obj).order_by("order")
|
||||
elif item_class == "source":
|
||||
refs = models.SourceDatamap.objects.filter(source=obj).order_by("order")
|
||||
count = 1
|
||||
for ref in refs:
|
||||
if item_class == "citation":
|
||||
ref_obj = ref.citation
|
||||
elif item_class == "source":
|
||||
ref_obj = ref.source
|
||||
table.row(
|
||||
Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser else "",
|
||||
ref_obj.key,
|
||||
ref_obj.value,
|
||||
)
|
||||
has_data = True
|
||||
count += 1
|
||||
text = table.get_html()
|
||||
count = 1
|
||||
for repo_ref in refs:
|
||||
text = text.replace("[[x%d]]" % count, make_button("x", "/%s/%s/remove/datamap/%d" % (item_class, obj.handle, count)))
|
||||
text = text.replace("[[^%d]]" % count, make_button("^", "/%s/%s/up/datamap/%d" % (item_class, obj.handle, count)))
|
||||
text = text.replace("[[v%d]]" % count, make_button("v", "/%s/%s/down/datamap/%d" % (item_class, obj.handle, count)))
|
||||
count += 1
|
||||
retval += text
|
||||
if user.is_superuser and url and act == "view":
|
||||
retval += make_button(_("Add Data"), (url % args))
|
||||
# /data/$act/citation/%s
|
||||
retval += make_button(_("Add Data"), (url.replace("$act", "add") % args))
|
||||
else:
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
@ -577,7 +625,7 @@ def attribute_table(obj, user, act, url=None, *args):
|
||||
table.columns(_("Type"),
|
||||
_("Value"),
|
||||
)
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
attributes = dji.Attribute.filter(object_type=obj_type,
|
||||
object_id=obj.id)
|
||||
@ -604,7 +652,7 @@ def address_table(obj, user, act, url=None, *args):
|
||||
_("City"),
|
||||
_("State"),
|
||||
_("Country"))
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
for address in obj.address_set.all().order_by("order"):
|
||||
locations = address.location_set.all().order_by("order")
|
||||
for location in locations:
|
||||
@ -623,29 +671,6 @@ def address_table(obj, user, act, url=None, *args):
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def location_table(obj, user, act, url=None, *args):
|
||||
retval = ""
|
||||
has_data = False
|
||||
cssid = "tab-locations"
|
||||
table = Table("location_table")
|
||||
table.columns(_("Date"),
|
||||
_("Address"),
|
||||
_("City"),
|
||||
_("State"),
|
||||
_("Country"))
|
||||
if user.is_authenticated():
|
||||
pass # FIXME
|
||||
## FIXME: missing table
|
||||
## has_data = True
|
||||
retval += table.get_html()
|
||||
if user.is_superuser and url and act == "view":
|
||||
retval += make_button(_("Add Address"), (url % args))
|
||||
else:
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def media_table(obj, user, act, url=None, *args):
|
||||
retval = ""
|
||||
has_data = False
|
||||
@ -655,7 +680,7 @@ def media_table(obj, user, act, url=None, *args):
|
||||
_("Type"),
|
||||
_("Path/Filename"),
|
||||
)
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
media_refs = dji.MediaRef.filter(object_type=obj_type,
|
||||
object_id=obj.id)
|
||||
@ -684,7 +709,7 @@ def internet_table(obj, user, act, url=None, *args):
|
||||
table.columns(_("Type"),
|
||||
_("Path"),
|
||||
_("Description"))
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
urls = dji.Url.filter(person=obj)
|
||||
for url_obj in urls:
|
||||
table.row(str(url_obj.url_type),
|
||||
@ -708,14 +733,29 @@ def association_table(obj, user, act, url=None, *args):
|
||||
table.columns(_("Name"),
|
||||
_("ID"),
|
||||
_("Association"))
|
||||
if user.is_authenticated():
|
||||
gperson = table.db.get_person_from_handle(obj.handle)
|
||||
if gperson:
|
||||
associations = gperson.get_person_ref_list()
|
||||
for association in associations:
|
||||
table.row() # FIXME: missing table
|
||||
if user.is_authenticated() or obj.public:
|
||||
person = table.db.get_person_from_handle(obj.handle)
|
||||
if person:
|
||||
links = []
|
||||
count = 1
|
||||
associations = person.get_person_ref_list()
|
||||
for association in associations: # PersonRef
|
||||
table.row(Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser and url and act == "view" else "",
|
||||
association.ref_object.get_primary_name(),
|
||||
association.ref_object.gramps_id,
|
||||
association.description,
|
||||
)
|
||||
links.append(('URL', "/person/%s/association/%d" % (obj.handle, count)))
|
||||
has_data = True
|
||||
retval += table.get_html()
|
||||
count += 1
|
||||
table.links(links)
|
||||
text = table.get_html()
|
||||
count = 1
|
||||
for association in associations: # PersonRef
|
||||
text = text.replace("[[x%d]]" % count, make_button("x", "/person/%s/remove/association/%d" % (obj.handle, count)))
|
||||
text = text.replace("[[^%d]]" % count, make_button("^", "/person/%s/up/association/%d" % (obj.handle, count)))
|
||||
text = text.replace("[[v%d]]" % count, make_button("v", "/person/%s/down/association/%d" % (obj.handle, count)))
|
||||
retval += text
|
||||
if user.is_superuser and url and act == "view":
|
||||
retval += make_button(_("Add Association"), (url % args))
|
||||
else:
|
||||
@ -724,6 +764,39 @@ def association_table(obj, user, act, url=None, *args):
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def location_table(obj, user, act, url=None, *args):
|
||||
# obj is Place or Address
|
||||
retval = ""
|
||||
has_data = False
|
||||
cssid = "tab-alternatelocations"
|
||||
table = Table("location_table")
|
||||
table.columns(_("Street"),
|
||||
_("Locality"),
|
||||
_("City"),
|
||||
_("State"),
|
||||
_("Country"))
|
||||
if user.is_authenticated() or obj.public:
|
||||
# FIXME: location confusion!
|
||||
# The single Location on the Location Tab is here too?
|
||||
# I think if Parish is None, then these are single Locations;
|
||||
# else they are in the table of alternate locations
|
||||
for location in obj.location_set.all().order_by("order"):
|
||||
table.row(
|
||||
location.street,
|
||||
location.locality,
|
||||
location.city,
|
||||
location.state,
|
||||
location.country)
|
||||
has_data = True
|
||||
retval += table.get_html()
|
||||
if user.is_superuser and url and act == "view":
|
||||
retval += make_button(_("Add Address"), (url % args))
|
||||
else:
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def lds_table(obj, user, act, url=None, *args):
|
||||
retval = ""
|
||||
has_data = False
|
||||
@ -734,7 +807,7 @@ def lds_table(obj, user, act, url=None, *args):
|
||||
_("Status"),
|
||||
_("Temple"),
|
||||
_("Place"))
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
obj_type = ContentType.objects.get_for_model(obj)
|
||||
ldss = obj.lds_set.all().order_by("order")
|
||||
for lds in ldss:
|
||||
@ -753,24 +826,6 @@ def lds_table(obj, user, act, url=None, *args):
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def reference_table(obj, user, act, url=None, *args):
|
||||
retval = ""
|
||||
has_data = False
|
||||
cssid = "tab-references"
|
||||
table = Table("reference_table")
|
||||
table.columns(
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated():
|
||||
pass
|
||||
## FIXME: missing table?
|
||||
retval += table.get_html()
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
|
||||
return retval
|
||||
|
||||
def person_reference_table(obj, user, act):
|
||||
retval = """<div style="overflow: auto; height:%spx;">""" % TAB_HEIGHT
|
||||
has_data = False
|
||||
@ -791,7 +846,7 @@ def person_reference_table(obj, user, act):
|
||||
_("Reference"),
|
||||
)
|
||||
table2.column_widths = [10, 10, 82]
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
count = 1
|
||||
for through in models.MyFamilies.objects.filter(person=obj).order_by("order"):
|
||||
reference = through.family
|
||||
@ -852,7 +907,7 @@ def note_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for reference in models.NoteRef.objects.filter(ref_object=obj):
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
item = ref_from_class.objects.get(id=reference.object_id)
|
||||
@ -876,7 +931,7 @@ def event_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for reference in models.EventRef.objects.filter(ref_object=obj):
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
try:
|
||||
@ -904,7 +959,7 @@ def repository_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for reference in models.RepositoryRef.objects.filter(ref_object=obj):
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
item = ref_from_class.objects.get(id=reference.object_id)
|
||||
@ -929,7 +984,7 @@ def citation_reference_table(obj, user, act):
|
||||
_("Reference"),
|
||||
# _("ID")
|
||||
)
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for reference in models.CitationRef.objects.filter(citation=obj):
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
item = ref_from_class.objects.get(id=reference.object_id)
|
||||
@ -952,9 +1007,13 @@ def source_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
pass
|
||||
# FIXME: where is source ref?
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for item in obj.citation_set.all():
|
||||
table.row(
|
||||
item.__class__.__name__,
|
||||
item,
|
||||
item.gramps_id)
|
||||
has_data = True
|
||||
retval += table.get_html()
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
@ -970,7 +1029,7 @@ def media_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
for reference in models.MediaRef.objects.filter(ref_object=obj):
|
||||
ref_from_class = reference.object_type.model_class()
|
||||
item = ref_from_class.objects.get(id=reference.object_id)
|
||||
@ -992,11 +1051,16 @@ def place_reference_table(obj, user, act):
|
||||
table = Table("place_reference_table")
|
||||
table.columns(
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
pass # FIXME
|
||||
## FIXME: missing table
|
||||
_("Reference"))
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
# location, url, event, lds
|
||||
querysets = [obj.location_set, obj.url_set, obj.event_set, obj.lds_set]
|
||||
for queryset in querysets:
|
||||
for item in queryset.all():
|
||||
table.row(
|
||||
item.__class__.__name__,
|
||||
item)
|
||||
has_data = True
|
||||
retval += table.get_html()
|
||||
retval += nbsp("") # to keep tabs same height
|
||||
if has_data:
|
||||
@ -1012,7 +1076,7 @@ def tag_reference_table(obj, user, act):
|
||||
_("Type"),
|
||||
_("Reference"),
|
||||
_("ID"))
|
||||
if user.is_authenticated() and act != "add":
|
||||
if (user.is_authenticated() or obj.public) and act != "add":
|
||||
querysets = [obj.person_set, obj.family_set, obj.note_set, obj.media_set]
|
||||
for queryset in querysets:
|
||||
for item in queryset.all():
|
||||
@ -1061,7 +1125,7 @@ def children_table(obj, user, act, url=None, *args):
|
||||
count = 1
|
||||
for childref in childrefs:
|
||||
child = childref.ref_object
|
||||
if user.is_authenticated():
|
||||
if user.is_authenticated() or obj.public:
|
||||
table.row(Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser and url and act == "view" else "",
|
||||
str(count),
|
||||
"[%s]" % child.gramps_id,
|
||||
@ -1069,7 +1133,7 @@ def children_table(obj, user, act, url=None, *args):
|
||||
child.gender_type,
|
||||
childref.father_rel_type,
|
||||
childref.mother_rel_type,
|
||||
date_as_text(child.birth, user),
|
||||
date_as_text(child.birth, user) if child.birth else "",
|
||||
)
|
||||
has_data = True
|
||||
links.append(('URL', childref.get_url()))
|
||||
@ -1116,20 +1180,6 @@ def get_title(place):
|
||||
else:
|
||||
return ""
|
||||
|
||||
def person_get_birth_date(person):
|
||||
#db = DbDjango()
|
||||
#event = get_birth_or_fallback(db, db.get_person_from_handle(person.handle))
|
||||
#if event:
|
||||
# return event.date
|
||||
return None
|
||||
|
||||
def person_get_death_date(person):
|
||||
#db = DbDjango()
|
||||
#event = get_death_or_fallback(db, db.get_person_from_handle(person.handle))
|
||||
#if event:
|
||||
# return event.date
|
||||
return None
|
||||
|
||||
def display_date(obj):
|
||||
date_tuple = dji.get_date(obj)
|
||||
if date_tuple:
|
||||
@ -1162,10 +1212,16 @@ def render(formfield, user, act, id=None, url=None, *args):
|
||||
else:
|
||||
retval = str(item)
|
||||
#### Some cleanup:
|
||||
if retval == "True":
|
||||
retval = "Yes"
|
||||
elif retval == "False":
|
||||
retval = "No"
|
||||
if fieldname == "private": # obj.private
|
||||
if retval == "True":
|
||||
retval = "Private"
|
||||
elif retval == "False":
|
||||
retval = "Not private"
|
||||
else:
|
||||
if retval == "True":
|
||||
retval = "Yes"
|
||||
elif retval == "False":
|
||||
retval = "No"
|
||||
except:
|
||||
# name, "prefix"
|
||||
try:
|
||||
@ -1177,6 +1233,8 @@ def render(formfield, user, act, id=None, url=None, *args):
|
||||
retval = formfield.as_widget(attrs={"id": id})
|
||||
else:
|
||||
retval = formfield.as_widget()
|
||||
if formfield.name == "private":
|
||||
retval += " Private"
|
||||
return retval
|
||||
|
||||
def render_name(name, user, act=None):
|
||||
@ -1236,15 +1294,15 @@ def date_as_text(obj, user):
|
||||
Given a Django object, render the date as text and return. This
|
||||
function uses authentication settings.
|
||||
"""
|
||||
if (user.is_authenticated() or
|
||||
(not user.is_authenticated() and obj and not obj.private)):
|
||||
if user.is_authenticated() or (obj and obj.public):
|
||||
if obj:
|
||||
date_tuple = dji.get_date(obj)
|
||||
if date_tuple:
|
||||
gdate = GDate().unserialize(date_tuple)
|
||||
return dd(gdate)
|
||||
return ""
|
||||
return "[Private]"
|
||||
else:
|
||||
return ""
|
||||
|
||||
def person_get_event(person, event_type=None):
|
||||
event_ref_list = dji.get_event_ref_list(person)
|
||||
@ -1489,3 +1547,17 @@ def make_log(obj, log_type, last_changed_by, reason, cache):
|
||||
cache=cache)
|
||||
log.save()
|
||||
|
||||
def person_get_birth_date(person):
|
||||
#db = DbDjango()
|
||||
#event = get_birth_or_fallback(db, db.get_person_from_handle(person.handle))
|
||||
#if event:
|
||||
# return event.date
|
||||
return None
|
||||
|
||||
def person_get_death_date(person):
|
||||
#db = DbDjango()
|
||||
#event = get_death_or_fallback(db, db.get_person_from_handle(person.handle))
|
||||
#if event:
|
||||
# return event.date
|
||||
return None
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user