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

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

More copyright adjustments.

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