예제 #1
0
    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()
예제 #2
0
    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()
예제 #3
0
 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]
예제 #4
0
    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
예제 #5
0
 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
예제 #6
0
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]
예제 #7
0
    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))
예제 #8
0
 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')
예제 #9
0
 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
예제 #10
0
 def sizeForDisplay(self):
     num = self.sizeForSorting()[1]
     if num == 1:
         msgid = _("1 person")
     else:
         msgid = _("${number} persons", mapping={'number': num})
     return msgid
예제 #11
0
    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)
예제 #12
0
    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
예제 #13
0
 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
예제 #14
0
 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
예제 #15
0
 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
예제 #16
0
 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
예제 #17
0
 def types(self):
     options = [
         {'id': 'equipment',
          'title': _('Equipment')},
         {'id': 'location',
          'title': _('Location')},
         {'id': 'resource',
          'title': _('Resource')},
         ]
     return options
예제 #18
0
 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
예제 #19
0
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;'
예제 #20
0
 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
예제 #21
0
 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'))
예제 #22
0
 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]
예제 #23
0
 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]
예제 #24
0
 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
예제 #25
0
 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'))
예제 #26
0
 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]
예제 #27
0
 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')
예제 #28
0
 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}),
             }
예제 #29
0
 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)
예제 #30
0
 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]
예제 #31
0
 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'))
예제 #32
0
 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]
예제 #33
0
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."""
예제 #34
0
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)
예제 #35
0
    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
예제 #36
0
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>
    ''')
예제 #37
0
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')
예제 #38
0
    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()
예제 #39
0
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')
예제 #40
0
 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]
예제 #41
0
    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
예제 #42
0
파일: term.py 프로젝트: l1ph0x/schooltool-2
 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]
예제 #43
0
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
        ]
예제 #44
0
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)
예제 #45
0
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})
예제 #46
0
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)
예제 #47
0
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'))
예제 #48
0
 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
예제 #49
0
 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))
     ]
예제 #50
0
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')
예제 #51
0
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."""
예제 #52
0
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
예제 #53
0
    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
예제 #54
0
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]
예제 #55
0
    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
예제 #56
0
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'))
예제 #57
0
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
예제 #58
0
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'])
예제 #59
0
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
예제 #60
0
 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