diff options
-rw-r--r-- | ishtar/__init__.py | 5 | ||||
-rw-r--r-- | ishtar/furnitures/forms.py | 155 | ||||
-rw-r--r-- | ishtar/furnitures/menus.py | 4 | ||||
-rw-r--r-- | ishtar/furnitures/models.py | 24 | ||||
-rw-r--r-- | ishtar/furnitures/urls.py | 6 | ||||
-rw-r--r-- | ishtar/furnitures/views.py | 50 | ||||
-rw-r--r-- | ishtar/furnitures/widgets.py | 95 | ||||
-rw-r--r-- | ishtar/templates/default_wizard.html | 2 | ||||
-rw-r--r-- | ishtar/templates/window.html | 40 | ||||
-rw-r--r-- | static/js/ishtar.js | 21 | ||||
-rw-r--r-- | static/media/style.css | 11 |
11 files changed, 371 insertions, 42 deletions
diff --git a/ishtar/__init__.py b/ishtar/__init__.py index d9bcb5701..8f70261d2 100644 --- a/ishtar/__init__.py +++ b/ishtar/__init__.py @@ -1,7 +1,8 @@ # force the retranslation of strings in the registration module from django.utils.translation import ugettext as _ -_("username") -_("email address") +_(u"username") +_(u"email address") +_(u"warehouse") if settings.XHTML2ODT_PATH: import sys sys.path.append(settings.XHTML2ODT_PATH) diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py index 0cd704f53..b88fa19af 100644 --- a/ishtar/furnitures/forms.py +++ b/ishtar/furnitures/forms.py @@ -66,6 +66,46 @@ def clean_duplicated(formset, key_names): _("There are identical items.") items.append(item) +regexp_name = re.compile(r'^[\w\- ]+$', re.UNICODE) +name_validator = validators.RegexValidator(regexp_name, +_(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid') + +class WarehouseForm(forms.Form): + name = forms.CharField(label=_(u"Name"), max_length=40, + validators=[name_validator]) + warehouse_type = forms.ChoiceField(label=_(u"Warehouse type"), + choices=models.WarehouseType.get_types()) + person_in_charge = forms.IntegerField(label=_(u"Person in charge"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-person'), associated_model=models.Person), + validators=[models.valid_id(models.Person)], + required=False) + comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, + required=False) + address = forms.CharField(label=_(u"Address"), widget=forms.Textarea, + required=False) + address_complement = forms.CharField(label=_(u"Address complement"), + widget=forms.Textarea, required=False) + postal_code = forms.CharField(label=_(u"Postal code"), max_length=10, + required=False) + town = forms.CharField(label=_(u"Town"), max_length=30, required=False) + country = forms.CharField(label=_(u"Country"), max_length=30, + required=False) + phone = forms.CharField(label=_(u"Phone"), max_length=18, required=False) + mobile_phone = forms.CharField(label=_(u"Town"), max_length=18, + required=False) + + def save(self): + dct = self.cleaned_data + dct['warehouse_type'] = models.WarehouseType.objects.get( + pk=dct['warehouse_type']) + if 'person_in_charge' in dct and dct['person_in_charge']: + dct['person_in_charge'] = models.Person.objects.get( + pk=dct['person_in_charge']) + new_item = models.Warehouse(**dct) + new_item.save() + return new_item + class FinalForm(forms.Form): final = True form_label = _("Confirm") @@ -544,10 +584,6 @@ def get_now(): value = datetime.datetime.now().strftime(format) return value -regexp_name = re.compile(r'^[\w\- ]+$', re.UNICODE) -name_validator = validators.RegexValidator(regexp_name, -_(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid') - class PersonWizard(Wizard): model = models.Person @@ -1985,3 +2021,114 @@ item_modification_wizard = ItemWizard([ ('final-item_modification', FinalForm)], url_name='item_modification',) +class TreatmentWizard(Wizard): + model = models.Treatment + +class BaseTreatmentForm(forms.Form): + form_label = _(u"Base treatment") + associated_models = {'treatment_type':models.TreatmentType, + 'person':models.Person, + 'location':models.Warehouse} + treatment_type = forms.ChoiceField(label=_(u"Treatment type"), + choices=models.TreatmentType.get_types()) + description = forms.CharField(label=_(u"Description"), + widget=forms.Textarea, required=False) + person = forms.IntegerField(label=_(u"Person"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-person'), associated_model=models.Person), + validators=[models.valid_id(models.Person)]) + location = forms.IntegerField(label=_(u"Location"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-warehouse'), associated_model=models.Warehouse, + new=True), + validators=[models.valid_id(models.Warehouse)]) + start_date = forms.DateField(label=_(u"Start date"), required=False, + widget=widgets.JQueryDate) + end_date = forms.DateField(label=_(u"End date"), required=False, + widget=widgets.JQueryDate) + +class ItemMultipleFormSelection(forms.Form): + form_label = _(u"Upstream items") + associated_models = {'items':models.Item} + items = forms.IntegerField(label="", required=False, + widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), + ItemSelect(), models.Item, multiple=True), + validators=[models.valid_id(models.Item)]) + +class ContainerForm(forms.Form): + form_label = _(u"Container") + associated_models = {'container_type':models.ContainerType,} + reference = forms.CharField(label=_(u"Reference")) + container_type = forms.ChoiceField(label=_(u"Container type"), + choices=models.ContainerType.get_types()) + comment = forms.CharField(label=_(u"Comment"), + widget=forms.Textarea, required=False) + +def check_treatment(form_name, type_key, type_list=[], not_type_list=[]): + type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk + for tpe in type_list] + not_type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk + for tpe in not_type_list] + def func(self, request, storage): + if storage.prefix not in request.session or \ + 'step_data' not in request.session[storage.prefix] or \ + form_name not in request.session[storage.prefix]['step_data'] or\ + form_name + '-' + type_key not in \ + request.session[storage.prefix]['step_data'][form_name]: + return False + try: + type = int(request.session[storage.prefix]['step_data']\ + [form_name][form_name+'-'+type_key]) + return (not type_list or type in type_list) \ + and type not in not_type_list + except ValueError: + return False + return func + +class ResultItemForm(forms.Form): + form_label = _("Resulting item") + associated_models = {'material_type':models.MaterialType} + label = forms.CharField(label=_(u"Label"), + validators=[validators.MaxLengthValidator(60)]) + description = forms.CharField(label=_("Precise description"), + widget=forms.Textarea) + material_type = forms.ChoiceField(label=_("Material type"), + choices=models.MaterialType.get_types()) + volume = forms.IntegerField(label=_(u"Volume")) + weight = forms.IntegerField(label=_(u"Weight")) + item_number = forms.IntegerField(label=_(u"Item number")) + +ResultItemFormSet = formset_factory(ResultItemForm, can_delete=True, + formset=FormSet) +ResultItemFormSet.form_label = _(u"Resulting items") + +UpstreamItemFormSelection = ItemFormSelection + +UpstreamItemFormSelection.form_label = _(u"Upstream item") + +treatment_creation_wizard = TreatmentWizard([ + ('basetreatment-treatment_creation', BaseTreatmentForm), + ('selecitem-treatment_creation', UpstreamItemFormSelection), + ('multiselecitems-treatment_creation', ItemMultipleFormSelection), + ('container-treatment_creation', ContainerForm), + ('resultitem-treatment_creation', ResultItemForm), + ('resultitems-treatment_creation', ResultItemFormSet), + ('final-treatment_creation', FinalForm)], + condition_list={ +'selecitem-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + not_type_list=['physical_grouping']), +'multiselecitems-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['physical_grouping']), +'resultitems-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['split']), +'resultitem-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + not_type_list=['split']), +'container-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['packaging']), + }, + url_name='treatment_creation',) diff --git a/ishtar/furnitures/menus.py b/ishtar/furnitures/menus.py index 5b47b6327..04ebb7968 100644 --- a/ishtar/furnitures/menus.py +++ b/ishtar/furnitures/menus.py @@ -193,6 +193,10 @@ class Menu: model=models.Item, access_controls=['change_item', 'change_own_item']), + MenuItem('treatment_creation', _(u"Add a treatment"), + model=models.Treatment, + access_controls=['add_treatment', + 'add_own_treatment']), ]), ] self.items = {} diff --git a/ishtar/furnitures/models.py b/ishtar/furnitures/models.py index 6afdee470..5069df262 100644 --- a/ishtar/furnitures/models.py +++ b/ishtar/furnitures/models.py @@ -718,8 +718,8 @@ class Warehouse(Address, OwnPerms): warehouse_type = models.ForeignKey(WarehouseType, verbose_name=_(u"Warehouse type")) person_in_charge = models.ForeignKey(Person, - verbose_name=_(u"Person in charge")) - comment = models.TextField(_(u"Comment")) + verbose_name=_(u"Person in charge"), null=True, blank=True) + comment = models.TextField(_(u"Comment"), null=True, blank=True) class Meta: verbose_name = _(u"Warehouse") @@ -732,7 +732,7 @@ class Warehouse(Address, OwnPerms): ) def __unicode__(self): - return unicode(self.warehouse_type) + return u"%s (%s)" % (self.name, unicode(self.warehouse_type)) class ActType(GeneralType): TYPE = (('F', _(u'Archaelogical file')), @@ -795,7 +795,6 @@ class ContainerType(GeneralType): verbose_name_plural = _(u"Container types") class Container(LightHistorizedItem): - reference = models.CharField(_(u"Reference"), max_length=15) location = models.ForeignKey(Warehouse, verbose_name=_(u"Location")) container_type = models.ForeignKey(ContainerType, verbose_name=_("Container type")) @@ -853,13 +852,17 @@ class TreatmentType(GeneralType): verbose_name_plural = _(u"Treatment types") class Treatment(BaseHistorizedItem, OwnPerms): - container = models.ForeignKey(Container, verbose_name=_(u"Container")) + container = models.ForeignKey(Container, verbose_name=_(u"Container"), + blank=True, null=True) + description = models.TextField(_(u"Description"), blank=True, null=True) treatment_type = models.ForeignKey(TreatmentType, verbose_name=_(u"Treatment type")) - location = models.ForeignKey(Warehouse, verbose_name=_(u"Location")) - person = models.ForeignKey(Person, verbose_name=_(u'Person')) - start_date = models.DateField(_(u"Start date")) - end_date = models.DateField(_(u"End date")) + location = models.ForeignKey(Warehouse, verbose_name=_(u"Location"), + blank=True, null=True) + person = models.ForeignKey(Person, verbose_name=_(u"Person"), + blank=True, null=True) + start_date = models.DateField(_(u"Start date"), blank=True, null=True) + end_date = models.DateField(_(u"End date"), blank=True, null=True) history = HistoricalRecords() class Meta: @@ -872,9 +875,6 @@ class Treatment(BaseHistorizedItem, OwnPerms): ("delete_own_treatment", ugettext(u"Can delete own Treatment")), ) - def __unicode__(self): - return self.item - class AuthorType(GeneralType): class Meta: verbose_name = _(u"Author type") diff --git a/ishtar/furnitures/urls.py b/ishtar/furnitures/urls.py index 5e28d6fed..59e9ae6f2 100644 --- a/ishtar/furnitures/urls.py +++ b/ishtar/furnitures/urls.py @@ -73,6 +73,8 @@ urlpatterns = patterns('', ishtar_forms.item_creation_wizard, name='item_creation'), url(BASE_URL + r'item_modification/(?P<step>.+)$', ishtar_forms.item_modification_wizard, name='item_modification'), + url(BASE_URL + r'treatment_creation/(?P<step>.+)$', + ishtar_forms.treatment_creation_wizard, name='treatment_creation'), ) for section in menu.childs: for menu_item in section.childs: @@ -95,6 +97,8 @@ urlpatterns += patterns('ishtar.furnitures.views', name='autocomplete-organization'), url(BASE_URL + r'autocomplete-file/$', 'autocomplete_file', name='autocomplete-file'), + url(BASE_URL + r'autocomplete-warehouse/$', 'autocomplete_warehouse', + name='autocomplete-warehouse'), url(BASE_URL + r'get-file/(?P<type>.+)?$', 'get_file', name='get-file'), url(BASE_URL + r'show-file/(?P<pk>.+)?/(?P<type>.+)?$', 'show_file', @@ -117,4 +121,6 @@ urlpatterns += patterns('ishtar.furnitures.views', name='get-contextrecord'), url(BASE_URL + r'get-item/(?P<type>.+)?$', 'get_archaeologicalitem', name='get-item'), + url(BASE_URL + r'new-warehouse/(?P<parent_name>.+)?/(?P<parent_pk>.+)?$', + 'new_warehouse', name='new-warehouse'), ) diff --git a/ishtar/furnitures/views.py b/ishtar/furnitures/views.py index 39c6bb66c..894a8f0cf 100644 --- a/ishtar/furnitures/views.py +++ b/ishtar/furnitures/views.py @@ -70,6 +70,9 @@ def update_current_item(request): return HttpResponse('ok') def check_permission(request, action_slug, obj_id=None): + if action_slug not in menu.items: + #! TODO + return True if obj_id: return menu.items[action_slug].is_available(request.user, obj_id) return menu.items[action_slug].can_be_available(request.user) @@ -384,6 +387,53 @@ get_contextrecord = get_item(models.ContextRecord, get_archaeologicalitem = get_item(models.Item, 'get_archaeologicalitem', 'item',) +def autocomplete_warehouse(request): + if not request.user.has_perm('furnitures.view_warehouse', models.Warehouse)\ + and not request.user.has_perm('furnitures.view_own_warehouse', + models.Warehouse) : + return HttpResponse(mimetype='text/plain') + if not request.GET.get('term'): + return HttpResponse(mimetype='text/plain') + q = request.GET.get('term') + query = Q() + for q in q.split(' '): + extra = Q(name__icontains=q) | \ + Q(warehouse_type__label__icontains=q) + query = query & extra + limit = 15 + warehouses = models.Warehouse.objects.filter(query)[:limit] + data = json.dumps([{'id':warehouse.pk, 'value':unicode(warehouse)} + for warehouse in warehouses]) + return HttpResponse(data, mimetype='text/plain') + +def new_item(model): + def func(request, parent_name='', parent_pk=''): + model_name = model._meta.object_name + if not parent_name: + parent_name = model_name.lower() + if not check_permission(request, 'add_'+model_name.lower()): + not_permitted_msg = ugettext(u"Operation not permitted.") + return HttpResponse(not_permitted_msg) + frm = getattr(ishtar_forms, model_name + 'Form') + dct = {'title':unicode(_(u'New ')) + unicode(_(model_name.lower()))} + if request.method == 'POST': + dct['form'] = frm(request.POST) + if dct['form'].is_valid(): + new_item = dct['form'].save() + dct['new_item_label'] = unicode(new_item) + dct['new_item_pk'] = new_item.pk + dct['parent_name'] = parent_name + dct['parent_pk'] = parent_pk + return render_to_response('window.html', dct, + context_instance=RequestContext(request)) + else: + dct['form'] = frm() + return render_to_response('window.html', dct, + context_instance=RequestContext(request)) + return func + +new_warehouse = new_item(models.Warehouse) + def action(request, action_slug, obj_id=None, *args, **kwargs): """ Action management diff --git a/ishtar/furnitures/widgets.py b/ishtar/furnitures/widgets.py index 5d184f123..5d2fc7c38 100644 --- a/ishtar/furnitures/widgets.py +++ b/ishtar/furnitures/widgets.py @@ -24,7 +24,7 @@ from django.forms.widgets import flatatt from django.utils.encoding import smart_unicode
from django.utils.html import escape
from django.utils.simplejson import JSONEncoder
-from django.core.urlresolvers import resolve
+from django.core.urlresolvers import resolve, reverse
from django.utils.translation import ugettext_lazy as _
from ishtar import settings
@@ -50,7 +50,8 @@ class JQueryDate(forms.TextInput): return rendered
class JQueryAutoComplete(forms.TextInput):
- def __init__(self, source, associated_model=None, options={}, attrs={}):
+ def __init__(self, source, associated_model=None, options={}, attrs={},
+ new=False):
"""
Source can be a list containing the autocomplete values or a
string containing the url used for the request.
@@ -62,6 +63,7 @@ class JQueryAutoComplete(forms.TextInput): if len(options) > 0:
self.options = JSONEncoder().encode(options)
self.attrs.update(attrs)
+ self.new = new
def render_js(self, field_id):
if isinstance(self.source, list):
@@ -111,7 +113,13 @@ objects.get(pk=value)) attrs_select['id'] = 'id_select_%s' % name
if 'class' not in attrs_select:
attrs_select['class'] = 'autocomplete'
- return u'''<input%(attrs_select)s/>\
+ new = ''
+ if self.new:
+ model_name = self.associated_model._meta.object_name.lower()
+ new = u' <a href="#" onclick="open_window(\'%s\');">%s</a>' % \
+ (reverse('new-' + model_name, args=[attrs_select['id'], attrs_hidden['id']]),
+ unicode(_(u"Add")))
+ html = u'''<input%(attrs_select)s/>%(new)s\
<input type="hidden"%(attrs_hidden)s/>\
<script type="text/javascript"><!--//
$(function() {%(js)s});//--></script>
@@ -119,7 +127,9 @@ objects.get(pk=value)) 'attrs_select' : flatatt(attrs_select),
'attrs_hidden' : flatatt(attrs_hidden),
'js' : self.render_js(name),
+ 'new':new
}
+ return html
class JQueryJqGrid(forms.RadioSelect):
COL_TPL = "{name:'%(idx)s', index:'%(idx)s', sortable:true}"
@@ -128,15 +138,17 @@ class JQueryJqGrid(forms.RadioSelect): settings.COUNTRY),
'%s/js/jquery.jqGrid.min.js' % settings.MEDIA_URL,
]
- css = {'all':['%s/media/ui.jqgrid.css' % settings.MEDIA_URL]}
+ css = {'all':['%s/media/ui.jqgrid.css' % settings.MEDIA_URL,
+ ]}
def __init__(self, source, form, associated_model, attrs={},
- table_cols='TABLE_COLS'):
+ table_cols='TABLE_COLS', multiple=False):
self.source = source
self.form = form
self.attrs = attrs
self.associated_model = associated_model
self.table_cols = table_cols
+ self.multiple = multiple
def render(self, name, value=None, attrs=None):
rendered = unicode(self.form)
@@ -171,18 +183,25 @@ class JQueryJqGrid(forms.RadioSelect): encoding = settings.ENCODING or 'utf-8'
rendered += """
<div id="foot_%s" class="gridfooter"><a href="%scsv" target="_blank">%s (%s)</a></div>
-<input type="hidden" id="hidden_%s" name="%s">""" % (name,
- unicode(self.source), unicode(_("Export as CSV")), encoding, name, name)
+""" % (name, unicode(self.source), unicode(_("Export as CSV")), encoding)
+ if self.multiple:
+ rendered += '''
+<input type="button" id="add_button_%s" value="%s"/>
+<ul id='selectmulti_%s' class='selectmulti'>
+</ul>
+''' % (name, unicode(_("Add")), name)
+ rendered += '<input type="hidden" id="hidden_%s" name="%s"/>' % (name,
+ name)
+ dct = {'name':name, 'col_names':col_names, 'extra_cols':extra_cols,
+ 'source':unicode(self.source), 'col_idx':col_idx,
+ 'no_result':unicode(_("No results")), 'loading':unicode(_("Loading...")),
+ 'remove':unicode(_("Remove")), 'sname':name.replace('-', '')}
+
rendered += """
<script type="text/javascript">
var query_vars = new Array(%(col_idx)s);
jQuery(document).ready(function(){
-jQuery("#submit_form").click(function (){
- var mygrid = jQuery("#grid_%(name)s");
- jQuery("#hidden_%(name)s").val(mygrid.getGridParam('selrow'));
- return true;
-});
-jQuery("#search_%(name)s").click(function (){
+ jQuery("#search_%(name)s").click(function (){
var data = "";
for (idx in query_vars)
{
@@ -198,17 +217,17 @@ jQuery("#search_%(name)s").click(function (){ mygrid.setGridParam({url:url});
mygrid.trigger("reloadGrid");
return false;
-});
+ });
-jQuery("#grid_%(name)s").jqGrid({
+ jQuery("#grid_%(name)s").jqGrid({
url:'%(source)s',
datatype: "json",
mtype: 'GET',
colNames:['id', '', %(col_names)s],
colModel:[
-{name:'id', index:'id', hidden:true},
-{name:'link', index:'link', width:80},
-%(extra_cols)s
+ {name:'id', index:'id', hidden:true},
+ {name:'link', index:'link', width:80},
+ %(extra_cols)s
],
sortname: 'value',
viewrecords: true,
@@ -220,11 +239,41 @@ jQuery("#grid_%(name)s").jqGrid({ pginput: false,
width:740,
jsonReader : {repeatitems: false}
-});
+ });
+""" % dct
+ if self.multiple:
+ rendered += """
+ var selItems_%(sname)s = new Array();
+ jQuery("#add_button_%(name)s").click(function (){
+ var mygrid = jQuery("#grid_%(name)s");
+ var idx = mygrid.getGridParam('selrow');
+ var label = mygrid.getCell(idx, 2);
+ for (id in selItems_%(sname)s){
+ if(selItems_%(sname)s[id] == idx){
+ return false;
+ }
+ }
+ selItems_%(sname)s.push(idx);
+ jQuery("#selectmulti_%(name)s").append(
+ "<li id='selected_%(name)s_"+idx+"'>"+label+" <a href='#' class='remove' onclick=\\"multiRemoveItem('selItems_%(sname)s', '%(name)s', "+ idx +");return false;\\">%(remove)s</a></li>");
+ return true;
+ });
+ jQuery("#submit_form").click(function (){
+ jQuery("#hidden_%(name)s").val(selItems_%(sname)s);
+ return true;
+ });
+""" % dct
+ else:
+ rendered += """
+ jQuery("#submit_form").click(function (){
+ var mygrid = jQuery("#grid_%(name)s");
+ jQuery("#hidden_%(name)s").val(mygrid.getGridParam('selrow'));
+ return true;
+ });
+""" % dct
+ rendered += """
});
</script>
-""" % {'name':name, 'col_names':col_names, 'extra_cols':extra_cols,
- 'source':unicode(self.source), 'col_idx':col_idx,
- 'no_result':unicode(_("No results")), 'loading':unicode(_("Loading..."))}
- return rendered
+"""
+ return mark_safe(rendered)
diff --git a/ishtar/templates/default_wizard.html b/ishtar/templates/default_wizard.html index 70563786b..c2a42dad5 100644 --- a/ishtar/templates/default_wizard.html +++ b/ishtar/templates/default_wizard.html @@ -5,7 +5,7 @@ {{form.media}} {% endblock %} {% block content %} -<form action="." method="post">{% csrf_token %} +<form action="." method="post" name='wizard'>{% csrf_token %} <ul id='form_path'> {% for step in previous_steps %} <li>» <button name="form_prev_step" value="{{forloop.counter0}}">{{step.form_label}}</button></li> diff --git a/ishtar/templates/window.html b/ishtar/templates/window.html new file mode 100644 index 000000000..3c52a3d90 --- /dev/null +++ b/ishtar/templates/window.html @@ -0,0 +1,40 @@ +{% load i18n %} +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + +<head> + <link rel="shortcut icon" href="{{MEDIA_URL}}/media/images/favicon.png"> + <title>{% block title %}Ishtar{% if APP_NAME %} - {{APP_NAME}}{%endif%}{% endblock %} + </title> + <script language="javascript" type="text/javascript"> + var url_path = "{{URL_PATH}}"; + </script> + <script language="javascript" type="text/javascript" src="{{JQUERY_URL}}"></script> + <script language="javascript" type="text/javascript" src="{{JQUERY_UI_URL}}jquery-ui.js"></script> + <script language="javascript" type="text/javascript" src="{{JQUERY_UI_URL}}ui/i18n/jquery.ui.datepicker-{{COUNTRY}}.js"></script> + <script language="javascript" type="text/javascript" src="{{MEDIA_URL}}/js/ishtar.js"></script> + <link type="text/css" href="{{JQUERY_UI_URL}}css/smoothness/jquery-ui.css" rel="stylesheet" /> + <link rel="stylesheet" href="{{MEDIA_URL}}/media/style.css" /> + {% block extra_head %} + {% endblock %} +</head> +<body> +{% if new_item_label %} +<script type='text/javascript' language='javascript'> +save_and_close_window("{{parent_name}}", "{{parent_pk}}", "{{new_item_label}}", "{{new_item_pk}}"); +</script> +{% endif %} +<div id="window_content"> + <h3>{{title}}</h3> + <form action="." method="post">{% csrf_token %} + <table> + {{form.as_table}} + <tr><td colspan='2' class='submit_button'><input type="submit" id="submit_new_item" value="{% trans "Add" %}"/></td></tr> + </table> + </form> + +</div> +</body> + +</html> diff --git a/static/js/ishtar.js b/static/js/ishtar.js index 784480f81..e32d2f1fa 100644 --- a/static/js/ishtar.js +++ b/static/js/ishtar.js @@ -58,7 +58,28 @@ function load_window(url){ error:function(XMLHttpRequest, textStatus, errorThrows){ } }); +} +function open_window(url){ + var newwindow = window.open(url, 'Ishtar', + 'height=400,width=550,scrollbars=yes'); + if (window.focus) {newwindow.focus()} + return false; +} +function save_and_close_window(name_label, name_pk, item_name, item_pk){ + var main_page = opener.document.wizard; + main_page[name_label] = item_name; + main_page[name_pk] = item_pk; + opener.focus(); + self.close(); +} +function multiRemoveItem(selItems, name, idx){ + for(id in selItems){ + if(selItems[id] == idx){ + selItems.pop(id); + } + } + jQuery("#selected_"+name+"_"+idx).remove(); } diff --git a/static/media/style.css b/static/media/style.css index 7868a4671..3323def19 100644 --- a/static/media/style.css +++ b/static/media/style.css @@ -346,3 +346,14 @@ table.confirm tr.spacer td:last-child{ font-style:italic; } +ul.selectmulti{ + list-style-type:none; +} + +ul.selectmulti li a.remove{ + padding-left:100px; +} + +td.submit_button{ + text-align:center; +} |