def __call__(self): response = self.request.response title = self.context.Title() ftitle = "/tmp/%s_CV.pdf" % (title) filename = ftitle attachment = 'attachment; filename=%s' % (ftitle) f = file(filename, "wb") pdf_template = ViewPageTemplateFile('pdf-view.pt')(self) response.setHeader('Content-Type', 'application/pdf') response.setHeader('Content-Disposition', attachment); pdf = pisa.CreatePDF(pdf_template.encode("UTF-8"), response) f.flush() f.close() if not pdf.err: return response else: # Something is wrong # Fledge this out later pass
class UserAssignmentView(forms.common.BaseForm): """View for user assignments. Allows users with adequate permissions to edit the assignments """ form_fields = [] render = ViewPageTemplateFile("templates/assignment.pt") def __init__(self, context, request): self._assignable_roles = [] self.principal = utils.common.get_request_principal() self.context_roles = common.get_context_roles(context, self.principal) self.context = removeSecurityProxy(context) self.prm = IPrincipalRoleMap(self.context) super(UserAssignmentView, self).__init__(context, request) def __call__(self): self.update() return self.render() def get_object_type_info(self): return capi.get_type_info(self.context.__class__) def get_config_roles(self, role_type): ti = self.get_object_type_info() workflow = ti.workflow if workflow.has_feature("user_assignment"): feature = None for f in workflow.features: if f.name == "user_assignment": feature = f if feature: if role_type == "assigner": return capi.schema.qualified_roles( feature.params["assigner_roles"]) elif role_type == "assignable": return capi.schema.qualified_roles( feature.params["assignable_roles"]) return [] def assignable_roles(self): """Returns a list of role ids that this user can assign to """ if self._assignable_roles: return self._assignable_roles # the assigner roles that this user has assigner_roles = [] # all the assigner roles that are in the workflow config config_assigner_roles = self.get_config_roles("assigner") for c_a_role in config_assigner_roles: role = getUtility(IRole, c_a_role) if role.id in self.context_roles: assigner_roles.append(role.id) # the assignable roles that this user can assign to assignable_roles = [] # all the assignable roles that are in the workflow config config_assignable_roles = self.get_config_roles("assignable") # Only assign to roles that have the same parent or are children # of assigner roles that this user has for assigner_role in assigner_roles: assigner_role_annt = ISubRoleAnnotations( getUtility(IRole, assigner_role)) if assigner_role_annt.is_sub_role: for c_assignable_role in config_assignable_roles: c_assignable_role_annt = ISubRoleAnnotations( getUtility(IRole, c_assignable_role)) if (c_assignable_role_annt.parent == assigner_role_annt.parent): assignable_roles.append(c_assignable_role) else: for c_assignable_role in config_assignable_roles: if (c_assignable_role in assigner_role_annt.sub_roles): assignable_roles.append(c_assignable_role) self._assignable_roles = assignable_roles return self._assignable_roles def can_edit(self, action=None): return checkPermission("bungeni.user_assignment.Edit", self.context) @property def columns(self): return [ column.GetterColumn( title=_("user name"), getter=lambda i, f: i.get("title") ), column.GetterColumn( title=_("assigned"), getter=lambda i, f: i, cell_formatter=lambda g, i, f: \ '<input type="checkbox" name="%s" %s %s/>' % ( i["name"], i["is_assigned"] and ' checked="checked"' or "", not i["editable"] and ' disabled="disabled"' or "") ) ] @property def checkbox_prefix(self): return "assignment_users" def make_id(self, role_id, user_login_id): return ".".join((self.checkbox_prefix, role_id, user_login_id)) def user_is_assigned(self, user_login, role_id): if self.prm.getSetting(role_id, user_login) == Allow: return True return False def role_listing(self, role_id, editable): listing = [] users = common.get_users(role_id) if not users: return _("No users available for this role.") for user in users: data = {} data["title"] = IDCDescriptiveProperties(user).title data["name"] = self.make_id(user.login, role_id) data["is_assigned"] = self.user_is_assigned(user.login, role_id) data["editable"] = editable listing.append(data) formatter = TableFormatter(self.context, self.request, listing, prefix="assignment", columns=self.columns) formatter.updateBatching() return formatter() def update(self): self.tables = [] assignable_roles = self.assignable_roles() for role_id in assignable_roles: if role_id in assignable_roles: editable = True else: editable = False self.tables.append({ "title": getUtility(IRole, role_id).title, "table": self.role_listing(role_id, editable) }) forms.common.BaseForm.update(self) def get_selected(self): selected = [ (k[len(self.checkbox_prefix) + 1:].split(".")[0].decode("base64"), k[len(self.checkbox_prefix) + 1:].split(".")[1].decode("base64")) for k in self.request.form.keys() if k.startswith(self.checkbox_prefix) and self.request.form.get(k) ] return selected def process_assignment(self): for role_id in self.assignable_roles(): for user in common.get_users(role_id): key = self.make_id(user.login, role_id) if key in self.request.form.keys(): self.prm.assignRoleToPrincipal(role_id, user.login) else: self.prm.unsetRoleForPrincipal(role_id, user.login) @formlib.form.action(label=_("Save"), name="save", condition=can_edit) def handle_save(self, action, data): self.process_assignment() next_url = url.absoluteURL(self.context, self.request) self.request.response.redirect(next_url) @formlib.form.action(label=_("Cancel"), name="", condition=can_edit) def handle_cancel(self, action, data): next_url = url.absoluteURL(self.context, self.request) self.request.response.redirect(next_url)
class WorkflowActionViewlet(browser.BungeniBrowserView, BaseForm, viewlet.ViewletBase): """Display workflow status and actions. """ # stores old_url of object before transition change # we could use HTTP_REFERER but that would mean relying on client input _old_url = None render = ViewPageTemplateFile("templates/viewlet.pt") class IWorkflowForm(zope.interface.Interface): note = zope.schema.Text(title=_("Comment on workflow change"), required=False) date_active = zope.schema.Datetime(title=_("Active Date"), required=True) registry_number = zope.schema.TextLine(title=_("Registry number"), required=False) form_name = "Workflow" form_fields = form.Fields(IWorkflowForm) note_widget = TextAreaWidget note_widget.height = 1 form_fields["note"].custom_widget = note_widget form_fields["date_active"].custom_widget = TextDateTimeWidget actions = () def get_min_date_active(self): """Determine the min_date_active to validate against. """ def is_workflowed_and_draft(instance): """is item workflowed, and if so is it in a logical draft state? """ if interfaces.IWorkflowed.providedBy(instance): wf = interfaces.IWorkflow(instance) return instance.status in wf.get_state_ids(tagged=["draft"], restrict=False) return False min_date_active = None if IAuditable.providedBy(self.context): instance = removeSecurityProxy(self.context) # !+PASTDATAENTRY(mr, jun-2011) offers a way to enter past data # for workflowed items via the UI -- note, ideally we should be # able to also control the item's creation active_date. # # If a workflowed item is in draft state, we do NOT take the # date_active of its last change as the min_date_active, but # let that min fallback to parliament's creation date... if not is_workflowed_and_draft(instance): changes = get_changes(instance, "workflow") if changes: # then use the "date_active" of the most recent entry min_date_active = changes[-1].date_active if not min_date_active: # fallback to current parliament's start_date (cast to a datetime) min_date_active = datetime.datetime.combine( globalsettings.get_current_parliament().start_date, datetime.time()) # As the precision of the UI-submitted datetime is only to the minute, # we adjust min_date_active by a margin of 59 secs earlier to avoid # issues of doing 2 transitions in quick succession (within same minute) # the 2nd of which could be taken to be too old... return min_date_active - datetime.timedelta(seconds=59) def validate(self, action, data): # submitted data is actually updated in following call to super.validate # !+PASTDATAENTRY(mr, jun-2011) enhancement? see Issue 612 Comment 6: # unrequire, allow active_date=None, # get_effective_active_date -> last workflow non-None active_date errors = super(WorkflowActionViewlet, self).validate(action, data) if "date_active" in data.keys(): min_date_active = self.get_min_date_active() if data.get("date_active") < min_date_active: errors.append( zope.interface.Invalid(_("Active Date is in the past."))) elif data.get("date_active") > datetime.datetime.now(): errors.append( zope.interface.Invalid(_("Active Date is in the future."))) if "registry_number" in data.keys(): reg_number = data.get("registry_number") if reg_number: session = Session() num = session.query(ParliamentaryItem).filter( ParliamentaryItem.registry_number == reg_number).count() if num != 0: errors.append( zope.interface.Invalid( "This registry number is already taken.")) return errors def setUpWidgets(self, ignore_request=False): class WorkflowForm: note = None date_active = None registry_number = None self.adapters = { self.IWorkflowForm: WorkflowForm, } self.widgets = form.setUpDataWidgets(self.form_fields, self.prefix, self.context, self.request, ignore_request=ignore_request) def update(self, transition_id=None): if IWorkspaceContainer.providedBy(self.context.__parent__): self._old_url = WorkspaceAbsoluteURLView(self.context, self.request)() workflow = interfaces.IWorkflow(self.context) if transition_id: transition = workflow.get_transition(transition_id) title = translate(_(transition.title), context=self.request) self.status = translate(_( u"Confirmation required for workflow transition: '${title}'", mapping={"title": title}), context=self.request) self.setupActions(transition_id) if (IBungeniParliamentaryContent.providedBy(self.context) and get_mask(self.context) == "manual" and not self.context.registry_number): self.form_fields = self.form_fields.omit("note", "date_active") else: self.form_fields = self.form_fields.omit("registry_number") if not self.actions: self.form_fields = self.form_fields.omit("note", "date_active") elif not IAuditable.providedBy(self.context): self.form_fields = self.form_fields.omit("note", "date_active") # !+SUPERFLUOUS_ObejctModifiedEvent(mr, nov-2011) the following update() # is causing a ModifiedEvent to be fired, causing a modify change to be # logged (while this workflow change should be just that). super(WorkflowActionViewlet, self).update() @property def next_url(self): if IWorkspaceContainer.providedBy(self.context.__parent__): # check if the object is in the same tab as before. # if it is redirect to the object, if not redirect to the listing if (WorkspaceAbsoluteURLView(self.context, self.request)() == self._old_url): self._next_url = self._old_url else: self._next_url = absoluteURL(self.context.__parent__, self.request) return self._next_url def setupActions(self, transition_id): # !+RENAME(mr, apr-2011) should be transition_id wfc = interfaces.IWorkflowController(self.context) if transition_id is None: transition_ids = wfc.getManualTransitionIds() else: transition_ids = (transition_id, ) self.actions = bindTransitions(self, transition_ids, wfc.workflow)
class PagedSearch(Pager, Search): template = ViewPageTemplateFile('templates/pagedsearch.pt')
class AdvancedPagedSearch(PagedSearch): template = ViewPageTemplateFile('templates/advanced-pagedsearch.pt') form_fields = form.Fields(IAdvancedSearch) form_fields["status_date"].custom_widget = SelectDateWidget def __init__(self, *args): super(AdvancedPagedSearch, self).__init__(*args) #print "Language:", translate("Language", domain="bungeni", context=self.request) statuses = SimpleVocabulary([]) indexed_fields = [ 'all', ] content_type = self.request.get('form.content_type', '') if content_type: dotted_name = "bungeni.models.domain.%s" % content_type domain_class = resolve.resolve(dotted_name) statuses = get_statuses_vocabulary(domain_class) f = IIndexer(domain_class()).fields() indexed_fields = indexed_fields + [i for i, fld in f] self.form_fields += \ form.Fields( schema.Choice(__name__='owner', title=_("Owner"), vocabulary=get_users_vocabulary(), required=False), schema.Choice(__name__='status', title=_("Status"), vocabulary=statuses, required=False), schema.Choice(__name__='field', title=_('Field'), values=indexed_fields, required=False), IHighLight ) @form.action(label=_(u"Search")) def handle_search(self, action, data): self.searcher = component.getUtility(interfaces.IIndexSearch)() search_term = data['full_text'] content_type = data['content_type'] lang = data['language'] indexed_field = data.get('field', '') status = data.get('status', '') status_date = data['status_date'] owner = data.get('owner', '') if not lang: lang = 'en' if not search_term: self.status = _(u"Invalid Query") return # compose query t = time.time() if content_type and indexed_field and indexed_field != 'all': text_query = self.searcher.query_field(indexed_field, search_term) lang_query = self.searcher.query_field('language', lang) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (text_query, lang_query,)) else: text_query = self.searcher.query_parse(search_term) lang_query = self.searcher.query_field('language', lang) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (text_query, lang_query,)) if content_type: content_type_query = self.searcher.query_field( 'object_type', content_type) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, content_type_query,)) if content_type and status: status_query = self.searcher.query_field('status', status) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, status_query,)) if status_date: status_date_query = self.searcher.query_field( 'status_date', index.date_value(status_date)) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, status_date_query,)) if owner: owner_query = self.searcher.query_field('owner', str(owner)) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, owner_query,)) self.results = self._results self.search_time = time.time() - t # spelling suggestions suggestion = self.searcher.spell_correct(search_term) self.spelling_suggestion = (search_term != suggestion and suggestion or None)
class ShareForm(form.SchemaForm): """ A page to share a country with a group or user """ implements(ICheckoutSharePage) schema = IShareSchema ignoreContext = True label = u"Share this country for checkout editing" description = u"""Here it is possible to choose the Eionet groups or individual users that have special checkout, edit and reviewing rights in this location.""" template = ViewPageTemplateFile("pt/share.pt") status = '' @button.buttonAndHandler(u"Save") def handleApply(self, action): print "doing handle apply" data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return principal_id = data['principal_id'] role = PLONE_ROLES[data['role_id']] try: principal = self._search_principal(principal_id) except NoResultsException: msg = u'No results found.' self.status = msg print self.status raise ActionExecutionError(Invalid(msg)) except MultipleResultsException: msg = 'The user/group id is not precise enough.' self.status = msg print self.status raise ActionExecutionError(Invalid(msg)) self.status = u"Saved." self.share_with_principal(principal['id'], role) @button.buttonAndHandler(u"Cancel") def handleCancel(self, action): return self.request.response.redirect(self.context.absolute_url()) def get_wc(self, context): policy = ICheckinCheckoutPolicy(context, None) if policy is None: return False wc = policy.getWorkingCopy() return wc def share_with_principal(self, principal_id, role): """ Setup proper share role for this principal """ logger.info("Setting up proper %s role for %s", role, principal_id) print "Sharing", principal_id, role contexts = [self.context] wc = self.get_wc(self.context) if wc: contexts.append(wc) site = getSite() for location in PLONE_LOCATIONS: if self.context.aq_parent.id != 'countries': continue obj = site.unrestrictedTraverse(location + self.context.id) if obj: contexts.append(obj) for folder in contexts: self.assign_role_to_principal(folder, role, principal_id) if ICountryPage not in list(providedBy(folder)): mark(folder, ICountryPage) def assign_role_to_principal(self, context, role, principal_id): roles = set(context.get_local_roles_for_userid(userid=principal_id)) roles.add(role) roles = list(roles) context.manage_setLocalRoles(principal_id, roles) def _search_principal(self, term): search = getMultiAdapter((self.context, self.request), name='pas_search') users = search.searchUsers(id=term) groups = search.searchGroups(id=term) result = users + groups if len(result) > 1: raise MultipleResultsException if len(result) == 0: raise NoResultsException return result[0]
class LibraryViewlet(viewlet.ViewletBase): render = ViewPageTemplateFile("templates/attached-files.pt") form_name = _("attached files") for_display = True weight = 50 def __init__(self, context, request, view, manager): self.context = [] trusted = removeSecurityProxy(context) # !+(murithi, mar-2010 )Attached file versions implement IVersion # but have no attached files - an adapter on all content # might make sense to fetch attachments. # here we conditionaly skip attachment versions if not IAttachedFileVersion.providedBy(trusted): for f in trusted.attached_files: if IAttachedFileVersion.providedBy(f): self.context.append(f) else: if f.attached_file_type != "system": self.context.append(f) self.request = request self.__parent__ = context self.manager = manager self.query = None self.for_display = len(self.context) > 0 self.interaction = getInteraction() self.formatter = utils.date.getLocaleFormatter(self.request, "date", "long") def results(self): for data in self.context: yield { "title": data.file_title, "url": "./files/obj-%i" % data.attached_file_id, "name": data.file_name, "type": _(data.attached_file_type), "status_date": self.formatter.format(data.status_date), "menu": self.generate_file_manipulation_menu(data) } def generate_file_manipulation_menu(self, context): menu_items = [] view_item = self.create_view_menu_item(context) if view_item: menu_items.append(view_item) edit_item = self.create_edit_menu_item(context) if edit_item: menu_items.append(edit_item) delete_item = self.create_delete_menu_item(context) if delete_item: menu_items.append(delete_item) download_item = self.create_download_menu_item(context) if download_item: menu_items.append(download_item) return menu_items def create_view_menu_item(self, context): permission_name = "bungeni.fileattachment.View" if self.interaction.checkPermission(permission_name, self.__parent__): return { "title": _("VIEW"), "url": "./files/obj-%i" % context.attached_file_id, "active": True } return None def create_edit_menu_item(self, context): permission_name = "bungeni.fileattachment.Edit" if self.interaction.checkPermission(permission_name, self.__parent__): return { "title": _("EDIT"), "url": "./files/obj-%i/edit" % context.attached_file_id, "active": True } return None def create_delete_menu_item(self, context): permission_name = "bungeni.fileattachment.Delete" if self.interaction.checkPermission(permission_name, self.__parent__): return { "title": _("DELETE"), "url": "./files/obj-%i/deactivate" % context.attached_file_id, "active": context.status != "inactive" } return None def create_download_menu_item(self, context): permission_name = "bungeni.fileattachment.View" if self.interaction.checkPermission(permission_name, self.__parent__): return { "title": _("DOWNLOAD"), "url": "./files/obj-%i/download" % context.attached_file_id, "active": True } return None
class DiffEditForm(EditForm): """ Form to display diff view if timestamp was changes. """ CustomValidation = validations.diff_validator template = ViewPageTemplateFile("templates/diff-form.pt") def __init__(self, context, request): self.diff_widgets = [] self.diff = False self.last_timestamp = None super(DiffEditForm, self).__init__(context, request) need("diff-form") def update(self): """ Checks if we have Modified errors and renders split view with display widgets for db values and normal for input """ super(DiffEditForm, self).update() for error in self.errors: if error.__class__ == Modified: # Set flag that form is in diff mode if not self.diff: self.diff = True if self.diff: # Set last timestamp which we store in hidden field because # document may be modified during diff and from.timestamp field # contains old value self.last_timestamp = self.context.timestamp for widget in self.widgets: try: value = widget.getInputValue() except: value = "" # Get widget's field form_field = self.form_fields.get(widget.context.__name__) field = form_field.field.bind(self.context) # Form display widget for our field if form_field.custom_widget is not None: display_widget = form_field.custom_widget( field, self.request) else: display_widget = component.getMultiAdapter( (field, self.request), IDisplayWidget) # If field is Text or TextLine we display HTML diff if IText.providedBy(field) or ITextLine.providedBy(field): if value: diff_val = textDiff(field.get(self.context), value) else: diff_val = "" display_widget = component.getMultiAdapter( (field, self.request), IDiffDisplayWidget) display_widget.setRenderedValue(diff_val) else: display_widget.setRenderedValue(field.get(self.context)) display_widget.name = widget.name + ".diff.display" # Add display - input widgets pair to list of diff widgets self.diff_widgets.append((widget, display_widget))
class DeleteForm(PageForm): """Delete-form for Bungeni content. Confirmation The user is presented with a confirmation form which details the items that are going to be deleted. Subobjects Recursively, a permission check is carried out for each item that is going to be deleted. If a permission check fails, an error message is displayed to the user. Will redirect back to the container on success. """ form_template = NamedTemplate("alchemist.form") template = ViewPageTemplateFile("templates/delete.pt") #template = z3evoque.PageViewTemplateFile("delete.html") _next_url = None form_fields = formlib.form.Fields() def _can_delete_item(self, action): return True def nextURL(self): return self._next_url def update(self): self.subobjects = self.get_subobjects() super(DeleteForm, self).update() def get_subobjects(self): return () def delete_subobjects(self): return 0 @formlib.form.action(_(u"Delete"), name="delete", condition=_can_delete_item) def handle_delete(self, action, data): count = self.delete_subobjects() container = self.context.__parent__ trusted = removeSecurityProxy(self.context) session = Session() session.delete(trusted) count += 1 try: session.flush() except IntegrityError, e: # this should not happen in production; it's a critical # error, because the transaction might have failed in the # second phase of the commit session.rollback() log.critical(e) self.status = _( "Could not delete item due to database integrity error. " "You may wish to try deleting any related sub-records first?") return self.render() #TODO: check that it is removed from the index! notify( ObjectRemovedEvent(self.context, oldParent=container, oldName=self.context.__name__)) # we have to switch our context here otherwise the deleted object will # be merged into the session again and reappear magically self.context = container #cascade_modifications(container) next_url = self.nextURL() if next_url is None: next_url = url.absoluteURL(container, self.request) + \ "/?portal_status_message=%d items deleted" % count if self.is_headless: log.info("Deleting in headless mode - No redirection") else: self.request.response.redirect(next_url)
class WhatsOnBrowserView(BrowserView): __call__ = ViewPageTemplateFile("templates/whatson.pt") def __init__(self, context, request): super(WhatsOnBrowserView, self).__init__(context, request) parliament_id = getCurrentParliamentId() if parliament_id: session = Session() parliament = session.query(domain.Parliament).get(parliament_id) self.context = parliament self.context.__parent__ = context self.context.__name__ = "" start_date, end_date = get_date_range(request) if type(start_date) != datetime.date: self.start_date = datetime.date.today() else: self.start_date = start_date if type(end_date) != datetime.date: end_date = datetime.date.today() + datetime.timedelta(10) self.end_date = datetime.datetime(end_date.year, end_date.month, end_date.day, 23, 59) else: self.end_date = datetime.datetime(end_date.year, end_date.month, end_date.day, 23, 59) self.get_items() def get_end_date(self): formatter = self.request.locale.dates.getFormatter('date', 'full') return formatter.format(self.end_date) def get_start_date(self): formatter = self.request.locale.dates.getFormatter('date', 'full') return formatter.format(self.start_date) def get_sitting_items(self, sitting): s_list = [] for schedule in sitting.item_schedule: s_list.append({ 'name': schedule.item.short_name, 'status': misc.get_wf_state(schedule.item), 'url': url.set_url_context( ('/business/' + schedule.item.type + 's/obj-' + str(schedule.item.parliamentary_item_id))), 'item_type': schedule.item.type, }) return s_list def get_sittings(self): formatter = self.request.locale.dates.getFormatter('date', 'full') session = Session() query = session.query(domain.GroupSitting).filter( sql.and_( schema.sittings.c.status.in_( get_states('groupsitting', tagged=['public'])), sql.between(schema.sittings.c.start_date, self.start_date, self.end_date))).order_by( schema.sittings.c.start_date).options( eagerload('group'), #eagerload('sitting_type'), eagerload('item_schedule'), eagerload('item_schedule.item')) sittings = query.all() day = u'' day_list = [] s_dict = {} for sitting in sittings: sday = formatter.format(sitting.start_date) if sday != day: s_list = [] day = sday if s_dict: day_list.append(s_dict) s_dict = {} if sitting.group.type == 'parliament': _url = url.set_url_context('/business/sittings/obj-%i' % (sitting.sitting_id)) elif sitting.group.type == 'committee': _url = url.set_url_context( '/business/committees/obj-%i/sittings/obj-%i' % (sitting.group.group_id, sitting.sitting_id)) else: _url = '#' s_list.append({ 'start': sitting.start_date.strftime("%H:%M"), 'end': sitting.end_date.strftime("%H:%M"), 'type': sitting.group.type, 'name': sitting.group.short_name, 'url': _url, 'items': self.get_sitting_items(sitting), }) s_dict['day'] = day s_dict['sittings'] = s_list else: if s_dict: day_list.append(s_dict) return day_list def get_items(self): session = Session() where_clause = sql.and_( schema.sittings.c.status.in_( get_states("groupsitting", tagged=["public"])), sql.between(schema.sittings.c.start_date, self.start_date, self.end_date)) query = session.query(domain.ItemSchedule).join( domain.GroupSitting).filter(where_clause).order_by( schema.sittings.c.start_date).options( eagerload('sitting'), eagerload('item'), #eagerload('sitting.sitting_type'), lazyload('item.owner')) self.itemschedules = query.all() def get_items_by_type(self, item_type): day = u'' day_list = [] s_dict = {} formatter = self.request.locale.dates.getFormatter('date', 'full') for schedule in self.itemschedules: if type(schedule.item) == item_type: sday = formatter.format(schedule.sitting.start_date) if sday != day: s_list = [] day = sday if s_dict: day_list.append(s_dict) s_dict = {} s_list.append({ 'name': schedule.item.short_name, 'status': misc.get_wf_state(schedule.item), 'url': url.set_url_context("/business/%ss/obj-%s" % (schedule.item.type, schedule.item.parliamentary_item_id)), 'group_type': schedule.sitting.group.type, 'group_name': schedule.sitting.group.short_name }) s_dict['day'] = day s_dict['items'] = s_list if s_dict: day_list.append(s_dict) return day_list def get_questions(self): return self.get_items_by_type(domain.Question) def get_bills(self): return self.get_items_by_type(domain.Bill) def get_motions(self): return self.get_items_by_type(domain.Motion) def get_tableddocuments(self): return self.get_items_by_type(domain.TabledDocument) def get_agendaitems(self): return self.get_items_by_type(domain.AgendaItem)
def render(self): if not self.__updated: raise UpdateNotCalled pageTemplate = ViewPageTemplateFile(self.pageTemplateFileName) return pageTemplate(self)
class WorkflowActionViewlet(BaseForm, viewlet.ViewletBase): """Display workflow status and actions.""" class IWorkflowComment(zope.interface.Interface): note = zope.schema.Text( title=_("Comment on workflow change"), required=True ) form_name = "Workflow" form_fields = form.Fields(IWorkflowComment) actions = () render = ViewPageTemplateFile ('templates/viewlet.pt') def update(self, transition=None): self.adapters = { self.IWorkflowComment: WorkflowComment(), } wf = interfaces.IWorkflow(self.context) if transition is not None: state_transition = wf.getTransitionById(transition) self.status = _( u"Confirmation required for workflow transition: '${title}'", mapping={'title': _(state_transition.title)}) self.setupActions(transition) super(WorkflowActionViewlet, self).update() # after we transition we have different actions self.setupActions(transition) # only display the notes field to comment if there is an action # and a log table auditor = audit.getAuditor( self.context ) if len(self.actions) == 0: self.form_fields = self.form_fields.omit('note') elif auditor is None: self.form_fields = self.form_fields.omit('note') else: note_widget = TextAreaWidget note_widget.height = 1 self.form_fields['note'].custom_widget = note_widget self.setUpWidgets() def setupActions(self, transition): self.wf = interfaces.IWorkflowInfo( self.context ) if transition is None: transitions = self.wf.getManualTransitionIds() else: transitions = (transition,) self.actions = bindTransitions( self, transitions, None, interfaces.IWorkflow(self.context)) def setUpWidgets(self, ignore_request=False): # setup widgets in data entry mode not bound to context self.widgets = form.setUpDataWidgets( self.form_fields, self.prefix, self.context, self.request, ignore_request = ignore_request )
class GlobalTaskListingTab(grok.View, OpengeverTab, ListingView): """A tabbed view mixing which brings support for listing tasks from the SQL (globally over all clients). There is support for searching, batching and ordering. """ implements(IGlobalTaskTableSourceConfig) grok.context(IJournalizable) grok.require('zope2.View') template = ViewPageTemplateFile("generic_task.pt") sort_on = 'modified' sort_reverse = False #lazy must be false otherwise there will be no correct batching lazy = False # the model attributes is used for a dynamic textfiltering functionality model = Task enabled_actions = [] major_actions = [] select_all_template = ViewPageTemplateFile('select_all_globaltasks.pt') selection = ViewPageTemplateFile("selection_tasks.pt") open_states = [ 'task-state-open', 'task-state-in-progress', 'task-state-resolved', 'task-state-rejected', 'forwarding-state-open', 'forwarding-state-refused', ] state_filter_name = 'task_state_filter' columns = ( ('', task_id_checkbox_helper), { 'column': 'review_state', 'column_title': _(u'column_review_state', default=u'Review state'), 'transform': workflow_state }, { 'column': 'title', 'column_title': _(u'column_title', default=u'Title'), 'transform': indexed_task_link_helper }, { 'column': 'task_type', 'column_title': _(u'column_task_type', default=u'Task type'), 'transform': task_type_helper }, { 'column': 'deadline', 'column_title': _(u'column_deadline', default=u'Deadline'), 'transform': overdue_date_helper }, { 'column': 'completed', 'column_title': _(u'column_date_of_completion', default=u'Date of completion'), 'transform': readable_date_set_invisibles }, { 'column': 'responsible', 'column_title': _(u'label_responsible_task', default=u'Responsible'), 'transform': readable_ogds_author }, { 'column': 'issuer', 'column_title': _(u'label_issuer', default=u'Issuer'), 'transform': readable_ogds_author }, { 'column': 'created', 'column_title': _(u'column_issued_at', default=u'Issued at'), 'transform': helper.readable_date }, { 'column': 'containing_dossier', 'column_title': _('containing_dossier', 'Dossier'), }, { 'column': 'client_id', 'column_title': _('column_client', default=u'Client'), 'transform': client_title_helper, 'condition': display_client_title_condition }, { 'column': 'sequence_number', 'column_title': _(u'column_sequence_number', default=u'Sequence number') }, ) __call__ = ListingView.__call__ update = ListingView.update render = __call__
class DhtmlxCalendarSittings(BrowserView): """This view returns xml of the sittings for the week and group requested in a format acceptable by DHTMLX scheduler""" interface.implements(IStructuralView) content_mimetype = "text/xml" template = ViewPageTemplateFile("templates/dhtmlxcalendarxml.pt") def __init__(self, context, request): super(DhtmlxCalendarSittings, self).__init__(ISchedulingContext(context), request) self.context.__name__ = self.__name__ interface.alsoProvides(self.context, ILocation) interface.alsoProvides(self.context, IDCDescriptiveProperties) self.__parent__ = context def get_sessions(self): sessions = [ removeSecurityProxy(session) for key, session in self.context.get_group().sessions.items() if checkPermission("bungeni.session.View", session) ] sessions.sort(key=lambda sess: sess.start_date) return sessions def get_colour(self, event): hx = event.colour if hasattr(event, "colour") else self.event_colour return "#%s" % hx def get_event_type(self, event): return event.__class__.__name__.lower() def get_end_date(self, event): """Get formatted end time of event. For sessions, we set the end time to last hour of last day. """ if model_interfaces.ISession.providedBy(event): return event.end_date.strftime('%Y-%m-%d 24:00') return event.end_date.strftime(DT_FORMAT) def get_event_id(self, event): """This ensures no collission between sessions and sittings """ return create_id(event) def is_readonly(self, event): """Return true if event is readonly """ readonly = 'true' if not model_interfaces.ISession.providedBy(event): if checkPermission("bungeni.sitting.Edit", event): readonly = '' return readonly @property def event_colour(self): if not hasattr(self, "event_color"): rq_color = unicode(self.request.form.get("color", "")) if rq_color: assert len(rq_color) <= 6 self._event_color = rq_color return self._event_color if hasattr(self, "_event_color") else "" @property def sittings_and_sessions(self): event_list = [] try: date = self.request.get("from") dateobj = datetime.datetime(*time.strptime(date, "%Y-%m-%d")[0:5]) start_date = utils.datetimedict.fromdate(dateobj) except: start_date = None try: date = self.request.get("to") dateobj = datetime.datetime(*time.strptime(date, "%Y-%m-%d")[0:5]) end_date = utils.datetimedict.fromdate(dateobj) except: end_date = None if start_date is None: start_date = utils.datetimedict.fromdate(datetime.date.today()) days = tuple(start_date + timedelta(days=d) for d in range(7)) end_date = days[-1] elif end_date is None: start_date = utils.datetimedict.fromdate(datetime.date.today()) days = tuple(start_date + timedelta(days=d) for d in range(7)) end_date = days[-1] sittings = self.context.get_sittings(start_date, end_date) for sitting in sittings.values(): if checkPermission("bungeni.sitting.View", sitting): trusted = removeSecurityProxy(sitting) trusted.text = dict(sitting_status=_( misc.get_wf_state(trusted, trusted.status))) event_list.append(trusted) if model_interfaces.IChamber.providedBy(self.context.get_group()): return event_list + self.get_sessions() else: return event_list def __call__(self): self.request.response.setHeader("Content-type", self.content_mimetype) return self.render() def render(self, template=None): return self.template()
class DhtmlxCalendarSittingsEdit(form.PageForm): """Form to add, edit or delete a sitting that works with DHTMLX scheduler""" #!+ CALENDAR(miano, dec-2010) Add recurrence to the model so that # sittings added as part of a recurrence can be modified as a part of that # recurrence a la google calendar. prefix = "" xml_template = ViewPageTemplateFile( "templates/dhtmlxcalendar_edit_form.pt") template_data = [] def __init__(self, context, request): #dhtmlxscheduler posts the field names prefixed with the id #of the sitting, the code below removes the prefix and set the action to #be performed data = request.form for key in request.form.keys(): t = key.partition("_") request.form[t[2]] = data[key] if request.form.get("event_pid"): request.form["event_pid"] = get_real_id(request.form["event_pid"]) if request.form.get("rec_type") == "none": request.form["!nativeeditor_status"] = "deleted" if "!nativeeditor_status" in request.form.keys(): if request.form["!nativeeditor_status"] == "inserted": request.form["actions.insert"] = "insert" elif request.form["!nativeeditor_status"] == "updated": request.form["actions.update"] = "update" elif request.form["!nativeeditor_status"] == "deleted": request.form["actions.delete"] = "delete" super(DhtmlxCalendarSittingsEdit, self).__init__(context, request) @property def sittings_container(self): traverser = component.getMultiAdapter((self.context, self.request), IPublishTraverse) return traverser.publishTraverse(self.request, "sittings") form_fields = form.Fields(interfaces.IDhtmlxCalendarSittingsEditForm) def setUpWidgets(self, ignore_request=False): class context: ids = None event_pid = None short_name = None start_date = None end_date = None location = None language = None venue = None rec_type = None event_length = None nativeeditor_status = None activity_type = None meeting_type = None convocation_type = None context.__parent__ = self.context self.adapters = {interfaces.IDhtmlxCalendarSittingsEditForm: context} self.widgets = form.setUpEditWidgets(self.form_fields, "", self.context, self.request, adapters=self.adapters, ignore_request=ignore_request) def insert_sitting_failure_handler(self, action, data, errors): error_message = _(u"Unable to add a sitting. Please make corrections.") error_string = u"" for error in errors: if error.message not in ("", None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" #!+CALENDAR(mb, oct-2011) Include error messages in XML log.error(error_message) log.error(error_string) self.template_data.append( dict(action="invalid", ids=data["ids"], sitting_id=data["ids"])) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template() def generate_dates(self, data): trusted = removeSecurityProxy(ISchedulingContext(self.context)) recurrence_start_date = data["start_date"].replace(tzinfo=None) recurrence_end_date = data["rec_end_date"].replace(tzinfo=None) group = trusted.get_group() # If group is none then there is a big problem assert group is not None year = timedelta(days=365) now = datetime.datetime.now() if (((group.end_date is not None) and ((now + year) < group.end_date)) or (group.end_date is None)): end = now + year else: end = group.end_date if recurrence_end_date > end: recurrence_end_date = end return utils.generate_recurrence_dates(recurrence_start_date, recurrence_end_date, data["rec_type"]) # The form action strings below do not need to be translated because they are # not visible in the UI. @form.action(u"insert", failure="insert_sitting_failure_handler") def handle_insert(self, action, data): session = Session() data["rec_end_date"] = data["end_date"] self.template_data = [] initial_sitting = None length = data["event_length"] venue_id = unicode(data["venue"]) if data['venue'] else None if data.get("rec_type") not in [None, "none"]: data["end_date"] = data["start_date"] + timedelta(seconds=length) self.request.form["end_date"] = data["end_date"].strftime( DT_FORMAT) data["headless"] = "true" self.request.form["venue_id"] = data["venue_id"] = venue_id self.request.form["headless"] = "true" add_form = AddForm(self.sittings_container, self.request) add_form.update() if not add_form.errors: initial_sitting = removeSecurityProxy(add_form.created_object) else: return self.insert_sitting_failure_handler(action, data, add_form.errors) if ("rec_type" in data.keys()) and (data["rec_type"] not in [None, "none"]): # create recurring sittings #base_sitting_length = sitting_length + timedelta(hours=1) sitting_length = timedelta(seconds=length) base_sitting_length = timedelta(seconds=length) + timedelta( hours=1) dates = self.generate_dates(data) initial_sitting.recurring_type = data.get("rec_type") initial_sitting.recurring_id = 0 initial_sitting.sitting_length = length for count, date in enumerate(dates): if not count: #we've already added the initial sitting initial_sitting.recurring_end_date = ( dates[len(dates) - 1] + base_sitting_length) session.merge(initial_sitting) continue sitting_data = copy(data) sitting_data["start_date"] = date.strftime(DT_FORMAT) sitting_data["end_date"] = (date + sitting_length).strftime(DT_FORMAT) request_copy = copy(self.request) request_copy.form = sitting_data add_form = AddForm(self.sittings_container, request_copy) add_form.update() if not add_form.errors: # use finishConstruction API here obj = add_form.created_object obj.sitting_length = int(time.mktime(date.timetuple())) obj.recurring_id = initial_sitting.sitting_id session.merge(obj) else: initial_sitting.recurring_type = data.get("rec_type") initial_sitting.recurring_id = data.get("event_pid", 0) if data.get("event_length"): initial_sitting.sitting_length = data.get("event_length") session.merge(initial_sitting) wfc = IWorkflowController(initial_sitting) wfc.fireAutomatic() sitting_action = "inserted" if data["rec_type"] == "none": sitting_action = "deleted" session.merge(initial_sitting) self.template_data.append({ "sitting_id": initial_sitting.sitting_id, "action": sitting_action, "ids": data["ids"], }) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template() def update_sitting_failure_handler(self, action, data, errors): error_string = u"" error_message = _(u"Error Updating Sitting") for error in errors: if error.message not in ("", None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" log.error(error_message) log.error(error_string) self.template_data.append( dict(action="invalid", ids=data["ids"], sitting_id=data["ids"])) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template() @form.action(u"update", failure="update_sitting_failure_handler") def handle_update(self, action, data): session = Session() self.template_data = [] venue_id = unicode(data["venue"]) if data['venue'] else None data["rec_end_date"] = data["end_date"] data["headless"] = 'true' self.request.form["venue_id"] = data["venue_id"] = venue_id self.request.form["headless"] = "true" if ("rec_type" in data.keys()) and (data["rec_type"] is not None): # updating recurring events - we assume existing events fall # at the beginning of the sequence and offer in place update. parent_sitting_id = get_real_id(data["ids"] or data["event_pid"]) length = data["event_length"] sitting_length = timedelta(seconds=length) base_sitting_length = sitting_length + timedelta(hours=1) siblings_filter = or_( domain.Sitting.recurring_id == parent_sitting_id, domain.Sitting.sitting_id == parent_sitting_id) siblings = [ sitting for sitting in self.sittings_container.batch( order_by=(domain.Sitting.sitting_id), limit=None, filter=siblings_filter) ] dates = self.generate_dates(data) current_count = len(siblings) for count, date in enumerate(dates): is_new = not count < current_count sitting_data = copy(data) sitting_data["start_date"] = date.strftime(DT_FORMAT) sitting_data["end_date"] = (date + sitting_length).strftime(DT_FORMAT) request_copy = copy(self.request) request_copy.form = sitting_data if is_new: add_form = AddForm(self.sittings_container, request_copy) add_form.update() if add_form.errors: log.error("Could not add sitting in sequence: %s", sitting_data) continue else: sitting = add_form.created_object sitting.recurring_id = parent_sitting_id else: sitting = siblings[count] if not count: sitting.recurring_end_date = dates[len(dates) - 1] + base_sitting_length sitting.recurring_type = data.get("rec_type") sitting.recurring_id = 0 sitting.sitting_length = length else: sitting.sitting_length = int(time.mktime(date.timetuple())) sitting.recurring_type = None if not is_new: edit_form = EditForm(sitting, request_copy) edit_form.update() if edit_form.errors: continue else: session.merge(edit_form.context) else: session.merge(sitting) self.template_data.append({ "sitting_id": sitting.sitting_id, "action": (is_new and "inserted" or "updated"), "ids": create_id(sitting) }) #delete any sittings outside recurring bounds for del_sibling in siblings[len(dates):]: delete_form = DeleteForm(del_sibling, self.request) delete_form.update() if delete_form.errors: continue else: self.template_data.append({ "sitting_id": del_sibling.sitting_id, "action": "deleted", "ids": create_id(del_sibling) }) else: sitting_id = get_real_id(data["ids"]) parent_id = get_real_id(data["event_pid"]) sitting = self.sittings_container.get(sitting_id) if sitting is None: sitting = self.sittings_container.get(int(parent_id)) edit_form = EditForm(sitting, self.request) edit_form.update() if edit_form.errors: return self.update_sitting_failure_handler( action, data, edit_form.errors) else: sitting.sitting_length = data.get("event_length") sitting = removeSecurityProxy(sitting) session.merge(sitting) self.template_data.append({ "sitting_id": sitting.sitting_id, "action": "updated", "ids": data["ids"], }) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template() def delete_sitting_failure_handler(self, action, data, errors): error_string = u"" error_message = _(u"Error Deleting Sitting") for error in errors: if error.message not in ("", None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" log.error(error_message) log.error(error_string) self.template_data.append( dict(action="inserted", ids=data["ids"], sitting_id=data["ids"])) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template() @form.action(u"delete", failure="delete_sitting_failure_handler") def handle_delete(self, action, data): self.template_data = [] if ISchedulingContext.providedBy(self.context): container = removeSecurityProxy(self.context.__parent__).sittings else: container = self.context.publishTraverse(self.request, "sittings") sitting = (container.get(get_real_id(data["ids"])) or container.get( get_real_id(self.request.form["event_pid"]))) self.template_data = [] if sitting is not None: self.request.form["headless"] = "true" delete_form = DeleteForm(sitting, self.request) delete_form.update() if not delete_form.errors: self.template_data.append({ "sitting_id": sitting.sitting_id, "action": "deleted", "ids": data["ids"], }) else: return self.delete_sitting_failure_handler( action, data, delete_form.errors) self.request.response.setHeader("Content-type", "text/xml") return self.xml_template()
class BungeniCalendarMacros(BrowserView): template = ViewPageTemplateFile('calendar/templates/macros.pt') def __getitem__(self, key): return self.template.macros[key]
from bungeni.ui.forms.common import ReorderForm from bungeni.ui.forms.common import PageForm from bungeni.ui.forms.common import AddForm from bungeni.ui.forms.common import EditForm from bungeni.ui.forms.common import DeleteForm from bungeni.ui.forms.common import DisplayForm from interfaces import Modified from zope import component from zope.formlib.interfaces import IDisplayWidget from zope.schema.interfaces import IText, ITextLine from bungeni.ui.widgets import IDiffDisplayWidget from bungeni.ui.diff import textDiff FormTemplate = namedtemplate.NamedTemplateImplementation( ViewPageTemplateFile("templates/form.pt")) ContentTemplate = namedtemplate.NamedTemplateImplementation( ViewPageTemplateFile("templates/content.pt")) def hasDeletePermission(context): """Generic check if the user has rights to delete the object. The permission must follow the convention: ``bungeni.<classname>.Delete`` where "classname" is the lowercase of the name of the python class. """ interaction = zope.security.management.getInteraction() class_name = context.__class__.__name__ permission_name = "bungeni.%s.Delete" % class_name.lower() return interaction.checkPermission(permission_name, context)
class Search(forms.common.BaseForm, ResultListing, HighlightMixin): """ basic content search form and results """ template = ViewPageTemplateFile('templates/search.pt') form_fields = form.Fields(ISearch, IHighLight) #selection_column = columns[0] def setUpWidgets(self, ignore_request=False): # setup widgets in data entry mode not bound to context self.adapters = {} self.widgets = form.setUpDataWidgets(self.form_fields, self.prefix, self.context, self.request, ignore_request=ignore_request) @property def doc_count(self): return len(self._searchresults) def authorized(self, result): obj = result.object() defaultview = getDefaultViewName(obj, self.request) view = queryMultiAdapter((ProxyFactory(obj), self.request), name=defaultview) return canAccess(view, "__call__") def get_description(self, item): return item.description def get_title(self, item): return "%s %s" % (translate_obj( item.origin, self.request.locale.id.language).short_name, _(u"changes from")) def get_url(self, item): site = getSite() base_url = absoluteURL(site, self.request) return base_url + "/business/%ss/obj-%s" % ( item.origin.type, item.origin.parliamentary_item_id) def get_user_subscriptions(self): """ Getting user subscribed items """ session = Session() user = session.query(domain.User).filter( domain.User.login == self.request.principal.id).first() return user.subscriptions def workspace_search(self): """ Search in workspace section, based on views from bungeni.ui.viewlets.workspace """ application = common.get_application() parliament = get_current_parliament(None) parliament.__parent__ = application principal = get_principal() roles = common.get_context_roles(parliament, principal) # minister role, filtering by states and object_type and ministry_id if not roles: user_id = get_db_user_id() government_id = get_current_parliament_governments( parliament)[0].group_id ministries = get_ministries_for_user_in_government( user_id, government_id) if ministries: states = workspace.MinistryArchiveViewlet.states + \ workspace.OralMinistryQuestionsViewlet.states + \ workspace.WrittenMinistryQuestionsViewlet.states + \ workspace.InProgressMinistryItemsViewlet.states states = set(states) ministry_ids = [m.group_id for m in ministries] # filter by object_type (questions only) type_query = self.searcher.query_field('object_type', "Question") query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, type_query,)) subqueries = [] for state in states: subqueries.append( self.searcher.query_field('status', state)) state_query = self.searcher.query_composite( self.searcher.OP_OR, subqueries) query = self.searcher.query_composite(self.searcher.OP_AND, \ (query, state_query,)) #filter for ministries ministries_queries = [] for mid in ministry_ids: ministries_queries.append( self.searcher.query_field('ministry_id', str(mid))) m_query = self.searcher.query_composite( self.searcher.OP_OR, ministries_queries) query = self.searcher.query_composite(self.searcher.OP_AND, \ (query, m_query,)) try: results = self.searcher.search( query, 0, self.searcher.get_doccount()) except: results = [] return list(results) # filtering by states and owner if 'bungeni.MP' in roles: states = workspace.MPItemActionRequiredViewlet.states + \ workspace.MPItemDraftViewlet.states + \ workspace.MPItemInProgressViewlet.states + \ workspace.ItemArchiveViewlet.states states = set(states) # filter by owner of PI owner_query = self.searcher.query_field('owner', str(get_db_user_id())) query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, owner_query,)) subqueries = [] for state in states: subqueries.append(self.searcher.query_field('status', state)) state_query = self.searcher.query_composite( self.searcher.OP_OR, subqueries) query = self.searcher.query_composite(self.searcher.OP_AND, \ (query, state_query,)) try: results = self.searcher.search(query, 0, self.searcher.get_doccount()) except: results = [] return list(results) # filtering by states if 'bungeni.Clerk' in roles: states = workspace.ClerkItemActionRequiredViewlet.states + \ workspace.ClerkItemsWorkingDraftViewlet.states + \ workspace.ClerkReviewedItemViewlet.states + \ workspace.ItemsApprovedViewlet.states + \ workspace.ItemsPendingScheduleViewlet.states + \ workspace.ItemsScheduledViewlet.states + \ workspace.AllItemArchiveViewlet.states states = set(states) subqueries = [] for state in states: subqueries.append(self.searcher.query_field('status', state)) state_query = self.searcher.query_composite( self.searcher.OP_OR, subqueries) query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, state_query,)) try: results = self.searcher.search(query, 0, self.searcher.get_doccount()) except: results = [] return list(results) # no results return False @CachedProperty def _searchresults(self): section = get_section_name() subqueries = [] # Filter items allowed in current section for tq in ALLOWED_TYPES[section]: subqueries.append(self.searcher.query_field('object_type', tq)) type_query = self.searcher.query_composite(self.searcher.OP_OR, subqueries) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, type_query,)) try: results = self.searcher.search(self.query, 0, self.searcher.get_doccount()) except: results = [] results = filter(self.authorized, results) # in workspace section we are using different search filters based on states if section == 'workspace': extra = self.workspace_search() # if no results - use common search if extra: return extra return results @property def _results(self): return map(lambda x: x.object(), self._searchresults) @form.action(label=_(u"Search")) def handle_search(self, action, data): self.searcher = component.getUtility(interfaces.IIndexSearch)() search_term = data['full_text'] if not search_term: self.status = _(u"Invalid Query") return # compose query t = time.time() lang = self.request.locale.getLocaleID() if lang == "en_US": lang = "en" if lang == "en_KE": lang = "en-ke" text_query = self.searcher.query_parse(search_term) lang_query = self.searcher.query_field('language', lang) self.query = self.searcher.query_composite(self.searcher.OP_AND, ( text_query, lang_query, )) self.results = self._results self.search_time = time.time() - t # spelling suggestions suggestion = self.searcher.spell_correct(search_term) self.spelling_suggestion = (search_term != suggestion and suggestion or None)
class AttendanceEditor(BungeniBrowserView, ui.BaseForm): """Multiple attendance record editor for sittings""" form_fields = [] render = ViewPageTemplateFile("templates/attendance.pt") def __init__(self, context, request): super(AttendanceEditor, self).__init__(context, request) @property def radio_prefix(self): return "sitting_attendance_radio" @property def columns(self): listing_columns = [ column.GetterColumn(title=_("full names"), getter=lambda i, f: i.get("attendee")) ] for rcount, at_type in enumerate(self.attendance_types): at_column = column.GetterColumn( title=at_type.title, getter=lambda i, f: i, cell_formatter=lambda g, i, f, rc=rcount: \ '<input type="radio" name="%s" value="%s"%s/>' % ( i["records"][rc]["name"], i["records"][rc]["value"], i["records"][rc]["checked"] and ' checked="checked"' or "" ) ) listing_columns.append(at_column) return listing_columns def make_id(self, value): return "".join( (self.radio_prefix, "".join(str(value).encode("base64").split()))) @property def column_titles(self): return [at.title for at in self.attendance_types] @property def attendance_types(self): """ () -> zope.schema.vocabulary.SimpleVocabulary.""" from bungeni.ui import vocabulary # !+ return vocabulary.attendance_type @property def formatted_listing(self): formatter = TableFormatter( self.context, self.request, self.listing, prefix="attendance", visible_column_names=[c.name for c in self.columns], columns=self.columns) formatter.updateBatching() return formatter() @property def listing(self): list_data = [] trusted = removeSecurityProxy(self.context) current_attendance = list(trusted.attendance.values()) for member in trusted.group.group_members: attd = filter(lambda i: i.member_id == member.user_id, current_attendance) m_data = {} m_data["attendee"] = IDCDescriptiveProperties(member).title m_data["has_record"] = int(bool(attd)) m_data["records"] = [{ "name": self.make_id(member.user_id), "checked": bool(attd) and (attd[0].attendance_type == at_type.value), "value": at_type.value } for at_type in self.attendance_types] list_data.append(m_data) sorted_list = sorted(list_data, key=itemgetter("has_record", "attendee")) return sorted_list def has_listing(self, action): return bool(len(self.listing)) @property def action_url(self): return "" @property def action_method(self): return "post" @formlib.form.action(label=_("Save"), name="save", condition=has_listing) def handle_save(self, action, data): self.process_attendance() @formlib.form.action(label=_("Save and view"), name="save_and_view", condition=has_listing) def handle_save_view(self, action, data): self.process_attendance() next_url = url.absoluteURL(self.__parent__, self.request) self.request.response.redirect(next_url + "/attendance") @formlib.form.action(label=_("Cancel"), name="cancel") def handle_cancel(self, action, data): next_url = url.absoluteURL(self.__parent__, self.request) self.request.response.redirect(next_url) def setUpWidgets(self, ignore_request=False): actions = self.actions self.actions = [] for action in actions: if getattr(action, "condition", None): if action.condition(self, self.context): self.actions.append(action) else: self.actions.append(action) super(AttendanceEditor, self).setUpWidgets(self) def get_selected(self): selected = [ { "user_id": k[len(self.radio_prefix):].decode("base64"), "attendance_type": self.request.form.get(k) } for k in self.request.form.keys() if k.startswith(self.radio_prefix) and self.request.form.get(k) ] return selected def process_attendance(self): session = Session() trusted = removeSecurityProxy(self.context) gs_id = trusted.sitting_id for selection in self.get_selected(): member_id = selection.get("user_id") if not member_id: continue at = selection.get("attendance_type") if not at: continue member_id = int(member_id) # check existing attendance record query = session.query(SittingAttendance).filter( sql.and_(SittingAttendance.member_id == member_id, SittingAttendance.sitting_id == gs_id)) result = query.first() if result is not None: result.attendance_type = at session.flush() zope.event.notify( zope.lifecycleevent.ObjectModifiedEvent( result, zope.lifecycleevent.Attributes(ISittingAttendance, "attendance_type"))) else: m_attendance = SittingAttendance() m_attendance.sitting_id = gs_id m_attendance.attendance_type = at m_attendance.member_id = member_id session.add(m_attendance) session.flush() zope.event.notify( zope.lifecycleevent.ObjectCreatedEvent(m_attendance)) self.status = _("Updated attendance record") def __call__(self): self.update() return self.render()
class SchedulingContextAgendaReportView(ReportView): result_template = ViewPageTemplateFile( "templates/default-report_scheduling.pt") display_minutes = False include_text = False note = ""
class MyGroupsViewlet(ViewletBase): name = _("My Groups") list_id = "my_groups" render = ViewPageTemplateFile("templates/workspace_group_viewlet.pt") def _setData(self): """Return the data of the query """ formatter = date.getLocaleFormatter(self.request, "date", "long") data_list = [] results = self.query.all() # if no current parliament, no data try: parliament_id = model_utils.get_current_parliament().parliament_id except: return data_list # government_id = self.__parent__.government_id for result in results: data = {} data["qid"] = "g_%s" % (result.group_id) data["subject"] = result.short_name data["title"] = "%s (%s)" % (result.short_name, result.type) data["result_item_class"] = "workflow-state-%s" % (result.status) _url = "/archive/browse/parliaments/obj-%s" % (parliament_id) if type(result) == domain.Parliament: data["url"] = url.set_url_context(_url) continue elif type(result) == domain.Committee: #data["url"] = url + "/committees/obj-" + str(result.group_id) data["url"] = url.set_url_context( "/groups/%s/%s" % (result.parent_group.group_principal_id, result.group_principal_id)) elif type(result) == domain.PoliticalGroup: data["url"] = url.set_url_context("%s/politicalgroups/obj-%s" % (_url, result.group_id)) elif type(result) == domain.Ministry: data["url"] = url.set_url_context( "%s/governments/obj-%s/ministries/obj-%s" % (_url, government_id, result.group_id)) else: data["url"] = "#" data["status"] = misc.get_wf_state(result) data["status_date"] = formatter.format(result.status_date) data["owner"] = "" data["type"] = _(result.type) data["to"] = "" data_list.append(data) self._data = data_list def update(self): """refresh the query """ session = Session() #user_id = self.__parent__.user_id #parliament_id = self.__parent__.context.parliament_id group_ids = self.__parent__.user_group_ids gfilter = sql.and_(domain.Group.group_id.in_(group_ids), domain.Group.status == "active") groups = session.query(domain.Group).filter(gfilter) self.query = groups self._setData()
class CalendarView(BungeniBrowserView): """Main calendar view.""" interface.implements(IStructuralView) template = ViewPageTemplateFile("templates/dhtmlxcalendar.pt") short_name = u"Scheduling" def __init__(self, context, request): log.debug("CalendarView.__init__: %s" % (context)) super(CalendarView, self).__init__(ISchedulingContext(context), request) def __call__(self, timestamp=None): log.debug("CalendarView.__call__: %s" % (self.context)) trusted = removeSecurityProxy(self.context) trusted.__name__ = self.__name__ interface.alsoProvides(trusted, ILocation) if (IBusinessSectionLayer.providedBy(self.request) and isinstance(trusted, SittingContainerSchedulingContext)): self.url = url.absoluteURL(trusted.__parent__.__parent__, self.request) else: self.url = url.absoluteURL(trusted.__parent__, self.request) self.title = ISchedulingContext(self.context).label log.debug(debug.interfaces(self)) log.debug(debug.location_stack(self)) return self.render() def publishTraverse(self, request, name): traverser = component.getMultiAdapter((self.context, request), IPublishTraverse) return traverser.publishTraverse(request, name) def render(self, template=None): need("dhtmlxscheduler") need("dhtmlxscheduler-recurring") if template is None: template = self.template if (not checkPermission(u"bungeni.sitting.Add", self.context)) or \ (IBusinessSectionLayer.providedBy(self.request)): self.edit = False else: self.edit = True session = Session() venues = session.query(domain.Venue).all() languages = get_all_languages() # !+SESSION_CLOSE(taras.sterch, july-2011) there is no need to close the # session. Transaction manager will take care of this. Hope it does not # brake anything. #session.close() self.display_language = get_default_language() if self.request.get("I18N_LANGUAGE"): self.display_language = self.request.get("I18N_LANGUAGE") #html is hardcoded in here because doing it in the template #would have been a colossal pain #TODO: FIX THIS s = '<div class="dhx_cal_ltext" style="height:90px;">' s += '<table>' s += '<tr><td>Venue</td><td><select id="select_sitting_venue">' for venue in venues: s += '<option value="' + str( venue.venue_id) + '">' + venue.short_name + '</option>' s += '</select></td></tr>' s += '<tr><td>Language</td><td><select id="select_sitting_lang">' for lang in languages: if lang == 'en': s += '<option value="' + lang + '" selected>' + lang + '</option>' else: s += '<option value="' + lang + '">' + lang + '</option>' s += '</select></td></tr></table></div>' self.sitting_details_form = s return template()
class Search(forms.common.BaseForm, ResultListing, HighlightMixin): """ basic content search form and results """ template = ViewPageTemplateFile('templates/search.pt') form_fields = form.Fields(ISearch, IHighLight) #selection_column = columns[0] def setUpWidgets(self, ignore_request=False): # setup widgets in data entry mode not bound to context self.adapters = {} self.widgets = form.setUpDataWidgets(self.form_fields, self.prefix, self.context, self.request, ignore_request=ignore_request) @property def doc_count(self): return len(self._searchresults) def authorized(self, result): obj = result.object() defaultview = getDefaultViewName(obj, self.request) view = queryMultiAdapter((ProxyFactory(obj), self.request), name=defaultview) return canAccess(view, "__call__") def get_description(self, item): return item.description def get_title(self, item): return "%s %s" % (translate_obj( item.origin, self.request.locale.id.language).short_name, _(u"changes from")) def get_url(self, item): site = getSite() base_url = absoluteURL(site, self.request) return base_url + "/business/%ss/obj-%s" % ( item.origin.type, item.origin.parliamentary_item_id) def get_user_subscriptions(self): """ Getting user subscribed items """ session = Session() user = session.query(domain.User).filter( domain.User.login == self.request.principal.id).first() return user.subscriptions @CachedProperty def _searchresults(self): section = get_section_name() subqueries = [] # Filter items allowed in current section for tq in ALLOWED_TYPES[section]: subqueries.append(self.searcher.query_field('object_type', tq)) type_query = self.searcher.query_composite(self.searcher.OP_OR, subqueries) self.query = self.searcher.query_composite(self.searcher.OP_AND, \ (self.query, type_query,)) try: results = self.searcher.search(self.query, 0, self.searcher.get_doccount()) except: results = [] results = filter(self.authorized, results) return results @property def _results(self): return map(lambda x: x.object(), self._searchresults) @form.action(label=_(u"Search")) def handle_search(self, action, data): self.searcher = component.getUtility(interfaces.IIndexSearch)() search_term = data['full_text'] if not search_term: self.status = _(u"Invalid Query") return # compose query t = time.time() lang = self.request.locale.getLocaleID() if lang == "en_US": lang = "en" if lang == "en_KE": lang = "en-ke" text_query = self.searcher.query_parse(search_term) lang_query = self.searcher.query_field('language', lang) self.query = self.searcher.query_composite(self.searcher.OP_AND, ( text_query, lang_query, )) self.results = self._results self.search_time = time.time() - t # spelling suggestions suggestion = self.searcher.spell_correct(search_term) self.spelling_suggestion = (search_term != suggestion and suggestion or None)
class GroupSittingScheduleView(BrowserView): """Group-sitting scheduling view. This view presents a sitting and provides a user interface to manage the agenda. """ template = ViewPageTemplateFile("templates/main.pt") ajax = ViewPageTemplateFile("templates/ajax.pt") _macros = ViewPageTemplateFile("templates/macros.pt") def __init__(self, context, request): super(GroupSittingScheduleView, self).__init__(context, request) self.__parent__ = context def __call__(self, timestamp=None): session = Session() if timestamp is None: # start the week on the first weekday (e.g. Monday) date = utils.datetimedict.fromdate(datetime.date.today()) else: try: timestamp = float(timestamp) except: raise TypeError("Timestamp must be floating-point (got %s)" % timestamp) date = utils.datetimedict.fromtimestamp(timestamp) #if misc.is_ajax_request(self.request): if self.request.get('headless') == 'true': rendered = self.render(date, template=self.ajax) else: rendered = self.render(date) # !+SESSION_CLOSE(taras.sterch, july-2011) there is no need to close the # session. Transaction manager will take care of this. Hope it does not # brake anything. #session.close() return rendered def reorder_field(self): if self.context.status == "draft_agenda": return 'planned_order' elif self.context.status == "draft_minutes": return 'real_order' else: return None def render(self, date, template=None): #need('yui-editor') need('yui-rte') need('yui-resize') need('yui-button') if template is None: template = self.template container = self.context.__parent__ #schedule_url = self.request.getURL() container_url = url.absoluteURL(container, self.request) # determine position in container key = stringKey(self.context) keys = list(container.keys()) pos = keys.index(key) links = {} if pos > 0: links['previous'] = "%s/%s/%s" % (container_url, keys[pos - 1], self.__name__) if pos < len(keys) - 1: links['next'] = "%s/%s/%s" % (container_url, keys[pos + 1], self.__name__) #start_date = utils.datetimedict.fromdatetime(self.context.start_date) #end_date = utils.datetimedict.fromdatetime(self.context.end_date) site_url = url.absoluteURL(getSite(), self.request) reorder = "reorder" if self.context.status in \ ["draft_agenda", "draft_minutes"] \ else "dont-reorder" return template( display="sitting", #title=_(u"$A $e, $B $Y", mapping=start_date), title="%s: %s - %s" % (self.context.group.short_name, self.context.start_date.strftime('%Y-%m-%d %H:%M'), self.context.end_date.strftime('%H:%M')), description=_(u"Sitting Info"), # title = u"", # description = u"", # links=links, actions=get_sitting_actions(self.context, self.request), items=get_sitting_items(self.context, self.request, include_actions=True), #categories=vocabulary.ItemScheduleCategories(self.context), new_category_url="%s/admin/content/categories/add?next_url=..." % site_url, status=self.context.status, reorder=reorder, ) @property def macros(self): return self._macros.macros
class Many2ManyEdit(RelationTableBaseViewlet): selection_column = column.SelectionColumn(lambda item: str(item.id), name="selection") state = 'listing' template = ViewPageTemplateFile('templates/relation-edit.pt') def setUpColumns(self): columns = super(Many2ManyEdit, self).setUpColumns() columns.insert(0, self.selection_column) return columns def update(self): # we capture state from the last processed action, so our next action # becomes available. self.state = self.request.get("%s.state" % self.property_name, self.state) # our previous state when we process searches is the add state, in order # to process the form values for the search action, we need to have search # widgets setup prior to the handler invocation, so do that here.. if self.state == 'add': self.form_fields = core.setUpFields(self.domain_model, mode='search') # if we're doing a listing prepopulate state before rendering so we # display empty results status, and for a delete do it eagerly so # we can check our condition if self.state in ('listing', 'delete'): self.results = getattr(self.context, self.property_name) super(Many2ManyEdit, self).update() # if our state changes to listing if not self.results and self.state == 'listing': self.results = getattr(self.context, self.property_name) def condition_search(self, action): return self.state == 'add' @form.action(u"Search", condition='condition_search') def handle_search(self, action, data): """ search the other end point of m2m relationship for rows to associate. """ self.state = 'search' d = core.constructQuery(self.form_fields, self.domain_model, data) context = proxy.removeSecurityProxy(self.context) mapper = orm.class_mapper(self.domain_model) instance_pkey = mapper.primary_key_from_instance pkey = mapper.primary_key[0] query = Session().query(self.domain_model) query = query.filter( rdb.not_( pkey.in_( [ob.id for ob in getattr(context, self.property_name)]))) if not d: self.results = query.all() return self.results = query.filter(*(d.values())).all() def condition_add(self, action): return self.state == 'listing' @form.action(u"Add", condition='condition_add') def handle_add(self, action, data): """ sends user to search form. """ self.state = 'add' session = Session() related_count = session.query(self.domain_model).count() if related_count > 20: self.form_fields = core.setUpFields(self.domain_model, mode='search') else: self.state = 'search' query = session.query(self.domain_model) context = proxy.removeSecurityProxy(self.context) collection = getattr(context, self.property_name) if collection: mapper = orm.class_mapper(self.domain_model) instance_pkey = mapper.primary_key_from_instance pkey = mapper.primary_key[0] query = query.filter( rdb.not_( pkey.in_([ instance_pkey(ob)[0] for ob in getattr(context, self.property_name) ]))) self.results = query.all() def condition_delete(self, action): return self.state == 'listing' and self.results @form.action(u"Delete", condition='condition_delete') def handle_delete(self, action, data): """ delete the selected items from the m2m relationship. """ # reset form state self.state = 'listing' # first we need to dereference the selection column values into # objects to disassociate. values = core.getSelectedObjects(self.selection_column, self.request, self.domain_model) if not values: self.status = "No %s Selected" % ( self.domain_model.__name__.title() + 's') return # remove objects from association association = getattr(self.context, self.property_name) for v in values: if v in association: association.remove(v) # pluralize properly if len(values) > 1: self.status = "%s Removed" % (self.domain_model.__name__.title() + 's') else: self.status = "%s Removed" % self.domain_model.__name__.title() def condition_associate(self, action): return self.state == 'search' @form.action(u"Associate", condition='condition_associate') def handle_associate(self, action, data): """ associate a search result with the context. """ # reset viewlet state to listing of associated objects self.state = 'listing' # first we need to dereference the selection column values into # objects to associate. values = core.getSelectedObjects(self.selection_column, self.request, self.domain_model) # add objects to the association association = proxy.removeSecurityProxy( getattr(self.context, self.property_name)) for v in values: if v not in association: association.append(v) # pluralize properly if len(values) > 1: self.status = "%s Associated" % ( self.domain_model.__name__.title() + 's') else: self.status = "%s Associated" % self.domain_model.__name__.title() # reset selection column self.form_reset = True def condition_cancel(self, action): return self.state != 'listing' @form.action(u"Cancel", condition='condition_cancel') def handle_cancel(self, action, data): """ cancel the current operation and go back to the view """ self.state = 'listing'
class DhtmlxCalendarSittingsEdit(form.PageForm): """Form to add, edit or delete a sitting that works with DHTMLX scheduler""" #!+ CALENDAR(miano, dec-2010) Add recurrence to the model so that # sittings added as part of a recurrence can be modified as a part of that # recurrence a la google calendar. prefix = "" xml_template = ViewPageTemplateFile( "templates/dhtmlxcalendar_edit_form.pt") template_data = [] def __init__(self, context, request): #dhtmlxscheduler posts the field names prefixed with the id #of the sitting, the code below removes the prefix and set the action to #be performed data = request.form for key in request.form.keys(): t = key.partition("_") request.form[t[2]] = data[key] if "!nativeeditor_status" in request.form.keys(): if request.form["!nativeeditor_status"] == "inserted": request.form["actions.insert"] = "insert" elif request.form["!nativeeditor_status"] == "updated": request.form["actions.update"] = "update" elif request.form["!nativeeditor_status"] == "deleted": request.form["actions.delete"] = "delete" super(DhtmlxCalendarSittingsEdit, self).__init__(context, request) class DhtmlxCalendarSittingsEditForm(interface.Interface): ids = schema.TextLine(title=u'ID', description=u'Sitting ID', required=False) start_date = schema.Datetime( title=_(u"Start Date and Time"), description=_(u"Choose a start date and time"), required=True) end_date = schema.Datetime( title=_(u"End Date and Time"), description=_(u"Choose an end date and time"), required=True) venue = schema.Choice(title=_(u"Venue"), source="bungeni.vocabulary.Venues", description=_(u"Venues"), required=True) language = schema.Choice(title=_(u"Language"), default=get_default_language(), vocabulary="language_vocabulary", description=_(u'Language'), required=True) rec_type = schema.TextLine(title=u'Recurrence Type', required=False, description=u"A string that contains the \ rules for reccurent sittings if any" ) event_length = schema.TextLine(title=u'Event Length', required=False, description=u'Length of event') nativeeditor_status = schema.TextLine(title=u'editor status', required=False, description=u'Editor Status') form_fields = form.Fields(DhtmlxCalendarSittingsEditForm) def setUpWidgets(self, ignore_request=False): class context: ids = None start_date = None end_date = None location = None language = None venue = None rec_type = None event_length = None nativeeditor_status = None self.adapters = {self.DhtmlxCalendarSittingsEditForm: context} self.widgets = form.setUpEditWidgets(self.form_fields, "", self.context, self.request, adapters=self.adapters, ignore_request=ignore_request) def insert_sitting_failure_handler(self, action, data, errors): error_message = _( u"The following errors occured while adding a sitting") error_string = u"" for error in errors: if error.message not in ('', None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" return "%s \n%s" % (error_message, error_string) # The form action strings below do not need to be translated because they are # not visible in the UI. @form.action(u"insert", failure='insert_sitting_failure_handler') def handle_insert(self, action, data): session = Session() self.template_data = [] trusted = removeSecurityProxy(ISchedulingContext(self.context)) if ("rec_type" in data.keys()) and (data["rec_type"] is not None): # !+ DATETIME(miano, dec-2010) the datetime widget above returns # aware datetime objects while the current database setup only # supports naive objects. The lines below(and in subsequent actions) # convert them to naive datetimes recurrence_start_date = data["start_date"].replace(tzinfo=None) recurrence_end_date = data["end_date"].replace(tzinfo=None) length = data["event_length"] sitting_length = timedelta(seconds=int(length)) # # Check the end date of the recurrence # The end date is set to be the end date of the current group # or one year from the present date whichever is sooner. group = trusted.get_group() # If group is none then there is a big problem assert group is not None year = timedelta(days=365) now = datetime.datetime.now() if ((group.end_date is not None) and ((now + year) < group.end_date)) or (group.end_date is None): end = now + year else: end = group.end_date if recurrence_end_date > end: recurrence_end_date = end dates = utils.generate_recurrence_dates(recurrence_start_date, recurrence_end_date, data["rec_type"]) recurrent_sittings = [] for date in dates: sitting = domain.GroupSitting() sitting.group_id = trusted.group_id sitting.start_date = date sitting.end_date = date + sitting_length sitting.language = data["language"] sitting.venue_id = data["venue"] session.add(sitting) recurrent_sittings.append(sitting) session.commit() for s in recurrent_sittings: notify(ObjectCreatedEvent(s)) self.template_data.append({ "group_sitting_id": s.group_sitting_id, "action": "inserted", "ids": data["ids"] }) self.request.response.setHeader('Content-type', 'text/xml') return self.xml_template() else: sitting = domain.GroupSitting() sitting.start_date = data["start_date"].replace(tzinfo=None) sitting.end_date = data["end_date"].replace(tzinfo=None) sitting.group_id = trusted.group_id sitting.language = data["language"] sitting.venue_id = data["venue"] session.add(sitting) session.commit() notify(ObjectCreatedEvent(sitting)) self.template_data.append({ "group_sitting_id": sitting.group_sitting_id, "action": "inserted", "ids": data["ids"] }) self.request.response.setHeader('Content-type', 'text/xml') return self.xml_template() def update_sitting_failure_handler(self, action, data, errors): error_string = u"" for error in errors: if error.message not in ('', None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" return "%s \n%s" % (error_message, error_string) @form.action(u"update", failure='update_sitting_failure_handler') def handle_update(self, action, data): session = Session() self.template_data = [] sitting = domain.GroupSitting() sitting = session.query(domain.GroupSitting).get(data["ids"]) sitting.start_date = data["start_date"].replace(tzinfo=None) sitting.end_date = data["end_date"].replace(tzinfo=None) if "language" in data.keys(): sitting.language = data["language"] if "venue" in data.keys(): sitting.venue_id = data["venue"] # set extra data needed by template session.update(sitting) notify(ObjectModifiedEvent(sitting)) self.template_data.append({ "group_sitting_id": sitting.group_sitting_id, "action": "inserted", "ids": data["ids"] }) session.commit() self.request.response.setHeader('Content-type', 'text/xml') return self.xml_template() def delete_sitting_failure_handler(self, action, data, errors): error_string = u"" for error in errors: if error.message not in ('', None): error_string += error.message + "\n" else: error_string += error.__str__() + "\n" return "%s \n%s" % (error_message, error_string) @form.action(u"delete", failure='delete_sitting_failure_handler') def handle_delete(self, action, data): session = Session() self.template_data = [] sitting = session.query(domain.GroupSitting).get(data["ids"]) # set extra data needed by template self.template_data = [] if sitting is not None: self.request.response.setHeader('Content-type', 'text/xml') self.template_data.append({ "group_sitting_id": sitting.group_sitting_id, "action": "deleted", "ids": data["ids"] }) session.delete(sitting) session.commit() return self.xml_template()
from zope import interface from zope.viewlet import viewlet, manager from zope.formlib import form from zope.formlib.namedtemplate import NamedTemplate from zope.formlib.namedtemplate import NamedTemplateImplementation from zope.app.pagetemplate import ViewPageTemplateFile from i18n import _ import core import content ContentViewletManagerTemplate = NamedTemplateImplementation( ViewPageTemplateFile('templates/content-manager.pt')) class FormViewlet(form.SubPageForm, viewlet.ViewletBase): __init__ = viewlet.ViewletBase.__init__ class AddFormViewlet(content.AddFormBase, FormViewlet): """ add form viewlet """ __init__ = FormViewlet.__init__ class EditFormViewlet(form.SubPageEditForm, viewlet.ViewletBase): __init__ = viewlet.ViewletBase.__init__ adapters = None
class DhtmlxCalendarSittings(BrowserView): """This view returns xml of the sittings for the week and group requested in a format acceptable by DHTMLX scheduler""" interface.implements(IStructuralView) template = ViewPageTemplateFile('templates/dhtmlxcalendarxml.pt') def __init__(self, context, request): super(DhtmlxCalendarSittings, self).__init__(ISchedulingContext(context), request) self.context.__name__ = self.__name__ interface.alsoProvides(self.context, ILocation) interface.alsoProvides(self.context, IDCDescriptiveProperties) self.__parent__ = context def __call__(self): try: date = self.request.get('from') dateobj = datetime.datetime(*time.strptime(date, "%Y-%m-%d")[0:5]) start_date = utils.datetimedict.fromdate(dateobj) except: start_date = None try: date = self.request.get('to') dateobj = datetime.datetime(*time.strptime(date, "%Y-%m-%d")[0:5]) end_date = utils.datetimedict.fromdate(dateobj) except: end_date = None if start_date is None: start_date = utils.datetimedict.fromdate(datetime.date.today()) days = tuple(start_date + timedelta(days=d) for d in range(7)) end_date = days[-1] elif end_date is None: start_date = utils.datetimedict.fromdate(datetime.date.today()) days = tuple(start_date + timedelta(days=d) for d in range(7)) end_date = days[-1] sittings = self.context.get_sittings( start_date, end_date, ) self.sittings = [] for sitting in sittings.values(): if checkPermission("zope.View", sitting): trusted = removeSecurityProxy(sitting) if trusted.venue: trusted.text = "<![CDATA[" \ "<b>Venue:</b></br>%s</br><b>Status:</b></br>%s" \ "]]>" % (trusted.venue.short_name, trusted.status) else: trusted.text = "<![CDATA[<b>Status:</b></br>%s]]>" % ( trusted.status) # !+PRESENTATION_CODE(mr, mar-2011) should be in templates. self.sittings.append(trusted) self.request.response.setHeader('Content-type', 'text/xml') return self.render() #return super(DhtmlxCalendarSittings, self).__call__() def render(self, template=None): return self.template()
class WorkflowChangeStateView(WorkflowView): """This gets called on selection of a transition from the menu i.e. NOT: a) when clicking on one of the transition buttons in the workflow form. b) when clicking Add of an object (automatic transitions). """ ajax_template = ViewPageTemplateFile("templates/workflow-ajax.pt") def __init__(self, context, request): self.context = context self.request = request zope.interface.alsoProvides(self.request, IConfirmWorkflowChangeLayer) super(WorkflowChangeStateView, self).__init__(context, request) def __call__(self, transition_id=None, headless=False): # parameters coming in via URL querystring or post vars ! method = self.request["REQUEST_METHOD"] # !+ALWAYS_POST(mr, sep-2011) requests coming from link clicks (GETs) # from the bungeni Web UI seem to always be intercepted and switched # into POSTs. workflow = interfaces.IWorkflow(self.context) require_confirmation = True if transition_id is not None: self.update(transition_id) require_confirmation = workflow.get_transition( transition_id).require_confirmation else: self.update() if (IBungeniParliamentaryContent.providedBy(self.context) and get_mask(self.context) == "manual" and not self.context.registry_number): require_confirmation = True if (not require_confirmation and method == "POST"): actions = bindTransitions(self.action_viewlet, (transition_id, ), workflow) assert len(actions) == 1 # execute action # !+ should pass self.request.form as data? e.g. value is: # {u"next_url": u"...", u"transition": u"submit_response"} result = actions[0].success({}) # !+UNUSED(mr, jun-2011) this result is never used! if headless: actions = get_actions("context_workflow", self.context, self.request) state_title = workflow.get_state(self.context.status).title result = self.ajax_template(actions=actions, state_title=state_title) if require_confirmation: self.request.response.setStatus(403) else: self.request.response.setStatus(200) self.request.response.setResult(result) self.request.response.setHeader("Content-Type", "text/xml") return result template = self.template() return template
class ReportView(form.PageForm): main_result_template = ViewPageTemplateFile("templates/main_reports.pt") result_template = ViewPageTemplateFile("templates/reports.pt") display_minutes = None def __init__(self, context, request): super(ReportView, self).__init__(context, request) class IReportForm(interface.Interface): short_name = schema.Choice( title=_(u"Document Type"), description=_(u"Type of report to be produced"), values=[ "Order of the day", "Weekly Business", "Questions of the week" ], required=True) date = schema.Date( title=_(u"Date"), description=_(u"Choose a starting date for this report"), required=True) item_types = schema.List( title=u"Items to include", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.AvailableItems")) bills_options = schema.List( title=u"Bill options", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.BillOptions")) agenda_items_options = schema.List( title=u"Agenda options", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.AgendaOptions")) motions_options = schema.List( title=u"Motion options", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.MotionOptions")) questions_options = schema.List( title=u"Question options", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.QuestionOptions")) tabled_documents_options = schema.List( title=u"Tabled Document options", required=False, value_type=schema.Choice( vocabulary="bungeni.vocabulary.TabledDocumentOptions")) note = schema.TextLine( title=u"Note", required=False, description=u"Optional note regarding this report") template = namedtemplate.NamedTemplate("alchemist.form") form_fields = form.Fields(IReportForm) form_fields["item_types"].custom_widget = horizontalMultiCheckBoxWidget form_fields["bills_options"].custom_widget = verticalMultiCheckBoxWidget form_fields[ "agenda_items_options"].custom_widget = verticalMultiCheckBoxWidget form_fields["motions_options"].custom_widget = verticalMultiCheckBoxWidget form_fields[ "questions_options"].custom_widget = verticalMultiCheckBoxWidget form_fields[ "tabled_documents_options"].custom_widget = verticalMultiCheckBoxWidget form_fields["date"].custom_widget = SelectDateWidget def setUpWidgets(self, ignore_request=False): class context: item_types = "Bills" bills_options = "Title" agenda_items_options = "Title" questions_options = "Title" motions_options = "Title" tabled_documents_options = "Title" note = None date = None short_name = "Order of the day" self.adapters = {self.IReportForm: context} self.widgets = form.setUpEditWidgets(self.form_fields, self.prefix, self.context, self.request, adapters=self.adapters, ignore_request=ignore_request) def update(self): super(ReportView, self).update() forms.common.set_widget_errors(self.widgets, self.errors) def get_end_date(self, start_date, time_span): if time_span is TIME_SPAN.daily: return start_date + timedelta(days=1) elif time_span is TIME_SPAN.weekly: return start_date + timedelta(weeks=1) raise RuntimeError("Unknown time span: %s" % time_span) def time_span(self, data): if "short_name" in data: if data["short_name"] == "Order of the day": return TIME_SPAN.daily elif data["short_name"] == "Proceedings of the day": return TIME_SPAN.daily elif data["short_name"] == "Weekly Business": return TIME_SPAN.weekly elif data["short_name"] == "Questions of the week": return TIME_SPAN.weekly else: return TIME_SPAN.daily def validate(self, action, data): errors = super(ReportView, self).validate(action, data) time_span = self.time_span(data) if IGroupSitting.providedBy(self.context): if not self.context.items: errors.append( interface.Invalid( _(u"The sitting has no scheduled items"))) else: start_date = data["date"] if "date" in data else \ datetime.datetime.today().date() end_date = self.get_end_date(start_date, time_span) try: ctx = ISchedulingContext(self.context) except: errors.append( interface.Invalid( _(u"You are trying to generate a report " "outside scheduling"))) sittings = ctx.get_sittings(start_date, end_date).values() if not sittings: errors.append( interface.Invalid( _(u"The period selected has no sittings"), "date")) parliament = queries.get_parliament_by_date_range( start_date, end_date) if parliament is None: errors.append( interface.Invalid( _(u"A parliament must be active in the period"), "date")) return errors @form.action(_(u"Preview")) def handle_preview(self, action, data): self.process_form(data) self.save_link = url.absoluteURL(self.context, self.request) + "/save-report" self.body_text = self.result_template() return self.main_result_template() def process_form(self, data): class optionsobj(object): """Object that holds all the options.""" self.options = optionsobj() if not hasattr(self, "short_name"): if "short_name" in data: self.short_name = data["short_name"] self.sittings = [] if IGroupSitting.providedBy(self.context): trusted = removeSecurityProxy(self.context) order = "real_order" if self.display_minutes else "planned_order" trusted.item_schedule.sort(key=operator.attrgetter(order)) self.sittings.append(trusted) self.start_date = self.context.start_date self.end_date = self.get_end_date(self.start_date, self.time_span(data)) else: self.start_date = data["date"] if "date" in data else \ datetime.datetime.today().date() self.end_date = self.get_end_date(self.start_date, self.time_span(data)) sittings = ISchedulingContext(self.context).get_sittings( self.start_date, self.end_date).values() self.sittings = map(removeSecurityProxy, sittings) self.ids = "" for s in self.sittings: self.ids += str(s.group_sitting_id) + "," def cleanup(string): return string.lower().replace(" ", "_") for item_type in data["item_types"]: itemtype = cleanup(item_type) setattr(self.options, itemtype, True) for option in data[itemtype + "_options"]: setattr(self.options, cleanup(itemtype + "_" + option), True) if self.display_minutes: self.link = url.absoluteURL(self.context, self.request) \ + "/votes-and-proceedings" else: self.link = url.absoluteURL(self.context, self.request) + "/agenda" try: self.group = self.context.group except: self.group = ISchedulingContext(self.context).get_group()
class BungeniAttributeDisplay(DynamicFields, form.SubPageDisplayForm, browser.BungeniViewlet): """bungeni.subform.manager """ # the instance of the ViewProvideViewletManager #provide = z3evoque.ViewProvideViewletManager( # default_provider_name="bungeni.subform.manager") #render = z3evoque.ViewTemplateFile("form.html#display") render = ViewPageTemplateFile("templates/display-form.pt") mode = "view" form_name = _(u"General") view_id = "display-item" has_data = True adapters = None def get_note(self): """Return Notes if supplied by context. """ context = removeSecurityProxy(self.context) if getattr(context, "note", False): return context.note def setupActions(self): return # !+ ?? wfc = interfaces.IWorkflowController(self.context, None) if wfc is not None: transitions = wfc.getManualTransitionIds() self.actions = tuple( bindTransitions(self, transitions, wfc.workflow)) def setUpWidgets(self, ignore_request=False): languages = get_all_languages() self.form_fields = filterFields(self.context, self.form_fields) #do not display empty form fields omit_names = [] for f in self.form_fields: val = getattr(self.context, f.__name__) if val is None: omit_names.append(f.__name__) self.form_fields = self.form_fields.omit(*omit_names) context = self.context if ITranslatable.providedBy(self.context): lang = self.request.locale.getLocaleID() try: translation = get_translation_for(self.context, lang) except: translation = [] if (not translation and getattr(self.context, "language", None) and getattr(self.context, "language", None) != lang): supported_lang = languages.get(lang) if supported_lang: langname = supported_lang.get("native", None) if langname == None: langname = supported_lang.get("name") self.status = translate( _(u"This content is not yet translated into" +\ " $language", mapping={"language": langname}), domain="bungeni", context=self.request ) context = copy(removeSecurityProxy(self.context)) for field_translation in translation: setattr(context, field_translation.field_name, field_translation.field_text) self.widgets = form.setUpEditWidgets(self.form_fields, "", context, self.request, adapters=self.adapters, for_display=True, ignore_request=ignore_request) def update(self): self.setupActions() #super(BungeniAttributeDisplay, self).update() #super(DynamicFields, self).update() DynamicFields.update(self) self.setupActions() # after we transition we have different actions try: self.wf_status = interfaces.IStateController( removeSecurityProxy(self.context)).get_status() except: pass @property def form_name(self): parent = self.context.__parent__ #DESCRIPTOR(miano, June 2011) This originally first checked the parent's #descriptor then the item's descriptor. Why??? #This was causing an error in the display pages of items in the #workspace since the workspace containers have no descriptor #defined for them. if IAlchemistContent.providedBy(self.context): descriptor = utils.get_descriptor(self.context.__class__) elif IAlchemistContainer.providedBy(parent): descriptor = utils.get_descriptor(parent.domain_model) else: raise RuntimeError("Unsupported object: %s." % repr(self.context)) if descriptor: name = getattr(descriptor, "display_name", None) if name is None: name = self.context.__class__.__name__ return name # !+RENAME get_object_class_name def getObjectClass(self): """Get the context object's class name. Called from the view template. """ return self.context.__class__.__name__ # !+ from ui.forms.common.BaseForm -- merge these 2 base classes? @property def invariantErrors(self): """ () -> [error:zope.interface.Invalid] """ errors = [] for error in self.errors: if isinstance(error, interface.Invalid): errors.append(error) return errors @property def invariantMessages(self): """ () -> [message:str] Called from the form.html#display template. """ return filter(None, [error.message for error in self.invariantErrors])
def _write_body(self): response = self.request.response body = ViewPageTemplateFile('templates/event_vcal.pt')(self) response.setHeader('Content-Type', 'text/vCal') response.setHeader('Content-Disposition', 'filename=cmf.vcs') response.write(body.encode("UTF-8"))