## $Id: browser.py 7747 2012-03-02 08:08:31Z henrik $ ## ## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## """UI components for accesscodes. """ import grok from datetime import datetime from hurry.workflow.interfaces import InvalidTransitionError from waeup.sirp.browser.resources import datatable from waeup.sirp.browser import SIRPPage, SIRPAddFormPage, NullValidator from waeup.sirp.browser.breadcrumbs import Breadcrumb from waeup.sirp.browser.viewlets import ( AdminTask, AddActionButton, SearchActionButton, BatchOpButton, ManageLink) from waeup.sirp.interfaces import ISIRPObject from waeup.sirp.interfaces import MessageFactory as _ from waeup.sirp.accesscodes.interfaces import ( IAccessCodeBatchContainer, IAccessCodeBatch, ) from waeup.sirp.accesscodes.catalog import search from waeup.sirp.browser.layout import action grok.context(ISIRPObject) class BatchContainerPage(SIRPPage): grok.name('index') grok.context(IAccessCodeBatchContainer) grok.template('batchcontainer') grok.require('waeup.manageACBatches') archive_button = _('Archive') delete_button = _('Archive and delete') label = _('Access Code Batches') pnav = 0 def update(self, batches=None, archive=None, delete=None): if archive is None and delete is None: return if not batches: self.flash(_('No batch selected.')) return if isinstance(batches, basestring): batches = [batches] ob_class = self.__implemented__.__name__.replace('waeup.sirp.','') for name in batches: batch = self.context[name] csv_file = batch.archive() self.flash(_('Archived ${a} (${b})', mapping = {'a':name, 'b':csv_file})) message = 'archived: %s (%s)' % (name,csv_file) self.context.logger_info(ob_class, message) if delete is None: continue del self.context[name] self.flash(_('Deleted batch ${a}', mapping = {'a':name})) message = 'deleted: %s' % name self.context.logger_info(ob_class, message) class AddBatchPage(SIRPAddFormPage): grok.name('add') grok.context(IAccessCodeBatchContainer) grok.require('waeup.manageACBatches') label = _('Create Access Code Batch') pnav = 0 form_fields = grok.AutoFields(IAccessCodeBatch).select( 'prefix', 'entry_num', 'cost') @action(_('Create batch'), style='primary') def createBatch(self, **data): creator = self.request.principal.id creation_date = datetime.now() data.update(creation_date=creation_date, creator=creator) batch = self.context.createBatch(**data) csv_file = batch.createCSVLogFile() self.context._p_changed = True self.flash(_('Batch created (${a} entries)', mapping = {'a':data['entry_num']})) self.flash(_('Data written to ${a}', mapping = {'a':csv_file})) ob_class = self.__implemented__.__name__.replace('waeup.sirp.','') message = 'created: %s (%d, %f)' % ( csv_file, data['entry_num'], data['cost']) self.context.logger_info(ob_class, message) self.redirect(self.url(self.context)) @action(_('Cancel'), validator=NullValidator) def cancel(self, *args, **kw): self.flash(_('Batch creation cancelled.')) self.redirect(self.url(self.context)) class ReimportBatchPage(SIRPPage): """Screen for reimporting AC batches. """ grok.name('reimport') grok.context(IAccessCodeBatchContainer) grok.template('reimportbatchpage') grok.require('waeup.manageACBatches') reimport_button = _('Reimport') cancel_button = _('Cancel') label = _('Reimport Access Code Batches') pnav = 0 def update(self, filenames=None, reimport=None, cancel=None): if cancel is not None: self.flash(_('Reimport cancelled.')) self.redirect(self.url(self.context)) return if reimport is None: return if not filenames: self.flash(_('No file chosen. Action cancelled.')) self.redirect(self.url(self.context)) return if isinstance(filenames, basestring): filenames = [filenames] userid = self.request.principal.id for filename in filenames: try: self.context.reimport(filename, userid) except KeyError: self.flash(_('This batch already exists: ${a}', mapping = {'a':filename})) continue self.flash(_('Successfully reimported: ${a}', mapping = {'a':filename})) ob_class = self.__implemented__.__name__.replace('waeup.sirp.','') message = 'reimported: %s' % filename self.context.logger_info(ob_class, message) self.redirect(self.url(self.context)) class BatchContainerSearchPage(SIRPPage): grok.name('search') grok.context(IAccessCodeBatchContainer) grok.template('searchpage') grok.require('waeup.manageACBatches') pnav = 0 label = _('Search and Manage Access Codes') search_button = _('Search') disable_button = _('Disable ACs') enable_button = _('Enable ACs') def update(self, *args, **kw): datatable.need() form = self.request.form self.hitlist = [] if 'searchterm' in form and form['searchterm']: self.searchterm = form['searchterm'] self.searchtype = form['searchtype'] elif 'old_searchterm' in form: self.searchterm = form['old_searchterm'] self.searchtype = form['old_searchtype'] else: return if not 'entries' in form: self.hitlist = search(query=self.searchterm, searchtype=self.searchtype, view=self) return entries = form['entries'] if isinstance(entries, basestring): entries = [entries] ob_class = self.__implemented__.__name__.replace('waeup.sirp.','') for entry in entries: if 'disable' in form: try: comment = _(u"disabled") self.context.disable(entry, comment) self.flash(_('${a} disabled.', mapping = {'a':entry})) message = 'disabled: %s' % entry self.context.logger_info(ob_class, message) except InvalidTransitionError: self.flash(_('${a}: Disable transition not allowed.', mapping = {'a':entry})) elif 'enable' in form: try: comment = _(u"re-enabled") self.context.enable(entry, comment) self.flash(_('${a} (re-)enabled.', mapping = {'a':entry})) message = '(re-)enabled: %s' % entry self.context.logger_info(ob_class, message) except InvalidTransitionError: self.flash(_('${a}: Re-enable transition not allowed.', mapping = {'a':entry})) self.hitlist = search(query=self.searchterm, searchtype=self.searchtype, view=self) return class BatchContainerBreadcrumb(Breadcrumb): """A breadcrumb for ac batch containers. """ grok.require('waeup.manageACBatches') grok.context(IAccessCodeBatchContainer) title = _(u'Access Code Batches') parent_viewname = 'administration' #class BatchContainerSearchBreadcrumb(Breadcrumb): # """A breadcrumb for ac batch containers search page. # """ # grok.require('waeup.manageACBatches') # grok.context(IAccessCodeBatchContainer) # grok.name('search') # title = u'Search Access Codes' # viewname = 'search' # parent_viewname = 'index' class AdminTaskManageACBatches(AdminTask): """Entry on administration page that links to batch container. """ grok.order(5) grok.require('waeup.manageACBatches') grok.template('admintaskacbatches') link_title = _('Access Code Batches') target_viewname = 'accesscodes' class CreateBatchButton(AddActionButton): """Action button on batch container page which links to batch creation. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') text = _('Add Access Code Batch') class ReimportBatchButton(BatchOpButton): """Action button on batch container page which links to batch reimport. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') target = 'reimport' text = _('Reimport Access Code Batch') class SearchAccessCodeButton(SearchActionButton): """Action button on batch container page which links to search. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') text = _('Search Access Codes') class ManageAccessCodes(ManageLink): """Link in upper left box to access code management. """ grok.order(6) grok.require('waeup.manageACBatches') link = u'accesscodes' text = _(u'Access Codes')