source: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py @ 7138

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

Move action button to the bottom (looks better in smartphone browsers).

Remove unneeded import.

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