summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ishtar/__init__.py5
-rw-r--r--ishtar/furnitures/forms.py155
-rw-r--r--ishtar/furnitures/menus.py4
-rw-r--r--ishtar/furnitures/models.py24
-rw-r--r--ishtar/furnitures/urls.py6
-rw-r--r--ishtar/furnitures/views.py50
-rw-r--r--ishtar/furnitures/widgets.py95
-rw-r--r--ishtar/templates/default_wizard.html2
-rw-r--r--ishtar/templates/window.html40
-rw-r--r--static/js/ishtar.js21
-rw-r--r--static/media/style.css11
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>&raquo;&nbsp;<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;
+}