source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py @ 8515

Last change on this file since 8515 was 7833, checked in by Henrik Bettermann, 13 years ago

In some cases we do no longer need to know the fallback language (= portal language) because the fallback language is already set in the cookie when accessing Kofa for the first time.

  • Property svn:keywords set to Id
File size: 11.4 KB
Line 
1## $Id: browser.py 7833 2012-03-10 09:45:25Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""UI components for hostels and related components.
19"""
20import grok
21import sys
22from zope.i18n import translate
23from zope.component import getUtility
24from waeup.kofa.browser import (
25    KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
26    NullValidator)
27from waeup.kofa.browser.breadcrumbs import Breadcrumb
28from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
29from waeup.kofa.browser.layout import default_primary_nav_template
30from waeup.kofa.browser.pages import delSubobjects
31from waeup.kofa.browser.viewlets import (
32    ManageActionButton, PrimaryNavTab)
33from waeup.kofa.browser.layout import jsaction, action
34from waeup.kofa.interfaces import IKofaObject, IKofaUtils
35from waeup.kofa.interfaces import MessageFactory as _
36from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
37from waeup.kofa.hostels.hostel import Hostel
38from waeup.kofa.hostels.interfaces import (
39    IHostelsContainer, IHostel, IBed, IBedAllocateStudent)
40
41def write_log_message(view, message):
42    ob_class = view.__implemented__.__name__.replace('waeup.kofa.','')
43    view.context.loggerInfo(ob_class, message)
44    return
45
46# Save function used for save methods in manager pages
47def msave(view, **data):
48    changed_fields = view.applyData(view.context, **data)
49    # Turn list of lists into single list
50    if changed_fields:
51        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
52    fields_string = ' + '.join(changed_fields)
53    view.context._p_changed = True
54    view.flash(_('Form has been saved.'))
55    if fields_string:
56        write_log_message(view, 'saved: % s' % fields_string)
57    return
58
59class HostelsTab(PrimaryNavTab):
60    """Hostels tab in primary navigation.
61    """
62
63    grok.context(IKofaObject)
64    grok.order(5)
65    grok.require('waeup.viewHostels')
66    template = default_primary_nav_template
67    pnav = 5
68    tab_title = _(u'Hostels')
69
70    @property
71    def link_target(self):
72        return self.view.application_url('hostels')
73
74class HostelsBreadcrumb(Breadcrumb):
75    """A breadcrumb for the hostels container.
76    """
77    grok.context(IHostelsContainer)
78    title = _(u'Hostels')
79
80class HostelBreadcrumb(Breadcrumb):
81    """A breadcrumb for the hostel container.
82    """
83    grok.context(IHostel)
84
85    def title(self):
86        return self.context.hostel_name
87
88class BedBreadcrumb(Breadcrumb):
89    """A breadcrumb for the hostel container.
90    """
91    grok.context(IBed)
92
93    def title(self):
94        co = self.context.getBedCoordinates()
95        return _('Block ${a}, Room ${b}, Bed ${c}',
96            mapping = {'a':co[1], 'b':co[2], 'c':co[3]})
97
98class HostelsContainerPage(KofaDisplayFormPage):
99    """The standard view for hostels containers.
100    """
101    grok.context(IHostelsContainer)
102    grok.name('index')
103    grok.require('waeup.viewHostels')
104    grok.template('containerpage')
105    label = _('Accommodation Section')
106    pnav = 5
107
108class HostelsContainerManageActionButton(ManageActionButton):
109    grok.order(1)
110    grok.context(IHostelsContainer)
111    grok.view(HostelsContainerPage)
112    grok.require('waeup.manageHostels')
113    text = _('Manage accommodation section')
114
115class HostelsContainerManagePage(KofaDisplayFormPage):
116    """The manage page for hostel containers.
117    """
118    grok.context(IHostelsContainer)
119    grok.name('manage')
120    grok.require('waeup.manageHostels')
121    grok.template('containermanagepage')
122    pnav = 5
123    label = _('Manage accommodation section')
124
125    def update(self):
126        warning.need()
127        return super(HostelsContainerManagePage, self).update()
128
129    # It's quite dangerous to remove entire hostels with its content (beds).
130    # Thus, this remove method should be combined with an archiving function.
131    @jsaction(_('Remove selected'))
132    def delHostels(self, **data):
133        form = self.request.form
134        if form.has_key('val_id'):
135            deleted = []
136            child_id = form['val_id']
137            if not isinstance(child_id, list):
138                child_id = [child_id]
139            for id in child_id:
140                deleted.append(id)
141            write_log_message(self, 'deleted: % s' % ', '.join(deleted))
142        delSubobjects(self, redirect='@@manage', tab='2')
143        return
144
145    @action(_('Add hostel'), validator=NullValidator)
146    def addSubunit(self, **data):
147        self.redirect(self.url(self.context, 'addhostel'))
148        return
149
150class HostelAddFormPage(KofaAddFormPage):
151    """Add-form to add a hostel.
152    """
153    grok.context(IHostelsContainer)
154    grok.require('waeup.manageHostels')
155    grok.name('addhostel')
156    #grok.template('hosteladdpage')
157    form_fields = grok.AutoFields(IHostel).omit('beds_reserved')
158    label = _('Add hostel')
159    pnav = 5
160
161    @action(_('Create hostel'))
162    def addHostel(self, **data):
163        hostel = Hostel()
164        self.applyData(hostel, **data)
165        hostel.hostel_id = data[
166            'hostel_name'].lower().replace(' ','-').replace('_','-')
167        try:
168            self.context.addHostel(hostel)
169        except KeyError:
170            self.flash(_('The hostel already exists.'))
171            return
172        self.flash(_('Hostel created.'))
173        write_log_message(self, 'added: % s' % data['hostel_name'])
174        self.redirect(self.url(self.context[hostel.hostel_id], 'index'))
175        return
176
177class HostelDisplayFormPage(KofaDisplayFormPage):
178    """ Page to display hostel data
179    """
180    grok.context(IHostel)
181    grok.name('index')
182    grok.require('waeup.viewHostels')
183    #grok.template('hostelpage')
184    pnav = 5
185
186    @property
187    def label(self):
188        return self.context.hostel_name
189
190class HostelManageActionButton(ManageActionButton):
191    grok.order(1)
192    grok.context(IHostel)
193    grok.view(HostelDisplayFormPage)
194    grok.require('waeup.manageHostels')
195    text = _('Manage')
196    target = 'manage'
197
198class HostelManageFormPage(KofaEditFormPage):
199    """ View to edit hostel data
200    """
201    grok.context(IHostel)
202    grok.name('manage')
203    grok.require('waeup.manageHostels')
204    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
205    form_fields['beds_reserved'].for_display = True
206    grok.template('hostelmanagepage')
207    label = _('Manage hostel')
208    pnav = 5
209    taboneactions = [_('Save')]
210    tabtwoactions = [_('Update all beds'),
211        _('Switch reservation of selected beds'),
212        _('Release selected beds')]
213    not_occupied = NOT_OCCUPIED
214
215    @property
216    def students_url(self):
217        return self.url(grok.getSite(),'students')
218
219    def update(self):
220        datepicker.need() # Enable jQuery datepicker in date fields.
221        tabs.need()
222        datatable.need()
223        self.tab1 = self.tab2 = ''
224        qs = self.request.get('QUERY_STRING', '')
225        if not qs:
226            qs = 'tab1'
227        setattr(self, qs, 'active')
228        super(HostelManageFormPage, self).update()
229        return
230
231    @action(_('Save'))
232    def save(self, **data):
233        msave(self, **data)
234        return
235
236    @action(_('Update all beds'))
237    def updateBeds(self, **data):
238        removed, added, modified, modified_beds = self.context.updateBeds()
239        message = '%d empty beds removed, %d beds added, %d occupied beds modified (%s)' % (
240            removed, added, modified, modified_beds)
241        flash_message = _(
242            '${a} empty beds removed, ${b} beds added, '
243            + '${c} occupied beds modified (${d})',
244            mapping = {'a':removed, 'b':added, 'c':modified, 'd':modified_beds})
245        self.flash(flash_message)
246        write_log_message(self, message)
247        self.redirect(self.url(self.context, '@@manage')+'?tab2')
248        return
249
250    @action(_('Switch reservation of selected beds'))
251    def switchReservations(self, **data):
252        form = self.request.form
253        if form.has_key('val_id'):
254            child_id = form['val_id']
255        else:
256            self.flash(_('No item selected.'))
257            self.redirect(self.url(self.context, '@@manage')+'?tab2')
258            return
259        if not isinstance(child_id, list):
260            child_id = [child_id]
261        switched = [] # for log file
262        switched_translated = [] # for flash message
263        # Here we know that the cookie has been set
264        preferred_language = self.request.cookies.get('kofa.language')
265        for bed_id in child_id:
266            message = self.context[bed_id].switchReservation()
267            switched.append('%s (%s)' % (bed_id,message))
268            m_translated = translate(message, 'waeup.kofa',
269                target_language=preferred_language)
270            switched_translated.append('%s (%s)' % (bed_id,m_translated))
271        if len(switched):
272            message = ', '.join(switched)
273            m_translated = ', '.join(switched_translated)
274            self.flash(_('Successfully switched beds: ${a}',
275                mapping = {'a':m_translated}))
276            write_log_message(self, 'switched: %s' % message)
277            self.redirect(self.url(self.context, '@@manage')+'?tab2')
278        return
279
280    @action(_('Release selected beds'))
281    def releaseBeds(self, **data):
282        form = self.request.form
283        if form.has_key('val_id'):
284            child_id = form['val_id']
285        else:
286            self.flash(_('No item selected.'))
287            self.redirect(self.url(self.context, '@@manage')+'?tab2')
288            return
289        if not isinstance(child_id, list):
290            child_id = [child_id]
291        released = []
292        for bed_id in child_id:
293            message = self.context[bed_id].releaseBed()
294            if message:
295                released.append('%s (%s)' % (bed_id,message))
296        if len(released):
297            message = ', '.join(released)
298            self.flash(_('Successfully released beds: ${a}',
299                mapping = {'a':message}))
300            write_log_message(self, 'released: %s' % message)
301            self.redirect(self.url(self.context, '@@manage')+'?tab2')
302        else:
303            self.flash(_('No allocated bed selected.'))
304            self.redirect(self.url(self.context, '@@manage')+'?tab2')
305        return
306
307class BedManageFormPage(KofaEditFormPage):
308    """ View to edit bed data
309    """
310    grok.context(IBedAllocateStudent)
311    grok.name('index')
312    grok.require('waeup.manageHostels')
313    form_fields = grok.AutoFields(IBedAllocateStudent).omit(
314        'bed_id').omit('bed_number').omit('bed_type')
315    label = _('Allocate student')
316    pnav = 5
317
318    @action(_('Save'))
319    def save(self, **data):
320        msave(self, **data)
321        self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
322        return
323
324    def update(self):
325        if self.context.owner != NOT_OCCUPIED:
326            # Don't use this form for exchanging students.
327            # Beds must be released first before they can be allocated to
328            # other students.
329            self.redirect(self.url(self.context.__parent__, '@@manage')+'?tab2')
330        return
Note: See TracBrowser for help on using the repository browser.