def renderBookedTable(self): prefix = "remove_item" available_columns = self.columns() available_columns[0].cell_formatter = label_cell_formatter_factory(prefix) available_columns[2].title = _('Reserved by others') columns = list(available_columns) title=_('Release resource') # XXX: this getter is just plain wrong getter = lambda r: r.__name__ remove_column = ImageInputColumn( prefix, name='action', title=title, alt=title, library='schooltool.skin.flourish', image='remove-icon.png', id_getter=getter) columns.append(remove_column) formatter = zc.table.table.FormFullFormatter( self.context, self.request, self.getBookedItems(), columns=columns, sort_on=self.sortOn(), prefix="booked") formatter.cssClasses['table'] = 'data' return formatter()
def renderAvailableTable(self): prefix = "add_item" available_columns = self.columns() available_columns[0].cell_formatter = label_cell_formatter_factory(prefix) available_columns[2].title = _('Reserved by others') columns = list(available_columns) title=_('Reserve resource') # XXX: this getter is just plain wrong getter = lambda r: r.__name__ add_column = ImageInputColumn( prefix, name='action', title=title, alt=title, library='schooltool.skin.flourish', image='add-icon.png', id_getter=getter) columns.append(add_column) formatter = zc.table.table.FormFullFormatter( self.context, self.request, self.filter(self.availableResources), columns=columns, batch_start=self.batch.start, batch_size=self.batch.size, sort_on=self.sortOn(), prefix="available") formatter.cssClasses['table'] = 'data' return formatter()
def columns(self): task_id = table.column.IndexedGetterColumn( index='task_id', name='task_id', cell_formatter=self.task_id_formatter, title=_(u'Task ID'), getter=lambda i, f: i.task_id, subsort=True) signature = table.table.GetterColumn( name='signature', title=_(u'Signature'), getter=lambda i, f: i.signature, subsort=True) internal_state = table.column.IndexedGetterColumn( index='internal_state', name='internal_state', title=_(u'Internal state'), getter=lambda i, f: i, cell_formatter=task_state_formatter, subsort=True) directlyProvides(internal_state, ISortableColumn) scheduled = table.column.IndexedGetterColumn( index='scheduled', name='scheduled', title=_(u'Scheduled'), getter=lambda i, f: i.scheduled, cell_formatter=table.table.datetime_formatter, subsort=True) directlyProvides(scheduled, ISortableColumn) return [task_id, signature, internal_state, scheduled]
def update(self): result = [] periods = self.getSessionData()['period_names'] for i in range(self.numPeriods()): name = 'period_%d' % i if name not in self.request: self.error = _('Please provide all periods.') return False result.append(self.request[name]) # Validate that all periods are selected seen = set() errors = set() for period in result: if period not in seen: seen.add(period) else: errors.add(period) if errors: self.error = _('The following periods were selected more' ' than once: $periods', mapping={'periods': ', '.join(errors)}) return False day_names = self.getSessionData()['day_names'] self.getSessionData()['periods_order'] = [result] * len(day_names) return True
def columns(self): first_name = table.column.LocaleAwareGetterColumn( name='first_name', title=_(u'First Name'), getter=lambda i, f: i.first_name, subsort=True) last_name = table.column.LocaleAwareGetterColumn( name='last_name', title=_(u'Last Name'), getter=lambda i, f: i.last_name, subsort=True) result = [first_name, last_name] optional_column_token = self.request.get('optional') if optional_column_token is not None: provider_name, column_name = optional_column_token.split('.') provider = getAdapter(self.view, IColumnProvider, name=provider_name) optional_column = None for column in provider.columns: if column.name == column_name: optional_column = column break if optional_column is not None: result.append(optional_column) return result
def email_container_table_columns(): from_address = GetterColumn(name='from_address', title=_(u'From'), getter=lambda i, f: i.from_address, subsort=True) directlyProvides(from_address, ISortableColumn) to_addresses = GetterColumn(name='to_addresses', title=_(u'To'), getter=lambda i, f: i.to_addresses, cell_formatter=to_addresses_formatter, subsort=True) directlyProvides(to_addresses, ISortableColumn) subject = GetterColumn(name='subject', title=_(u'Subject'), getter=lambda i, f: i.subject, cell_formatter=subject_formatter, subsort=True) directlyProvides(subject, ISortableColumn) time_created = GetterColumn(name='time_created', title=_(u'Created on'), getter=lambda i, f: i.time_created, cell_formatter=table.table.datetime_formatter, subsort=True) directlyProvides(time_created, ISortableColumn) time_sent = GetterColumn(name='time_sent', title=_(u'Last time tried'), getter=lambda i, f: i.time_sent, cell_formatter=table.table.datetime_formatter, subsort=True) directlyProvides(time_sent, ISortableColumn) return [from_address, to_addresses, subject, time_created, time_sent]
def update(self): """Read and validate form data, and update model if necessary. Also choose the correct template to render. """ self.field_errors = [] self.template = self.select_template if 'CANCEL' in self.request: self.request.response.redirect( absoluteURL(self.context, self.request)) return if 'date' in self.request: try: self.date = parse_date(self.request['date']) except ValueError: self.error = _("Invalid date. Please use YYYY-MM-DD format.") else: self.term = getTermForDate(self.date) if self.term is None: self.error = _("The date does not belong to any term.") self.date = None if self.date: self.template = self.form_template if self.date and 'SUBMIT' in self.request: replacements = self.extractMeetings() if self.field_errors: self.error = self.field_error_message else: self.updateExceptions(replacements) self.request.response.redirect( absoluteURL(self.context, self.request))
def populate(self, states): super(GroupMembershipStatesStartup, self).populate(states) states.add(_('Pending'), INACTIVE, 'i') states.add(_('Member'), ACTIVE, 'a') states.add(_('Suspended'), INACTIVE, 's') states.add(_('Removed'), INACTIVE, 'r') states.add(_('Added in error'), INACTIVE, 'e')
def toFieldValue(self, value): if value is None or value == '': return z3c.form.interfaces.NOT_CHANGED if value == 'delete': # XXX: delete checkbox was marked return None data = value.read() try: image = Image.open(StringIO(data)) if image.format not in ('JPEG', 'PNG'): raise IOError() except (IOError,): raise FormatterValidationError( _('The file uploaded is not a JPEG or PNG image'), value) size = len(data) if size > self.field.max_file_size: msg = _('The image uploaded cannot be larger than ${size} MB') raise FormatterValidationError( format_message( msg, mapping={'size': '%.2f' % (float(size) / (10**6))}), value) data = self.processImage(image) f = ImageFile() self.updateFile(f, data) return f
def sizeForDisplay(self): num = self.sizeForSorting()[1] if num == 1: msgid = _("1 person") else: msgid = _("${number} persons", mapping={'number': num}) return msgid
def parseCSVRows(self, rows): """Parse rows (a list of strings) in CSV format. Returns a list of rows as lists. rows must be in the encoding specified during construction of BaseCSVImportView; the returned values are in unicode. If the provided data is invalid, self.errors.generic will be updated and None will be returned. """ result = [] reader = csv.reader(rows) line = 0 try: while True: line += 1 values = [v.strip() for v in reader.next()] if self.charset: values = [unicode(v, self.charset) for v in values] # Remove trailing empty cells. while values and not values[-1].strip(): del values[-1] result.append(values) except StopIteration: return result except csv.Error: error_msg = _("Error in CSV data, line ${line_no}", mapping={'line_no': line}) self.errors.generic.append(error_msg) except UnicodeError: error_msg = _("Conversion to unicode failed in line ${line_no}", mapping={'line_no': line}) self.errors.generic.append(error_msg)
def update(self): result = [] periods = self.periods() numSlots = self.numSlots() for i in range(len(self.days())): day = [] for j in range(numSlots[i]): name = 'period_%d_%d' % (i, j) if name not in self.request: self.error = _('Please provide all periods.') return False day.append(self.request[name]) result.append(day) # Validate that all periods are selected errors = set() for i, day in enumerate(self.days()): seen = set() for period in result[i]: if period not in seen: seen.add(period) else: error = _("$period on day $day", mapping={'period': period, 'day': self.days()[i]}) errors.add(translate(error, context=self.request)) if errors: self.error = _('The following periods were selected more' ' than once: $periods', mapping={'periods': ', '.join(errors)}) return False self.getSessionData()['periods_order'] = result return True
def updateWidgets(self): super(FlourishTermAddView, self).updateWidgets() description = _(u'The year starts ${year_start}', mapping={'year_start': self.dateString(self.context.first)}) self.widgets['first'].field.description = description description = _(u'The year ends ${year_end}', mapping={'year_end': self.dateString(self.context.last)}) self.widgets['last'].field.description = description
def choices(self): session = self.getSessionData() if session['cycle'] == 'rotating': choices = ((True, _("Have names")),) else: choices = ((True, _("Have names")), (False, _("Designated by time"))) return choices
def subtitle(self): cursor_yw = year_week(self.cursor) if cursor_yw == year_week(self.today): return _("This Week") if cursor_yw == year_week(self.today - datetime.timedelta(weeks=1)): return _("Last Week") if cursor_yw == year_week(self.today + datetime.timedelta(weeks=1)): return _("Next Week") return None
def getColumnsAfter(self): result = [ table.DateColumn(title=_("First Day"), name='first', getter=lambda x, y: x.first), table.DateColumn(title=_("Last Day"), getter=lambda x, y: x.last), FlourishActiveSchoolYearColumn(title=_("Active")), ] return result
def types(self): options = [ {'id': 'equipment', 'title': _('Equipment')}, {'id': 'location', 'title': _('Location')}, {'id': 'resource', 'title': _('Resource')}, ] return options
def subtitle(self): if self.cursor == self.today: return _("Today") if self.cursor == self.today + datetime.timedelta(days=1): return _("Tomorrow") if self.cursor == self.today - datetime.timedelta(days=1): return _("Yesterday") if (year_week(self.cursor) == year_week(self.today) and self.cursor > self.today): return day_of_week_names[self.cursor.weekday()] return None
def set_server_status_message(form, container): form.widgets['server_status'].mode = 'display' if container.enabled: info = '%s:%s' % (container.hostname, container.port or '25') form.widgets['server_status'].value = _('Enabled on ${info}', mapping={'info': info}) form.widgets['server_status'].style = u'color: green;' else: form.widgets['server_status'].value = _('Disabled') form.widgets['server_status'].style = u'color: red;'
def serverStatus(self): result = {} if self.context.hostname: info = '%s:%s' % (self.context.hostname, self.context.port or '25') result['status'] = _('Enabled on ${info}', mapping={'info': info}) result['color'] = 'green' else: result['status'] = _('Disabled') result['color'] = 'red' return result
def populate(self, states): super(StudentMembershipStatesStartup, self).populate(states) states.add(_('Pending'), INACTIVE, 'i') states.add(_('Pre-enrolled'), INACTIVE+PREENROLLED, 'p') states.add(_('Enrolled'), ACTIVE, 'a') states.add(_('Graduated/Active'), ACTIVE+GRADUATED, 'c') states.add(_('Graduated/Inactive'), INACTIVE+GRADUATED, 'r') states.add(_('Withdrawn'), INACTIVE, 'w') states.add(_('Added in error'), INACTIVE, 'e') states.describe(INACTIVE+PREENROLLED, _('Pre-enrolled')) states.describe(ACTIVE+GRADUATED, _('Graduated/Active')) states.describe(INACTIVE+GRADUATED, _('Graduated/Inactive'))
def columns(self): title = GetterColumn( name='title', title=_(u"Title"), getter=lambda i, f: i.title, subsort=True) type = GetterColumn( name='type', title=_(u"Type"), getter=lambda i, f: i.cal_type, subsort=True) return [title, type]
def columns(self): default = table.table.TableContent.columns(self) description = zc.table.column.GetterColumn( name='description', title=_('Description'), getter=lambda i, f: i.description or '', ) schoolyear = SchoolYearColumn( name='schoolyear', title=_(u'School Year'), subsort=True) directlyProvides(schoolyear, ISortableColumn) return default + [description, schoolyear]
def toFieldValue(self, value): """See interfaces.IDataConverter""" if value == u"": return self.field.missing_value try: value = parse_date(value) except (ValueError,): raise FormatterValidationError(_("The datetime string did not match the pattern yyyy-mm-dd"), value) try: value.strftime("%Y-%m-%d") except (ValueError,): raise FormatterValidationError(_("Year has to be equal or greater than 1900"), value) return value
def populate(self, states): states.add(_('Pending'), INACTIVE, 'p') states.add(_('Enrolled'), ACTIVE, 'a') states.add(_('Withdrawn'), INACTIVE, 'i') states.add(_('Completed'), ACTIVE+COMPLETED, 'c') states.add(_('Added in error'), INACTIVE, 'e') states.describe(ACTIVE, _('Member')) states.describe(ACTIVE+COMPLETED, _('Completed/Active')) states.describe(INACTIVE+COMPLETED, _('Completed/Inactive')) states.describe(INACTIVE, _('Inactive'))
def columns(self): title = table.table.LocaleAwareGetterColumn( name='title', title=_(u'Title'), getter=lambda i, f: i.title, subsort=True) course_id = table.table.LocaleAwareGetterColumn( name='course_id', title=_('Course ID'), getter=lambda i, f: i.course_id or '', subsort=True) directlyProvides(title, ISortableColumn) directlyProvides(course_id, ISortableColumn) return [title, course_id]
def buildFieldsetGroups(self): self.fieldset_groups = { 'address': ( _('Address'), ['address_line_1', 'address_line_2', 'city', 'state', 'country', 'postal_code']), 'contact_information': ( _('Contact Information'), ['home_phone', 'work_phone', 'mobile_phone', 'email', 'other_1', 'other_2', 'language']), } self.fieldset_order = ( 'address', 'contact_information')
def year(self): year = self.schoolyear if year is not None: return { 'title': _(u'School Year: ${year_title}', mapping={'year_title': year.title}), 'first': year.first, 'last': year.last, 'empty': not bool(tuple(year.values())), 'canModify': canAccess(year, '__delitem__'), 'addurl': absoluteURL(year, self.request) + '/add.html', 'alt': _(u'Add a new term to ${year_title}', mapping={'year_title': year.title}), }
def setUpTableFormatter(self, formatter): columns_before = [] if self.canModify(): columns_before = [ table.DependableCheckboxColumn(prefix="delete", name='delete_checkbox', title=u'')] columns_after = [table.DateColumn(title=_("Starts"), getter=lambda x, y: x.first), table.DateColumn(title=_("Ends"), getter=lambda x, y: x.last)] formatter.setUp(formatters=[table.url_cell_formatter], columns_before=columns_before, columns_after=columns_after)
def columns(self): title = LocaleAwareGetterColumn( name='title', title=_(u'Title'), getter=lambda i, f: i.title, subsort=True) directlyProvides(title, ISortableColumn) capacity = GetterColumn( name='capacity', title=_(u'Capacity'), getter=lambda i, f: i.capacity, subsort=True) directlyProvides(capacity, ISortableColumn) return [title, capacity]
def populate(self, states): states.add(_('Instructor'), ACTIVE, 'a') states.add(_('Substitute'), ACTIVE, 's') states.add(_('Withdrawn'), INACTIVE, 'i') states.add(_('Added in error'), INACTIVE, 'e') states.describe(ACTIVE, _('Instructing')) states.describe(INACTIVE, _('Removed'))
def columns(self): title = LocaleAwareGetterColumn(name='title', title=_(u'Title'), getter=lambda i, f: i.title, subsort=True) directlyProvides(title, ISortableColumn) type = GetterColumn(name='type', title=_(u'Type'), getter=lambda i, f: i.type, subsort=True) directlyProvides(type, ISortableColumn) manufacturer = GetterColumn(name='manufacturer', title=_(u'Manufacturer'), getter=lambda i, f: i.manufacturer, subsort=True) directlyProvides(manufacturer, ISortableColumn) model = GetterColumn(name='model', title=_(u'Model'), getter=lambda i, f: i.model, subsort=True) directlyProvides(model, ISortableColumn) serialNumber = GetterColumn(name='serialNumber', title=_(u'Serial Number'), getter=lambda i, f: i.serialNumber, subsort=True) directlyProvides(serialNumber, ISortableColumn) purchaseDate = GetterColumn(name='purchaseDate', title=_(u'Purchase Date'), getter=lambda i, f: i.purchaseDate, subsort=True) directlyProvides(purchaseDate, ISortableColumn) return [title, type, manufacturer, model, serialNumber, purchaseDate]
class IRelationshipStates(IContained): title = zope.schema.TextLine( title=_("Title")) states = zope.schema.Dict( title=_(u'Statuses'), description=_(u'Recipient addresses'), key_type=zope.schema.TextLine(title=u"Key"), value_type=zope.schema.Object( title=_(u"Status"), schema=IRelationshipState), min_length=1) system_titles = zope.schema.Dict( title=_(u'System state value descriptions'), description=_(u'Descriptions of state "active" values'), key_type=zope.schema.TextLine(title=u"Key"), value_type=zope.schema.TextLine(title=u"Description"), min_length=1) factory = Attribute(u'State factory') def __iter__(): """Iterate through self.states values.""" def getState(state_tuple): """Return app state given (meaning, code) tuple.""" def getTitle(state_tuple): """Return state title given (meaning, code) tuple.""" def getDescription(state_tuple): """Return state description given (meaning, code) tuple."""
class TaskFailedMessage(Message): task_id = None title = _("Internal server error, ticket ${ticket}") def __init__(self, task): Message.__init__(self) self.task_id = task.__name__ def send(self, sender=None, recipients=None): self.title = format_message(self.title, mapping={'ticket': self.task_id}) Message.send(self, sender=sender, recipients=recipients)
def extractStates(self, data): states = [] unique = set() for rownum, values in enumerate(data): code, title, active = values[:3] if code in unique: return self.setMessage( _('Duplicate code ${code} in ${row}.', mapping={ 'code': code, 'row': rownum + 1 })) if not len(code): return self.setMessage( _('Code field must not be empty in row ${row}.', mapping={'row': rownum + 1})) if not len(title): return self.setMessage( _('Title field must not be empty in row ${row}.', mapping={'row': rownum + 1})) state = self.createState(*values) states.append(state) unique.add(code) used_active = set([state.active for state in states]) available_active = set(self.target.system_titles.keys()) missing_active = sorted(available_active.difference(used_active)) if missing_active: return self.setMessage( _('Must have at least one ${title} state.', mapping={ 'title': translate(removeSecurityProxy( self.target.system_titles[missing_active[0]]), context=self.request) })) self.validStates = states return True
class AdministrationSnippets(CrowdDescriptionSnippetBase): """A way to display short crowd description with a link to a legend. Not a good way to do that. """ description = _(u'School administration') template = InlinePageTemplate(''' <p> <tal:block content="view/description" /> <a href="#legend_administration">[1]</a> </p> ''')
class FlourishResourceDeleteView(flourish.form.DialogForm, form.Form): dialog_submit_actions = ('delete', ) dialog_close_actions = ('cancel', ) label = None @button.buttonAndHandler(_('Delete')) def handle_delete_action(self, action): parent = self.context.__parent__ parent_url = absoluteURL(parent, self.request) context_name = self.context.__name__.encode('utf-8') url = '%s/delete.html?delete.%s&CONFIRM' % (parent_url, context_name) self.request.response.redirect(url) @button.buttonAndHandler(_('Cancel')) def handle_cancel_action(self, action): pass def updateActions(self): super(FlourishResourceDeleteView, self).updateActions() self.actions['delete'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel')
def __call__(self): if 'DELETE' in self.request: if not self.deletingActiveSchoolYear(): return self.delete_template() elif not self.canDeleteSchoolYears(): self.error = _( "You can not delete the active school year." " Unless you are deleting all the school years.") else: return self.delete_template() self.setUpTableFormatter(self.table) return self.template()
class LevelEditView(form.EditForm): template = ViewPageTemplateFile('templates/level_edit.pt') fields = field.Fields(ILevel) def redirectToContainer(self): url = absoluteURL(self.context.__parent__, self.request) self.request.response.redirect(url) @button.buttonAndHandler(_("Apply"), name='apply') def handleApply(self, action): # Pretty, isn't it? form.EditForm.handleApply.func(self, action) self.redirectToContainer() @button.buttonAndHandler(_("Cancel"), name='cancel') def handle_cancel_action(self, action): self.redirectToContainer() def updateActions(self): super(LevelEditView, self).updateActions() self.actions['apply'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel')
def columns(self): title = table.column.LocaleAwareGetterColumn( name='title', title=_(u'Name'), getter=lambda i, f: i.title, subsort=True) address_1 = zc.table.column.GetterColumn( name='address_1', title=_(u'Address 1'), getter=lambda i, f: IContact(i).address_line_1) address_2 = zc.table.column.GetterColumn( name='address_2', title=_(u'Address 2'), getter=lambda i, f: IContact(i).address_line_2) city = zc.table.column.GetterColumn(name='city', title=_(u'City'), getter=city_getter) country = zc.table.column.GetterColumn( name='country', title=_(u'Country'), getter=lambda i, f: IContact(i).country) return [title, address_1, address_2, city, country]
def __call__(self): self.makeProgress() self.task_progress.title = _("Exporting school data") self.addImporters(self.task_progress) wb = xlwt.Workbook() self.export_school_years(wb) self.export_terms(wb) self.export_school_timetables(wb) self.export_resources(wb) self.export_levels(wb) self.export_persons(wb) self.export_contacts(wb) self.export_courses(wb) self.export_sections(wb) self.export_sections_enrollment(wb) self.export_section_timetables(wb) self.export_groups(wb) self.task_progress.title = _("Export complete") self.task_progress.force('overall', progress=1.0) data = self.render(wb) return data
def columns(self): title = table.column.LocaleAwareGetterColumn( name='title', title=_(u"Title"), getter=lambda i, f: i.title, subsort=True) starts = GetterColumn( name='starts', title=_(u"First Day"), getter=lambda i, f: i.first, cell_formatter=date_cell_formatter, subsort=True) ends = GetterColumn( name='ends', title=_(u"Last Day"), getter=lambda i, f: i.last, cell_formatter=date_cell_formatter, subsort=True) directlyProvides(title, ISortableColumn) directlyProvides(starts, ISortableColumn) directlyProvides(ends, ISortableColumn) return [title, starts, ends]
class ContactContainerView(TableContainerView): """A Contact Container view.""" __used_for__ = IContactContainer delete_template = ViewPageTemplateFile('templates/contacts_delete.pt') index_title = _("Contact index") @property def itemsToDelete(self): return sorted(TableContainerView._listItemsForDeletion(self), key=lambda obj: '%s %s' % (obj.last_name, obj.first_name)) def columnsBefore(self): if self.canModify(): return [ table.column.DependableCheckboxColumn(prefix="delete", name='delete_checkbox', title=u'', id_getter=IUniqueFormKey, show_disabled=False) ] return [] def setUpTableFormatter(self, formatter): columns_before = self.columnsBefore() formatter.setUp(columns_before=columns_before) def listIdsForDeletion(self): int_ids = getUtility(IIntIds) return [ int_ids.getObject(intid).__name__ for intid in self.listIntIdsForDeletion() ] def listFormKeysForDeletion(self): catalog = ICatalog(self.context) index = catalog['form_keys'] return [ 'delete.%s' % index.documents_to_values[intid] for intid in self.listIntIdsForDeletion() ] def listIntIdsForDeletion(self): catalog = ICatalog(self.context) index = catalog['form_keys'] return [ intid for intid in catalog.extent if 'delete.%s' % index.documents_to_values[intid] in self.request ]
class FlourishCourseEditView(Form, form.EditForm): template = InheritTemplate(Page.template) label = None legend = _('Course Information') @property def fields(self): fields = field.Fields(ICourse) fields += field.Fields(ICourseLevel) fields = fields.select('title', 'description', 'course_id', 'government_id', 'credits', 'level') return fields @property def title(self): return self.context.title def update(self): return form.EditForm.update(self) def updateActions(self): super(FlourishCourseEditView, self).updateActions() self.actions['apply'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel') @button.buttonAndHandler(_('Submit'), name='apply') def handleApply(self, action): super(FlourishCourseEditView, self).handleApply.func(self, action) # XXX: hacky sucessful submit check if (self.status == self.successMessage or self.status == self.noChangesMessage): url = absoluteURL(self.context, self.request) self.request.response.redirect(url) @button.buttonAndHandler(_("Cancel")) def handle_cancel_action(self, action): url = absoluteURL(self.context, self.request) self.request.response.redirect(url)
class ContactEditView(form.EditForm): """Edit form for basic contact.""" form.extends(form.EditForm) template = ViewPageTemplateFile('templates/contact_add.pt') fields = field.Fields(IContact) formErrorsMessage = _('Please correct the marked fields below.') @button.buttonAndHandler(_("Cancel")) def handle_cancel_action(self, action): url = absoluteURL(self.context, self.request) self.request.response.redirect(url) def update(self): super(ContactEditView, self).update() self.subforms = [] for relationship_info in self.context.persons.all().relationships: subform = ContactPersonInfoSubForm(self.context, self.request, self, relationship_info) # XXX: should also apply at least urllib.quote here: prefix = unicode( relationship_info.target.__name__).encode('punycode') subform.prefix += '.%s' % prefix subform.update() # One more hack. if subform.changed and self.status == self.noChangesMessage: self.status = self.successMessage self.subforms.append(subform) def updateActions(self): super(ContactEditView, self).updateActions() self.actions['apply'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel') @property def label(self): return _(u'Change contact information for ${person}', mapping={'person': self.context.title})
class FlourishFieldDescriptionEditView(flourish.form.Form, FieldDescriptionEditView): template = InheritTemplate(flourish.page.Page.template) label = None legend = _('Field Details') @property def title(self): return getAdapter(self.context.__parent__, IAddEditViewTitle) @property def subtitle(self): return _(u'Change information for ${field_title}', mapping={'field_title': self.context.title}) @button.buttonAndHandler(_('Submit'), name='apply') def handleApply(self, action): super(FlourishFieldDescriptionEditView, self).handleApply.func(self, action) # XXX: hacky sucessful submit check if (self.status == self.successMessage or self.status == self.noChangesMessage): self.request.response.redirect(self.nextURL()) @button.buttonAndHandler(_("Cancel")) def handle_cancel_action(self, action): self.request.response.redirect(self.nextURL()) def updateWidgets(self): super(FlourishFieldDescriptionEditView, self).updateWidgets() self.widgets['limit_keys'].label = getAdapter(self.context.__parent__, ILimitKeysLabel) self.widgets['limit_keys'].field.description = getAdapter( self.context.__parent__, ILimitKeysHint) def nextURL(self): return absoluteURL(self.context.__parent__, self.request)
class StudentLevelsStatesStartup(StateStartUpBase): states_name = 'student-levels' states_title = _('Student Levels') def populate(self, states): super(StudentLevelsStatesStartup, self).populate(states) states.add(_('Pre-enrolled'), INACTIVE + PREENROLLED, 'p') states.add(_('Enrolled'), ACTIVE, 'a') states.add(_('Graduated'), INACTIVE + GRADUATED, 'c') states.add(_('Inactive'), INACTIVE, 'i') states.add(_('Added in error'), INACTIVE, 'e') states.describe(INACTIVE + PREENROLLED, _('Pre-enrolled')) states.describe(INACTIVE + GRADUATED, _('Graduated'))
def url(self): rc = ISchoolToolApplication(None)['resources'] booking_calendar = IBookingCalendar(rc) url = absoluteURL(booking_calendar, self.request) url = "%s/book_one_resource.html?resource_id=%s" % ( url, self.context.__name__) today = getUtility(IDateManager).today hour = utcnow().hour duration = 3600 url = "%s&start_date=%s&start_time=%s:00&duration=%s&title=%s" % ( url, today.isoformat(), hour, duration, translate(_("Unnamed Event"), context=self.request)) url = "%s&next_url=%s" % (url, self.nextURL()) return url
def ptos(self): collator = ICollator(self.request.locale) ptos_dict = {} for resource in sorted(self.context.values(), key=lambda x: collator.key(x.title)): if ILocation(resource, None) is not None: resource_type = _('Location') elif IEquipment(resource, None) is not None: resource_type = _('Equipment') else: resource_type = _('Resource') pto = ptos_dict.setdefault(resource_type, { 'type': resource_type, 'rows': [], }) pto['rows'].append({ 'title': resource.title, 'description': resource.description, }) return [ ptos_dict[k] for k in sorted(ptos_dict.keys(), key=lambda x: collator.key(x)) ]
class FlourishGroupDeleteView(flourish.form.DialogForm, form.EditForm): """View used for confirming deletion of a group.""" dialog_submit_actions = ('apply', ) dialog_close_actions = ('cancel', ) label = None @button.buttonAndHandler(_("Delete"), name='apply') def handleDelete(self, action): url = '%s/delete.html?delete.%s&CONFIRM' % (absoluteURL( self.context.__parent__, self.request), self.context.__name__) self.request.response.redirect(url) # We never have errors, so just close the dialog. self.ajax_settings['dialog'] = 'close' @button.buttonAndHandler(_("Cancel")) def handle_cancel_action(self, action): pass def updateActions(self): super(FlourishGroupDeleteView, self).updateActions() self.actions['apply'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel')
class ISchedule(Interface): """A schedule of meetings.""" title = zope.schema.TextLine( title=u"Title of the timetable", required=True) first = zope.schema.Date( title=_("First scheduled day"), required=True) last = zope.schema.Date( title=_("Last scheduled day"), required=True) timezone = zope.schema.Choice( title=u"Time Zone", description=u"Meetings time zone", values=pytz.common_timezones, required=True) def iterMeetings(date, until_date=None): """Yields meetings for the given date range."""
class RotatingSlotEntryStep(Step): """Step for entering start and end times of slots in each day. This step is taken when the start/end times are different for each day, the rotating cycle is chosen in the CycleStep and 'day in the cycle' is chosen in the SequentialModelStep. """ __name__ = 'rotating_slot_entry_step' __call__ = ViewPageTemplateFile("templates/ttwizard_slottimes.pt") description = _("Enter start and end times for each slot on each day," " one slot (HH:MM - HH:MM) per line. The start and " "end times MUST BE IN 24 HOUR FORMAT, " "for example, 13:30 not 01:30 PM.") error = None example_intervals = '8:00 - 8:45\n9:05 - 9:50\n' def days(self): """Return a list of day ids/values for the view""" for day_number in range(len(self.dayNames())): day_id = "times.%s" % day_number default = "" if day_number < 5: default = self.example_intervals value = self.request.get(day_id, default) yield {'id': day_id, 'value': value} def dayNames(self): """Return the list of day names.""" return self.getSessionData()['day_names'] def update(self): result = [] for i, day_name in enumerate(self.dayNames()): s = self.request.form.get('times.%d' % i, '') try: times = parse_time_range_list(s) except ValueError, e: self.error = _("Not a valid time slot: $slot.", mapping={'slot': unicode(e.args[0])}) return False result.append(times) session = self.getSessionData() session['time_slots'] = result return True
def update(self): result = [] periods = self.periods() numSlots = self.numSlots() for i in range(len(self.days())): day = [] for j in range(numSlots[i]): name = 'period_%d_%d' % (i, j) if name not in self.request: self.error = _('Please provide all periods.') return False day.append(self.request[name]) result.append(day) # Validate that all periods are selected errors = set() for i, day in enumerate(self.days()): seen = set() for period in result[i]: if period not in seen: seen.add(period) else: error = _("$period on day $day", mapping={ 'period': period, 'day': self.days()[i] }) errors.add(translate(error, context=self.request)) if errors: self.error = _( 'The following periods were selected more' ' than once: $periods', mapping={'periods': ', '.join(errors)}) return False self.getSessionData()['periods_order'] = result return True
class FlourishDemographicsView(flourish.page.WideContainerPage): keys = [('students', _("Stud.")), ('teachers', _("Teach.")), ('administrators', _("Admin."))] types = { 'Enum': _('Selection'), 'Date': _('Date'), 'Text': _('Text'), 'Bool': _('Yes/No'), 'Description': _('Description'), 'Int': _('Integer'), } def table(self): result = [] for demo in list(self.context.values()): classname = demo.__class__.__name__ class_key = classname[:classname.find('FieldDescription')] field_type = self.types.get(class_key, '') limit_keys = demo.limit_keys if limit_keys is None: limit_keys = [] result.append({ 'title': demo.title, 'url': '%s/edit.html' % absoluteURL(demo, self.request), 'id': demo.name, 'type': field_type, 'required': demo.required, 'limited': bool(limit_keys), 'groups': [(key[0] in limit_keys) for key in self.keys], }) return result def groups(self): return [key[1] for key in self.keys]
def parseCSVRows(self, rows): """Parse rows (a list of strings) in CSV format. Returns a list of rows as lists. Trailing empty cells are discarded. rows must be in the encoding specified during construction of TimetableCSVImportView; the returned values are in unicode. If the provided data is invalid, self.errors.generic will be updated and None will be returned. """ result = [] reader = csv.reader(rows) line = 0 try: while True: line += 1 values = [v.strip() for v in reader.next()] if self.charset: values = [unicode(v, self.charset) for v in values] # Remove trailing empty cells. while values and not values[-1].strip(): del values[-1] result.append(values) except StopIteration: return result except csv.Error: error_msg = _("Error in timetable CSV data, line ${line_no}", mapping={'line_no': line}) self.errors.generic.append(error_msg) return except UnicodeError: error_msg = _("Conversion to unicode failed in line ${line_no}", mapping={'line_no': line}) self.errors.generic.append(error_msg) return
class SectionMemberStatesStartup(StateStartUpBase): states_name = 'section-membership' states_title = _('Section Enrollment') def populate(self, states): states.add(_('Pending'), INACTIVE, 'p') states.add(_('Enrolled'), ACTIVE, 'a') states.add(_('Withdrawn'), INACTIVE, 'i') states.add(_('Completed'), ACTIVE + COMPLETED, 'c') states.add(_('Added in error'), INACTIVE, 'e') states.describe(ACTIVE, _('Member')) states.describe(ACTIVE + COMPLETED, _('Completed/Active')) states.describe(INACTIVE + COMPLETED, _('Completed/Inactive')) states.describe(INACTIVE, _('Inactive'))
class PersonInstructorsCrowd(Crowd): """Crowd of instructors of a person.""" title = _(u'Instructors') description = _(u'Instructors of a person in any of his sections.') def _getSections(self, ob): result = [] group_relation = membership.Membership relationships = group_relation.bind(member=ob).all().relationships for link_info in relationships: section = removeSecurityProxy(link_info.target) if not interfaces.ISection.providedBy(section): continue result.append(section) return result def contains(self, principal): user = IPerson(principal, None) person = IPerson(self.context) for section in self._getSections(person): if user in section.instructors: return True return False
class RequestReportDownloadDialog(DialogForm, z3c.form.form.EditForm): template = ViewPageTemplateFile('templates/f_request_report_download.pt') dialog_submit_actions = ('download', ) dialog_close_actions = ('cancel', ) label = None @button.buttonAndHandler(_("Download"), name='download') def handleDownload(self, action): self.request.response.redirect(self.nextURL()) # We never have errors, so just close the dialog. self.ajax_settings['dialog'] = 'close' @button.buttonAndHandler(_("Cancel")) def handle_cancel_action(self, action): pass def updateActions(self): super(RequestReportDownloadDialog, self).updateActions() self.actions['download'].addClass('button-ok') self.actions['cancel'].addClass('button-cancel') def nextURL(self): raise NotImplementedError( "nextURL must redirect to a 'downloadable' view") @property def file_type(self): if 'file_type' in self.request: return unquote_plus(self.request['file_type']) @property def description(self): if 'description' in self.request: return unquote_plus(self.request['description'])
class PeriodOrderSimple(Step): """Step to put periods in order if all days are the same.""" __name__ = 'period_order_simple_step' __call__ = ViewPageTemplateFile('templates/ttwizard_period_order1.pt') description = _('Please put the periods in order:') error = None def periods(self): return self.getSessionData()['period_names'] def numPeriods(self): return max([len(day) for day in self.getSessionData()['time_slots']]) def update(self): result = [] periods = self.getSessionData()['period_names'] for i in range(self.numPeriods()): name = 'period_%d' % i if name not in self.request: self.error = _('Please provide all periods.') return False result.append(self.request[name]) # Validate that all periods are selected seen = set() errors = set() for period in result: if period not in seen: seen.add(period) else: errors.add(period) if errors: self.error = _( 'The following periods were selected more' ' than once: $periods', mapping={'periods': ', '.join(errors)}) return False day_names = self.getSessionData()['day_names'] self.getSessionData()['periods_order'] = [result] * len(day_names) return True def next(self): return HomeroomStep
def overlay_container(self): container = OverlayCalendarsContainer() cal = self.getApplicationCalendar() if cal is not None: key = 'app.school' container[key] = OverlayCalendarsInfo(removeSecurityProxy(cal), cal.__parent__.title, _('School Calendar')) for cal in self.getResourceCalendars(): resource = cal.__parent__ key = 'resource.%s' % resource.__name__ res_info = IResourceTypeInformation(resource) container[key] = OverlayCalendarsInfo(removeSecurityProxy(cal), resource.title, res_info.title) return container