summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/context_processors.py7
-rw-r--r--ishtar_common/forms.py7
-rw-r--r--ishtar_common/menu_base.py8
-rw-r--r--ishtar_common/models.py35
-rw-r--r--ishtar_common/static/js/ishtar.js12
-rw-r--r--ishtar_common/static/media/style.css6
-rw-r--r--ishtar_common/templates/base.html4
-rw-r--r--ishtar_common/templates/blocks/JQueryJqGrid.html1
-rw-r--r--ishtar_common/templates/ishtar/basket_list.html10
-rw-r--r--ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html1
-rw-r--r--ishtar_common/templates/ishtar/form_delete.html14
-rw-r--r--ishtar_common/templates/ishtar/manage_basket.html42
-rw-r--r--ishtar_common/templates/ishtar/simple_form.html11
-rw-r--r--ishtar_common/templatetags/window_tables.py27
-rw-r--r--ishtar_common/views.py12
-rw-r--r--ishtar_common/widgets.py5
-rw-r--r--ishtar_common/wizards.py2
17 files changed, 180 insertions, 24 deletions
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index 03ba9bc36..76f58bf8e 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -77,10 +77,13 @@ def get_base_context(request):
current = model_name in request.session and request.session[model_name]
items = []
for item in model.get_owns(request.user):
- selected = unicode(item.pk) == current
+ pk = unicode(item.pk)
+ if item.IS_BASKET:
+ pk = "basket-" + pk
+ selected = pk == current
if selected:
cls = item.get_short_menu_class()
- items.append((item.pk, shortify(unicode(item), 60),
+ items.append((pk, shortify(unicode(item), 60),
selected, item.get_short_menu_class()))
if items:
dct['current_menu'].append((lbl, model_name, cls, items))
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index a5abdddcd..5e0d14eb8 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -128,7 +128,7 @@ class ClosingDateFormSelection(forms.Form):
def get_form_selection(
class_name, label, key, model, base_form, get_url,
not_selected_error=_(u"You should select an item."), new=False,
- new_message=_(u"Add a new item")):
+ new_message=_(u"Add a new item"), get_full_url=None):
"""
Generate a class selection form
class_name -- name of the class
@@ -145,11 +145,14 @@ def get_form_selection(
'form_label': label,
'associated_models': {key: model},
'currents': {key: model}}
+ widget_kwargs = {"new": new, "new_message": new_message}
+ if get_full_url:
+ widget_kwargs['source_full'] = reverse_lazy(get_full_url)
attrs[key] = forms.IntegerField(
label="", required=False,
validators=[models.valid_id(model)],
widget=widgets.JQueryJqGrid(reverse_lazy(get_url), base_form, model,
- new=new, new_message=new_message))
+ **widget_kwargs))
def clean(self):
cleaned_data = self.cleaned_data
diff --git a/ishtar_common/menu_base.py b/ishtar_common/menu_base.py
index d8ee0775c..7c309d376 100644
--- a/ishtar_common/menu_base.py
+++ b/ishtar_common/menu_base.py
@@ -89,9 +89,9 @@ class MenuItem:
for access_control in self.access_controls:
access_control = prefix + access_control
if hasattr(user, 'ishtaruser') and \
- user.ishtaruser.has_perm(access_control, self.model,
- session=session) or \
+ user.ishtaruser.has_perm(access_control, self.model) or\
access_control in user.get_group_permissions():
+ # session=session) or \
return True
# manage by person type
if hasattr(user, 'ishtaruser'):
@@ -107,8 +107,8 @@ class MenuItem:
prefix = (self.model._meta.app_label + '.') if self.model else ''
for access_control in self.access_controls:
access_control = prefix + access_control
- if user.has_perm(access_control, self.model, obj=obj,
- session=session):
+ if user.has_perm(access_control, self.model, obj=obj):
+ # session=session):
return True
# manage by person type
if hasattr(user, 'ishtaruser'):
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 9509b36a6..f3974d04d 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -243,10 +243,15 @@ class OwnPerms:
user = IshtarUser.objects.get(user_ptr=user)
if user.is_anonymous():
return cls.objects.filter(pk__isnull=True)
+ items = []
+ if hasattr(cls, 'BASKET_MODEL'):
+ items = list(cls.BASKET_MODEL.objects.filter(user=user).all())
query = cls.get_query_owns(user)
if not query:
return cls.objects.filter(pk__isnull=True)
- return cls.objects.filter(query).order_by(*cls._meta.ordering)
+ items += list(
+ cls.objects.filter(query).order_by(*cls._meta.ordering).all())
+ return items
class Cached(object):
@@ -475,6 +480,33 @@ class GeneralType(models.Model, Cached):
item.generate_key()
+class Basket(models.Model):
+ """
+ Abstract class for a basket
+ Subclass must be defined with an "items" ManyToManyField
+ """
+ IS_BASKET = True
+ label = models.CharField(_(u"Label"), max_length=1000)
+ comment = models.TextField(_(u"Comment"), blank=True, null=True)
+ user = models.ForeignKey('IshtarUser', blank=True, null=True)
+ available = models.BooleanField(_(u"Available"), default=True)
+
+ class Meta:
+ abstract = True
+ unique_together = (('label', 'user'),)
+
+ def __unicode__(self):
+ return self.label
+
+ def get_short_menu_class(self):
+ return 'basket'
+
+ @property
+ def associated_filename(self):
+ return "{}-{}".format(datetime.date.today().strftime(
+ "%Y-%m-%d"), slugify(self.label))
+
+
class ItemKey(models.Model):
key = models.CharField(_(u"Key"), max_length=100)
content_type = models.ForeignKey(ContentType)
@@ -551,6 +583,7 @@ class HistoryError(Exception):
class BaseHistorizedItem(Imported):
+ IS_BASKET = False
history_modifier = models.ForeignKey(
User, related_name='+', on_delete=models.SET_NULL,
verbose_name=_(u"Last editor"), blank=True, null=True)
diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js
index 9af5cf2b0..f469fc546 100644
--- a/ishtar_common/static/js/ishtar.js
+++ b/ishtar_common/static/js/ishtar.js
@@ -23,6 +23,15 @@ beforeSend: function(xhr, settings) {
}
}});
+function manage_async_link(event){
+ event.preventDefault();
+ var url = $(this).attr('href');
+ var target = $(this).attr('data-target');
+ $.get(url, function(data) {
+ $(target).html(data);
+ });
+}
+
/* default function to prevent undefined */
function get_next_table_id(){}
function get_previous_table_id(){}
@@ -63,7 +72,8 @@ $(document).ready(function(){
}
$('#current_items select').change(function(){
$(this).attr('class', $(this).children("option:selected").attr('class'));
- })
+ });
+ $("a.async-link").click(manage_async_link);
});
$(document).on("click", '#to_bottom_arrow', function(){
diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css
index 1590c1738..1d47bcbd9 100644
--- a/ishtar_common/static/media/style.css
+++ b/ishtar_common/static/media/style.css
@@ -45,6 +45,12 @@ a.add-button,
color:#000;
}
+#context_menu .basket{
+ color:#000;
+ font-weight: bold;
+ font-style: italic;
+}
+
/* borders */
a.add-button, a.remove,
#progress-content,
diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html
index 578b3edcc..1bab3d647 100644
--- a/ishtar_common/templates/base.html
+++ b/ishtar_common/templates/base.html
@@ -74,7 +74,7 @@
<td>
<select class='{{main_cls}}' id='current_{{model_name}}'>
<option class='normal' value=''>--</option>
- {% for val, label, selected, cls in items %}<option class='{{cls}}' value='{{val}}'{%if selected%} selected="selected"{%endif%}>{{label}}</option>
+ {% for val, label, selected, cls in items %}<option class='{{cls}}' value='{{val}}'{% if selected %} selected="selected"{%endif%}>{{label}}</option>
{% endfor %}</select>
</td>{% with 'show-'|add:model_name as model_url%}
<td><a href='#' onclick='load_current_window("{% url model_url 0 %}", "{{model_name}}");' class='display_details'>{% trans "Details" %}</a></td>
@@ -87,7 +87,7 @@
{% endif %}{% endblock %}
</div>{% endif %}
{% if reminders %}<fieldset id='reminder'><legend>{% trans "Current items" %}</legend>
-{% for lbl, value in reminders%}
+{% for lbl, value in reminders %}
<p><strong class='lbl'>{{lbl}}{% trans ":"%}</strong> <span class='value'>{{value}}</span></p>
{% endfor %}
</fieldset>{%endif%}
diff --git a/ishtar_common/templates/blocks/JQueryJqGrid.html b/ishtar_common/templates/blocks/JQueryJqGrid.html
index 063a3c1da..c6a15243a 100644
--- a/ishtar_common/templates/blocks/JQueryJqGrid.html
+++ b/ishtar_common/templates/blocks/JQueryJqGrid.html
@@ -90,6 +90,7 @@ jQuery(document).ready(function(){
width: null,
shrinkToFit: false,
rowNum:20,
+ {% if multiple_select %}multiselect: true,{% endif %}
jsonReader : {repeatitems: false},
loadError: function (jqXHR, textStatus, errorThrown) {
alert("{% trans "An error as occured during search. Check your query fields." %}");
diff --git a/ishtar_common/templates/ishtar/basket_list.html b/ishtar_common/templates/ishtar/basket_list.html
new file mode 100644
index 000000000..a0a0e5d73
--- /dev/null
+++ b/ishtar_common/templates/ishtar/basket_list.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+<table>
+<tr>{% for item in basket.items.all %}
+ <td><a class="display_details" href="#" onclick="load_window('{{item_url}}/{{item.pk}}/');">{% trans 'Details' %}</a></td>
+ <td>{{item.full_label}}</td>
+ <td><a class='async-link' data-target='#basket-content' href='{{delete_url}}/{{basket.pk}}/{{item.pk}}/'>{% trans "remove" %}</a></td></tr>{% endfor %}
+</table>
+<script type='text/javascript'>
+ $("a.async-link").click(manage_async_link);
+</script>
diff --git a/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html b/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html
index 7239b64fc..8850bd34a 100644
--- a/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html
+++ b/ishtar_common/templates/ishtar/blocks/window_tables/dynamic_documents.html
@@ -42,6 +42,7 @@ setTimeout(
alert("{% trans "An error as occured during search. Check your query fields." %}");
}
});
+ {% if large %}jQuery("#grid_{{name}}").jqGrid('setGridHeight', 400);{% endif %}
}, 200);
</script>
diff --git a/ishtar_common/templates/ishtar/form_delete.html b/ishtar_common/templates/ishtar/form_delete.html
new file mode 100644
index 000000000..6243e9423
--- /dev/null
+++ b/ishtar_common/templates/ishtar/form_delete.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load i18n inline_formset %}
+{% block content %}
+<h2>{{page_name}}</h2>
+<div class='form'>
+<form enctype="multipart/form-data" action="." method="post"
+ onsubmit="return confirm('Do you really want to delete this item?');">{% csrf_token %}
+<table>
+{{form}}
+</table>
+<input type="submit" value="{% trans "Delete" %}"/>
+</form>
+</div>
+{% endblock %}
diff --git a/ishtar_common/templates/ishtar/manage_basket.html b/ishtar_common/templates/ishtar/manage_basket.html
new file mode 100644
index 000000000..6332b326e
--- /dev/null
+++ b/ishtar_common/templates/ishtar/manage_basket.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+{% load i18n inline_formset %}
+{% block content %}
+<h2>{{page_name}}{% trans ":"%} {{basket}}</h2>
+<form enctype="multipart/form-data" action="." method="post">{% csrf_token %}
+<div class='form'>
+<p class='alert'>{% trans 'Checking "Select all" only select the current page.' %}</p>
+{{form}}
+<button id='add_to' onclick='return false'>{% trans "Add" %}</button>
+<h3>{% trans "Basket content" %}</h3>
+<div id='basket-content' style='text-align:left'>
+</div>
+</div>
+</form>
+<script type='text/javascript' language='javascript'>
+
+function load_list(data){
+ $('#basket-content').html(data);
+}
+
+$('#add_to').click(function(){
+ var selected_items = jQuery("#grid_pk").getGridParam('selarrrow');
+ if(!selected_items) return false;
+ for (i = 0, n = selected_items.length; i < n; i++) {
+ var selected_item = selected_items[i];
+ $.ajax({
+ type: "POST",
+ url: '{{add_url}}',
+ data: {
+ basket_id: {{basket.pk}},
+ item_id: selected_item
+ },
+ success: load_list
+ });
+ }
+ return false;
+});
+jQuery(document).ready(function(){
+ $.get('{{list_url}}', load_list);
+});
+</script>
+{% endblock %}
diff --git a/ishtar_common/templates/ishtar/simple_form.html b/ishtar_common/templates/ishtar/simple_form.html
new file mode 100644
index 000000000..e3a464459
--- /dev/null
+++ b/ishtar_common/templates/ishtar/simple_form.html
@@ -0,0 +1,11 @@
+{% load i18n %}
+<html>
+<body>
+<div class='form'>
+<form enctype="multipart/form-data" action="." method="post">{% csrf_token %}
+{{form}}
+<input type="submit" value="{% trans "Validate" %}"/>
+</form>
+</div>
+</body>
+</html>
diff --git a/ishtar_common/templatetags/window_tables.py b/ishtar_common/templatetags/window_tables.py
index cdd681b52..6710672e1 100644
--- a/ishtar_common/templatetags/window_tables.py
+++ b/ishtar_common/templatetags/window_tables.py
@@ -27,25 +27,28 @@ def table_document(caption, data):
ASSOCIATED_MODELS = {}
ASSOCIATED_MODELS['files'] = (File, 'get-file', '')
-ASSOCIATED_MODELS['operation_docs'] = (OperationSource,
- 'get-operationsource', '')
+ASSOCIATED_MODELS['operation_docs'] = (
+ OperationSource, 'get-operationsource', 'get-operationsource-full')
ASSOCIATED_MODELS['operations'] = (Operation, 'get-operation', '')
ASSOCIATED_MODELS['context_records'] = (ContextRecord, 'get-contextrecord',
'get-contextrecord-full')
ASSOCIATED_MODELS['context_records_for_ope'] = (
ContextRecord,
'get-contextrecord-for-ope', 'get-contextrecord-full')
-ASSOCIATED_MODELS['context_records_docs'] = (ContextRecordSource,
- 'get-contextrecordsource', '')
+ASSOCIATED_MODELS['context_records_docs'] = (
+ ContextRecordSource,
+ 'get-contextrecordsource', 'get-contextrecordsource-full')
ASSOCIATED_MODELS['finds'] = (Find, 'get-find', 'get-find-full')
ASSOCIATED_MODELS['finds_for_ope'] = (
Find, 'get-find-for-ope', 'get-find-full')
-ASSOCIATED_MODELS['finds_docs'] = (FindSource, 'get-findsource', '')
+ASSOCIATED_MODELS['finds_docs'] = (
+ FindSource, 'get-findsource', 'get-findsource-full')
@register.simple_tag(takes_context=True)
-def dynamic_table_document(context, caption, associated_model, key, value,
- table_cols='TABLE_COLS', output='html'):
+def dynamic_table_document(
+ context, caption, associated_model, key, value,
+ table_cols='TABLE_COLS', output='html', large=False):
if not table_cols:
table_cols = 'TABLE_COLS'
model, url, url_full = ASSOCIATED_MODELS[associated_model]
@@ -68,6 +71,7 @@ def dynamic_table_document(context, caption, associated_model, key, value,
'no_result': unicode(_("No results")),
'loading': unicode(_("Loading...")),
'encoding': settings.ENCODING or 'utf-8',
+ 'large': large
})
return t.render(context)
else:
@@ -103,3 +107,12 @@ def dynamic_table_document(context, caption, associated_model, key, value,
'data': data
})
return t.render(context)
+
+
+@register.simple_tag(takes_context=True)
+def dynamic_table_document_large(
+ context, caption, associated_model, key,
+ value, table_cols='TABLE_COLS', output='html'):
+ return dynamic_table_document(
+ context, caption, associated_model, key,
+ value, table_cols, output, large=True)
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index f4a8d02e2..59cfe6321 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -350,7 +350,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
if specific_perms and perm not in specific_perms:
continue
cperm = model._meta.app_label + '.' + perm
- if cperm in request.user.get_all_permissions() \
+ if request.user.has_perm(cperm)\
+ or cperm in request.user.get_all_permissions() \
or (request.user.is_authenticated()
and request.user.ishtaruser.has_right(
perm, session=request.session)):
@@ -416,7 +417,12 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
if 'submited' not in request_items:
if default_name in request.session and \
request.session[default_name]:
- dct = {"pk": request.session[default_name]}
+ value = request.session[default_name]
+ if 'basket-' in value:
+ dct = {"basket__pk":
+ request.session[default_name].split('-')[-1]}
+ else:
+ dct = {"pk": request.session[default_name]}
elif not dct:
for name in relative_session_names.keys():
if name in request.session and request.session[name]:
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index b8b104a61..6d9600d0c 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -513,13 +513,15 @@ class JQueryJqGrid(forms.RadioSelect):
def __init__(self, source, form, associated_model, attrs={},
table_cols='TABLE_COLS', multiple=False, multiple_cols=[2],
- new=False, new_message="", source_full=None):
+ new=False, new_message="", source_full=None,
+ multiple_select=False):
self.source = source
self.form = form
self.attrs = attrs
self.associated_model = associated_model
self.table_cols = table_cols
self.multiple = multiple
+ self.multiple_select = multiple_select
self.multiple_cols = multiple_cols
self.new, self.new_message = new, new_message
self.source_full = source_full
@@ -604,6 +606,7 @@ class JQueryJqGrid(forms.RadioSelect):
'remove': unicode(_(u"Remove")),
'sname': name.replace('-', ''),
'multiple': self.multiple,
+ 'multiple_select': self.multiple_select,
'multi_cols': ",".join((u'"%d"' % col
for col in self.multiple_cols))})
t = loader.get_template('blocks/JQueryJqGrid.html')
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index e974942b7..49abe606f 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -510,7 +510,7 @@ class Wizard(NamedUrlWizardView):
adds = {}
# manage attributes relations
if hasattr(self.model, 'ATTRS_EQUIV'):
- for k in other_objs:
+ for k in other_objs.keys():
if k in self.model.ATTRS_EQUIV:
new_k = self.model.ATTRS_EQUIV[k]
if new_k in other_objs: