def bindTransitions(form_instance, transitions, wf_name=None, collection=False, wf=None): """ bind workflow transitions into formlib actions """ assert not (collection and wf_name) if collection: success_factory = CollectionTransitionHandler elif wf_name: success_factory = lambda tid: TransitionHandler(tid, wf_name) else: success_factory = TransitionHandler actions = [] for tid in transitions: d = {} if success_factory: d['success'] = success_factory(tid) if wf is not None: action = form.Action(_(unicode(wf.getTransitionById(tid).title))) else: action = form.Action(tid, **d) action.form = form_instance action.__name__ = "%s.%s" % (form_instance.prefix, action.__name__) actions.append(action) return actions
class ContentEditFormBase(_EditFormMixin, PageForm): actions = form.Actions( form.Action( name='change', label=_(u'Change'), validator='handle_validate', success='handle_change_success', failure='handle_failure'), form.Action( name='change_and_view', label=_(u'Change and View'), validator='handle_validate', success='handle_change_and_view_success', failure='handle_failure')) description = u'' def setUpWidgets(self, ignore_request=False): self.adapters = {} self.widgets = form.setUpEditWidgets( self.form_fields, self.prefix, self.context, self.request, adapters=self.adapters, ignore_request=ignore_request ) @property def label(self): obj_type = translate(self.context.Type(), self.context) return _(u'Edit ${obj_type}', mapping={'obj_type': obj_type}) def handle_validate(self, action, data): if self.context.wl_isLocked(): return (_(u'This resource is locked via webDAV.'),) return None def _handle_success(self, action, data): # normalize set and datetime for k, v in data.iteritems(): if isinstance(v, Set): data[k] = set(v) elif isinstance(v, datetime) and v.tzname() is None: data[k] = parseDatetimetz(str(v)) changed = form.applyChanges(self.context, self.form_fields, data, self.adapters) if changed: self.context.reindexObject() obj_type = translate(self.context.Type(), self.context) self.status = _(u'${obj_type} changed.', mapping={'obj_type': obj_type}) else: self.status = _(u'Nothing to change.') return changed def handle_change_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/edit') def handle_change_and_view_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/view')
class Site(SettingsEditFormBase): """Enable or disable syndication for a site.""" form_fields = form.FormFields(ISyndicationInfo).omit('enabled') label = _(u"Configure Portal Syndication") actions = form.Actions( form.Action( name="enable", label=_(u"Enable Syndication"), condition="disabled", success="handle_enable", ), form.Action( name="change", label=_(u"Change"), condition="enabled", success="handle_change", ), form.Action( name="disable", label=_(u"Disable Syndication"), condition="enabled", success="handle_disable" ) ) redirect = ("portal_actions", "global/syndication") @memoize def getContent(self): syndtool = getUtility(ISyndicationTool) return syndtool @memoize def enabled(self, action=None): return self.getContent().enabled @memoize def disabled(self, action=None): return not self.getContent().enabled def handle_enable(self, action, data): self.getContent().enable() self._handle_success(action, data) self.status = _(u"Syndication enabled.") self._setRedirect(*self.redirect) def handle_change(self, action, data): self._handle_success(action, data) self.status = _(u"Syndication settings changed.") self._setRedirect(*self.redirect) def handle_disable(self, action, data): self.getContent().disable() self.status = _(u"Syndication disabled.") self._setRedirect(*self.redirect)
class Discuss(EditFormBase): """ Discuss an item """ form_fields = form.FormFields(IDiscussion) actions = form.Actions( form.Action( name="add", label=_("Add"), condition=1, validator="validate", success="handle_add" ), form.Action( name="edit", label=_("Edit"), condition=1, success="handle_edit", ), form.Action( name="preview", label=_("Preview"), condition=1, success="handle_preview", ) ) redirect = ("portal_actions", "object/view") @property @memoize def dtool(self): return getUtility(IDiscussionTool) @property def is_preview(self): pass def handle_add(self, action, data): """Create comment and redirect to it""" talkback = self.dtool.getDiscussionFor(self.context) replyID = talkback.createReply(title=data['title'], text=data['text']) reply = talkback.getReply(replyID) self.status = _(u"Reply added.") self.context.setRedirect(reply, "object/view") def handle_preview(self, action, data): """Preview comment and allow editing or adding""" pass def handle_edit(self, action, data): """Edit comment before submitting it""" pass
class MetadataEditView(ContentEditFormBase): """Edit view for IMutableDublinCore. """ actions = form.Actions( form.Action( name='change', label=_(u'Change'), validator='handle_validate', success='handle_change_success', failure='handle_failure'), form.Action( name='change_and_edit', label=_(u'Change and Edit'), validator='handle_validate', success='handle_change_and_edit_success', failure='handle_failure'), form.Action( name='change_and_view', label=_(u'Change and View'), validator='handle_validate', success='handle_change_and_view_success', failure='handle_failure')) form_fields = form.FormFields(IMetadataSchema) form_fields['subject'].custom_widget = SubjectInputWidget form_fields['contributors'].custom_widget = TupleInputWidget form_fields['effective'].custom_widget = DatetimeI18nWidget form_fields['expires'].custom_widget = DatetimeI18nWidget label = _(u'Properties') def setUpWidgets(self, ignore_request=False): super(MetadataEditView, self).setUpWidgets(ignore_request=ignore_request) self.widgets['allow_discussion']._messageNoValue = _(u'Default') self.widgets['description'].height = 4 self.widgets['subject'].split = True self.widgets['contributors'].height = 6 self.widgets['contributors'].split = True self.widgets['created'].split = True self.widgets['modified'].split = True self.widgets['effective'].split = True self.widgets['expires'].split = True def handle_change_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/metadata') def handle_change_and_edit_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/edit')
class SettingsEditFormBase(_EditFormMixin, form.PageForm): """Base class for editing global settings. """ actions = form.Actions( form.Action(name='change', label=_(u'Change'), success='handle_change_success', failure='handle_failure'), form.Action(name='cancel', label=_(u'Cancel'), validator='handle_cancel_validate', success='handle_cancel_success')) description = u'' successMessage = _(u"Settings changed.") noChangesMessage = _(u'Nothing to change.') def getContent(self): return self.context def setUpWidgets(self, ignore_request=False): self.adapters = {} self.widgets = form.setUpEditWidgets(self.form_fields, self.prefix, self.getContent(), self.request, adapters=self.adapters, ignore_request=ignore_request) def applyChanges(self, data): return form.applyData(self.getContent(), self.form_fields, data, self.adapters) def _handle_success(self, action, data): # normalize set and datetime for k, v in data.iteritems(): if isinstance(v, Set): data[k] = set(v) elif isinstance(v, datetime) and v.tzinfo: # DatetimeWidget returns offset-aware datetime objects data[k] = v.replace(tzinfo=None) changes = self.applyChanges(data) if changes: self.status = self.successMessage else: self.status = self.noChangesMessage return changes
class Submit(EditFormBase): """Submit an item for review""" template = ViewPageTemplateFile("submit.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="submit", label=_(u"Submit item"), success='handle_workflow', failure='handle_failure')) @property @memoize def workflow(self): return getUtility(IWorkflowTool) def handle_workflow(self, action, data): try: self.workflow.doActionFor(self.context, action.name, comment=data['comment']) self.status = STATUS.get(action.name, _(u"Status changed.")) self._setRedirect('portal_types', 'object/view') except WorkflowException, errmsg: self.status = errmsg self._setRedirect('portal_actions', 'object/edit')
def _makeEditAction(label, status, text): """Make an Action to call a particular code import method. :param label: The label for the action, which will end up as the button title. :param status: If the code import has this as its review_status, don't show the button (always show the button if it is None). :param text: The text to go after 'The code import has been' in a notifcation, if a change was made. """ if status is not None: def condition(self, ignored): return self._showButtonForStatus(status) else: condition = None def success(self, action, data): """Make the requested status change.""" if status is not None: data['review_status'] = status event = self.code_import.updateFromData(data, self.user) if event is not None: self.request.response.addNotification( 'The code import has been ' + text + '.') else: self.request.response.addNotification('No changes made.') name = label.lower().replace(' ', '_') return form.Action( label, name=name, success=success, condition=condition)
class Folder(Site): """Enable, disable and customise syndication settings for a folder. """ label = _(u"Configure Folder Syndication") actions = Site.actions actions.append( form.Action( name="revert", label=_(u"Revert to Site Default"), condition="enabled", success="handle_revert", )) redirect = ("portal_actions", "object/syndication") @memoize def getContent(self): return getAdapter(self.context, ISyndicationInfo) @memoize def allowed(self, action=None): return self.getContent().allowed def handle_revert(self, action, data): self.getContent().revert() self.status = _(u"Syndication reset to site default.") self._setRedirect(*self.redirect)
class DisplayViewlet(BungeniAttributeDisplay): """Display a target object; if the object is `None`, the user is prompted to add it. """ mode = "view" for_display = True query = None factory = None has_data = False form_fields = form.Fields() add_action = form.Actions(form.Action(_(u"Add"), success="handle_add"), ) def __init__(self, context, request, view, manager): super(DisplayViewlet, self).__init__(context, request, view, manager) # set add url before we change context self.add_url = self.get_add_url() target = self.get_target() if target is None: self.status = _(u"No item has been set") else: self.context = target self.has_data = True assert self.factory is not None descriptor = queryModelDescriptor(self.factory) self.form_fields = descriptor.fields def update(self): # only if there's data to display do we update using our # immediate superclass if self.has_data: super(DisplayViewlet, self).update() else: self.setupActions() super(form.SubPageDisplayForm, self).update() def handle_add(self, action, data): self.request.response.redirect(self.add_url) def get_add_url(self): raise NotImplementedError("Must be implemented by subclass.") def get_target(self): raise NotImplementedError("Must be implemented by subclass.") def set_target(self, target): raise NotImplementedError("Must be implemented by subclass.") def setupActions(self): if self.has_data: super(DisplayViewlet, self).setupActions() else: self.actions = self.add_action.actions @property def form_name(self): descriptor = queryModelDescriptor(self.factory) return descriptor.display_name
class ContentEditFormBase(SettingsEditFormBase): actions = form.Actions( form.Action(name='change', label=_(u'Change'), validator='handle_validate', success='handle_change_success', failure='handle_failure'), form.Action(name='change_and_view', label=_(u'Change and View'), validator='handle_validate', success='handle_change_and_view_success', failure='handle_failure')) @property def label(self): obj_type = translate(self.context.Type(), self.context) return _(u'Edit ${obj_type}', mapping={'obj_type': obj_type}) @property def successMessage(self): obj_type = translate(self.context.Type(), self.context) return _(u'${obj_type} changed.', mapping={'obj_type': obj_type}) def handle_validate(self, action, data): if self.context.wl_isLocked(): return (_(u'This resource is locked via webDAV.'), ) return self.validate(action, data) def applyChanges(self, data): changes = super(ContentEditFormBase, self).applyChanges(data) # ``changes`` is a dictionary; if empty, there were no changes if changes: self.context.reindexObject() return changes def handle_change_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/edit') def handle_change_and_view_success(self, action, data): self._handle_success(action, data) return self._setRedirect('portal_types', 'object/view')
class Reject(Submit): """Reject an item submitted for publication""" template = ViewPageTemplateFile("reject.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="reject", label=_(u"Reject this item"), success='handle_workflow', failure='handle_failure'))
class Publish(Submit): """Publish an item""" template = ViewPageTemplateFile("publish.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="publish", label=_(u"Publish this item"), success='handle_workflow', failure='handle_failure'))
class Show(Submit): """Reveal a hidden item""" template = ViewPageTemplateFile("show.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="show", label=_(u"Show this item"), success='handle_workflow', failure='handle_failure'))
class Retract(Submit): """Remove a published object""" template = ViewPageTemplateFile("retract.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="retract", label=_(u"Retract this item"), success='handle_workflow', failure='handle_failure'))
class Hide(Submit): """Hide a published item""" template = ViewPageTemplateFile("hide.pt") form_fields = form.FormFields(IWorkflowSchema) actions = form.Actions( form.Action(name="hide", label=_(u"Hide this item"), success='handle_workflow', failure='handle_failure'))
class LoginFormView(EditFormBase): """Form view for ILoginSchema. """ base_template = EditFormBase.template template = ViewPageTemplateFile('login.pt') label = _(u'Log in') prefix = '' form_fields = form.FormFields(ILoginSchema) actions = form.Actions( form.Action(name='login', label=_(u'Login'), validator='handle_login_validate', success='handle_login_success', failure='handle_failure')) def setUpWidgets(self, ignore_request=False): cctool = queryUtility(ICookieCrumbler) if cctool is not None: ac_name_id = cctool.name_cookie ac_password_id = cctool.pw_cookie ac_persistent_id = cctool.persist_cookie else: ac_name_id = '__ac_name' ac_password_id = '__ac_password' ac_persistent_id = '__ac_persistent' ac_name = self.request.get(ac_name_id) if ac_name is not None: self.request.form['name'] = ac_name self.request.form[ac_name_id] = ac_name ac_persistent = self.request.get(ac_persistent_id) if ac_persistent is not None: self.request.form['persistent'] = ac_persistent ac_persistent_used = self.request.get("%s.used" % ac_persistent_id) if ac_persistent_used is not None: self.request.form['persistent.used'] = ac_persistent_used super(LoginFormView, self).setUpWidgets(ignore_request=ignore_request) self.widgets['came_from'].hide = True self.widgets['name'].name = ac_name_id self.widgets['password'].name = ac_password_id self.widgets['persistent'].name = ac_persistent_id def handle_login_validate(self, action, data): mtool = getUtility(IMembershipTool) if mtool.isAnonymousUser(): _expireAuthCookie(self) return (_(u'Login failure'), ) return None def handle_login_success(self, action, data): return self._setRedirect('portal_actions', 'user/logged_in', 'came_from')
def bindTransitions(form_instance, transitions, wf): """Bind workflow transitions into formlib actions. """ actions = [] for tid in transitions: action = form.Action(_(unicode(wf.get_transition(tid).title)), success=TransitionHandler(tid)) action.form = form_instance action.__name__ = "%s.%s" % (form_instance.prefix, action.__name__) actions.append(action) return actions
def bindTransitions(form_instance, transitions, wf_name=None, wf=None): """Bind workflow transitions into formlib actions. """ if wf_name: success_factory = lambda tid: TransitionHandler(tid, wf_name) else: success_factory = TransitionHandler actions = [] for tid in transitions: d = {} if success_factory: d["success"] = success_factory(tid) if wf is not None: title = _(unicode(wf.getTransitionById(tid).title)) action = form.Action(title, **d) else: action = form.Action(tid, **d) action.form = form_instance action.__name__ = "%s.%s" % (form_instance.prefix, action.__name__) actions.append(action) return actions
class MailPasswordFormView(EditFormBase): """Form view for IMailPasswordSchema. """ template = ViewPageTemplateFile('mail_password.pt') label = _(u"Don't panic!") description = _(u"Just enter your member ID below, click 'Send', and " u"your password will be mailed to you if you gave a " u"valid email address when you signed on.") form_fields = form.FormFields(IMailPasswordSchema) form_fields['name'].custom_widget = TextWidget actions = form.Actions( form.Action(name='send', label=_(u'Send'), success='handle_send_success', failure='handle_failure')) def setUpWidgets(self, ignore_request=False): cctool = queryUtility(ICookieCrumbler) if cctool is not None: ac_name_id = cctool.name_cookie else: ac_name_id = '__ac_name' ac_name = self.request.get(ac_name_id) if ac_name and not ('%s.name' % self.prefix) in self.request: self.request.form['%s.name' % self.prefix] = ac_name super(MailPasswordFormView, self).setUpWidgets(ignore_request=ignore_request) def handle_send_success(self, action, data): mtool = getUtility(IMembershipTool) if not mtool.getMemberById(data['name']): candidates = mtool.searchMembers('email', data['name']) for candidate in candidates: if candidate['email'].lower() == data['name'].lower(): data['name'] = candidate['username'] break rtool = getUtility(IRegistrationTool) rtool.mailPassword(data['name'], self.request) self.status = _(u'Your password has been mailed to you.') return self._setRedirect('portal_actions', 'user/login') @property @memoize def admin_email(self): ptool = getUtility(IPropertiesTool) return ptool.getProperty('email_from_address')
class ResponseViewlet(BungeniAttributeDisplay): """Response to question.""" mode = "view" for_display = True form_name = _(u"Response") add_action = form.Actions( form.Action(_(u'Add response'), success='handle_response_add_action'), ) def __init__(self, context, request, view, manager): self.context = context self.request = request self.__parent__ = view self.manager = manager self.query = None md = queryModelDescriptor(domain.Response) self.form_fields = md.fields self.add_url = '%s/responses/add' % url.absoluteURL( self.context, self.request) def handle_response_add_action(self, action, data): self.request.response.redirect(self.add_url) def update(self): context = self.context responses = context.responses if len(responses): self.context = tuple(responses.values())[0] self.has_data = True else: self.context = domain.Response() self.has_data = False super(ResponseViewlet, self).update() def setupActions(self): if self.has_data: super(ResponseViewlet, self).setupActions() else: self.actions = self.add_action.actions
class Search(EditFormBase): """Portal Search Form""" template = ViewPageTemplateFile('search.pt') actions = form.Actions( form.Action( name='search', label=_(u"Search"), success='handle_search', failure='handle_failure', ), ) @property def label(self): return _(u'Search ${portal_title}', mapping={'portal_title': self.title()}) @property def form_fields(self): form_fields = form.FormFields(ISearchSchema) form_fields['review_state'].custom_widget = ChoiceMultiSelectWidget form_fields['Subject'].custom_widget = ChoiceMultiSelectWidget form_fields['portal_type'].custom_widget = ChoiceMultiSelectWidget if not self._checkPermission(ReviewPortalContent): form_fields = form_fields.omit('review_state') return form_fields def handle_search(self, action, data): if 'form.created' in self.request.form: del self.request.form['form.created'] if 'created' in data and data['created']: created = record() created.query = DateTime(str(data['created'])) created.range = 'min' self.request.form['form.created'] = created return self._setRedirect('portal_actions', 'global/search', 'review_state,SearchableText,Title,Subject,' 'Description,created,portal_type,' 'listCreators')
class TimeLineViewlet( viewlet.ViewletBase ): """ tracker/timeline view: Chronological changes are aggregated from : bill workflow, bill audit, bill scheduling and bill event records. """ sql_timeline = "" add_action = form.Actions( form.Action(_(u'add event'), success='handle_event_add_action'), ) for_display = True view_name = "Timeline" view_id ="unknown-timeline" # sqlalchemy give me a rough time sorting a union, with hand coded sql it is much easier. def __init__( self, context, request, view, manager ): self.context = context self.request = request self.__parent__= view self.manager = manager self.query = None def handle_event_add_action( self, action, data ): self.request.response.redirect(self.addurl) def update(self): """ refresh the query """ item_id = self.context.parliamentary_item_id self.results = queries.execute_sql( self.sql_timeline, item_id=item_id) path = ui_url.absoluteURL(self.context, self.request) self.addurl = '%s/event/add' %( path ) render = ViewPageTemplateFile ('templates/timeline_viewlet.pt')
class PortalConfig(EditFormBase): form_fields = form.FormFields(IPortalConfig) form_fields['validate_email'].custom_widget = ChoiceRadioWidget actions = form.Actions( form.Action( name='change', label=_(u'Change'), success='handle_success', failure='handle_failure'), ) template = ViewPageTemplateFile("config.pt") def setUpWidgets(self, ignore_request=False): data = {} ptool = getUtility(IPropertiesTool) charset = ptool.getProperty('default_charset', None) for name in getFieldNames(IPortalConfig): value = ptool.getProperty(name) try: value = value.decode(charset) except (AttributeError, UnicodeEncodeError): pass data[name] = value data['smtp_server'] = ptool.smtp_server() self.widgets = form.setUpDataWidgets( self.form_fields, self.prefix, self.context, self.request, data=data, ignore_request=ignore_request) def handle_success(self, action, data): ptool = getUtility(IPropertiesTool) ptool.editProperties(data) self.status = _(u"Portal settings changed.") self._setRedirect('portal_actions', 'global/configPortal')
class ContentsView(BatchViewBase, _EditFormMixin, form.PageForm): """Folder contents view""" template = ViewPageTemplateFile('folder_contents.pt') prefix = 'form' object_actions = form.Actions( form.Action(name='rename', label=_(u'Rename'), validator='validate_items', condition='has_subobjects', success='handle_rename', failure='handle_failure'), form.Action(name='cut', label=_(u'Cut'), condition='has_subobjects', validator='validate_items', success='handle_cut', failure='handle_failure'), form.Action(name='copy', label=_(u'Copy'), condition='has_subobjects', validator='validate_items', success='handle_copy', failure='handle_failure'), form.Action(name='paste', label=_(u'Paste'), condition='check_clipboard_data', success='handle_paste'), form.Action(name='delete', label=_(u'Delete'), condition='has_subobjects', validator='validate_items', success='handle_delete', failure='handle_failure')) delta_actions = form.Actions( form.Action(name='up', label=_(u'Up'), condition='is_orderable', validator='validate_items', success='handle_up', failure='handle_failure'), form.Action(name='down', label=_(u'Down'), condition='is_orderable', validator='validate_items', success='handle_down', failure='handle_failure')) absolute_actions = form.Actions( form.Action(name='top', label=_(u'Top'), condition='is_orderable', validator='validate_items', success='handle_top', failure='handle_failure'), form.Action(name='bottom', label=_(u'Bottom'), condition='is_orderable', validator='validate_items', success='handle_bottom', failure='handle_failure')) sort_actions = form.Actions( form.Action(name='sort_order', label=_(u'Set as Default Sort'), condition='can_sort_be_changed', validator='validate_items', success='handle_top', failure='handle_failure')) actions = object_actions + delta_actions + absolute_actions + sort_actions errors = () def __init__(self, *args, **kw): super(ContentsView, self).__init__(*args, **kw) self.form_fields = form.FormFields() self.delta_field = form.FormFields(IDeltaItem) self.contents = self.context.contentValues() def content_fields(self): """Create content field objects only for batched items""" f = IFolderItem['select'] contents = [] b_start = self._getBatchStart() key, reverse = self._get_sorting() fields = form.FormFields() for idx, item in enumerate(self._getBatchObj()): field = form.FormField(f, 'select', item.id) fields += form.FormFields(field) content = ContentProxy(item) if key == 'position': content.position = b_start + idx + 1 else: content.position = '...' contents.append(content) self.listBatchItems = contents return fields @memoize @decode def up_info(self): """Link to the contens view of the parent object""" up_obj = self.context.aq_inner.aq_parent mtool = getUtility(IMembershipTool) allowed = mtool.checkPermission(ListFolderContents, up_obj) if allowed: if IDynamicType.providedBy(up_obj): up_url = up_obj.getActionInfo('object/folderContents')['url'] return { 'icon': '%s/UpFolder_icon.gif' % self._getPortalURL(), 'id': up_obj.getId(), 'url': up_url } else: return {'icon': '', 'id': 'Root', 'url': ''} else: return {} def setUpWidgets(self, ignore_request=False): """Create widgets for the folder contents.""" super(ContentsView, self).setUpWidgets(ignore_request) self.widgets = form.setUpWidgets(self.content_fields(), self.prefix, self.context, self.request, ignore_request=ignore_request) self.widgets += form.setUpWidgets(self.delta_field, self.prefix, self.context, self.request, ignore_request=ignore_request) @memoize def _get_sorting(self): """How should the contents be sorted""" data = self._getHiddenVars() key = data.get('sort_key') if key: return (key, data.get('reverse', 0)) else: return self.context.getDefaultSorting() @memoize def _is_default_sorting(self, ): return self._get_sorting() == self.context.getDefaultSorting() @memoize def column_headings(self): key, reverse = self._get_sorting() columns = ({ 'sort_key': 'Type', 'title': _(u'Type'), 'colspan': '2' }, { 'sort_key': 'getId', 'title': _(u'Name') }, { 'sort_key': 'modified', 'title': _(u'Last Modified') }, { 'sort_key': 'position', 'title': _(u'Position') }) for column in columns: paras = {'form.sort_key': column['sort_key']} if key == column['sort_key'] \ and not reverse and key != 'position': paras['form.reverse'] = 1 query = urllib.urlencode(paras) column['url'] = '%s?%s' % (self._getViewURL(), query) return tuple(columns) @memoize def _get_items(self): key, reverse = self._get_sorting() items = self.contents return sort(items, ((key, 'cmp', reverse and 'desc' or 'asc'), )) def _get_ids(self, data): """Identify objects that have been selected""" ids = [ k[:-7] for k, v in data.items() if v is True and k.endswith('.select') ] return ids #Action conditions @memoize def has_subobjects(self, action=None): """Return false if the user cannot rename subobjects""" return bool(self.contents) @memoize def check_clipboard_data(self, action=None): """Any data in the clipboard""" return bool(self.context.cb_dataValid()) @memoize def can_sort_be_changed(self, action=None): """Returns true if the default sort key may be changed may be sorted for display""" items_move_allowed = self._checkPermission(ManageProperties) return items_move_allowed and not \ self._get_sorting() == self.context.getDefaultSorting() @memoize def is_orderable(self, action=None): """Returns true if the displayed contents can be reorded.""" (key, reverse) = self._get_sorting() return key == 'position' and len(self.contents) > 1 #Action validators def validate_items(self, action=None, data=None): """Check whether any items have been selected for the requested action.""" super(ContentsView, self).validate(action, data) if self._get_ids(data) == []: return [_(u"Please select one or more items first.")] else: return [] #Action handlers def handle_rename(self, action, data): """Redirect to rename view passing the ids of objects to be renamed""" # currently redirects to a PythonScript # should be replaced with a dedicated form self.request.form['ids'] = self._get_ids(data) keys = ",".join(self._getHiddenVars().keys() + ['ids']) # keys = 'b_start, ids, key, reverse' return self._setRedirect('portal_types', 'object/rename_items', keys) def handle_cut(self, action, data): """Cut the selected objects and put them in the clipboard""" ids = self._get_ids(data) try: self.context.manage_cutObjects(ids, self.request) if len(ids) == 1: self.status = _(u'Item cut.') else: self.status = _(u'Items cut.') except CopyError: self.status = _(u'CopyError: Cut failed.') except zExceptions_Unauthorized: self.status = _(u'Unauthorized: Cut failed.') return self._setRedirect('portal_types', 'object/folderContents') def handle_copy(self, action, data): """Copy the selected objects to the clipboard""" ids = self._get_ids(data) try: self.context.manage_copyObjects(ids, self.request) if len(ids) == 1: self.status = _(u'Item copied.') else: self.status = _(u'Items copied.') except CopyError: self.status = _(u'CopyError: Copy failed.') return self._setRedirect('portal_types', 'object/folderContents') def handle_paste(self, action, data): """Paste the objects from the clipboard into the folder""" try: result = self.context.manage_pasteObjects(self.request['__cp']) if len(result) == 1: self.status = _(u'Item pasted.') else: self.status = _(u'Items pasted.') except CopyError, error: self.status = _(u'CopyError: Paste failed.') self.request['RESPONSE'].expireCookie( '__cp', path='%s' % (self.request['BASEPATH1'] or "/")) except zExceptions_Unauthorized: self.status = _(u'Unauthorized: Paste failed.')
class ContentAddFormBase(_EditFormMixin, form.PageAddForm): adapts(IFolderish, ICMFDefaultSkin, ITypeInformation) implementsOnly(IPageForm) security = ClassSecurityInfo() security.declareObjectPrivate() actions = form.Actions( form.Action(name='add', label=form._('Add'), condition=form.haveInputWidgets, success='handle_add', failure='handle_failure'), form.Action(name='cancel', label=_(u'Cancel'), validator='handle_cancel_validate', success='handle_cancel_success')) def __init__(self, context, request, ti): self.context = context self.request = request self.ti = ti security.declareProtected(AddPortalContent, '__call__') def __call__(self): container = self.context portal_type = self.ti.getId() # check allowed (sometimes redundant, but better safe than sorry) if not self.ti.isConstructionAllowed(container): raise AccessControl_Unauthorized('Cannot create %s' % portal_type) # check container constraints ttool = getUtility(ITypesTool) container_ti = ttool.getTypeInfo(container) if container_ti is not None and \ not container_ti.allowType(portal_type): raise ValueError('Disallowed subobject type: %s' % portal_type) return super(ContentAddFormBase, self).__call__() @property def label(self): obj_type = translate(self.ti.Title(), self.context) return _(u'Add ${obj_type}', mapping={'obj_type': obj_type}) @property def description(self): return self.ti.Description() #same as in form.AddFormBase but without action decorator def handle_add(self, action, data): self.createAndAdd(data) def handle_cancel_success(self, action, data): return self._setRedirect('portal_types', ('object/folderContents', 'object/view')) def create(self, data): id = data.pop('id', '') or '' factory = getUtility(IFactory, self.ti.factory) obj = factory(id=id, **data) obj._setPortalTypeName(self.ti.getId()) return obj def add(self, obj): container = self.context name = INameChooser(container).chooseName(obj.getId(), obj) obj.id = name container._setObject(name, obj) obj = container._getOb(name) obj_type = translate(obj.Type(), container) self.status = _(u'${obj_type} added.', mapping={'obj_type': obj_type}) self._finished_add = True self._added_obj = obj return obj def nextURL(self): obj = self._added_obj message = translate(self.status, self.context) if isinstance(message, unicode): message = message.encode(self._getBrowserCharset()) return '%s/%s?%s' % (obj.absolute_url(), self.ti.immediate_view, make_query(portal_status_message=message))
class TimeLineViewlet(browser.BungeniItemsViewlet): """ tracker/timeline view: Chronological changes are aggregated from : bill workflow, bill audit, bill scheduling and bill event records. """ # evoque render = z3evoque.ViewTemplateFile("viewlets.html#timeline") # zpt #render = ViewPageTemplateFile("templates/timeline_viewlet.pt") # sqlalchemy give me a rough time sorting a union, # with hand coded sql it is much easier. # !+ get rid of the hard-coded sql sql_timeline = "" add_action = form.Actions( form.Action(_(u"add event"), success="handle_event_add_action"), ) view_title = _("Timeline") view_id = "unknown-timeline" changes_getter = { "atype": lambda item: item.action, "adate": lambda item: item.date_active, "description": format_change_description, "notes": lambda item: "", } events_getter = { "atype": lambda item: "event", "adate": lambda item: item.event_date, "description": lambda item: "<a href='%s'>%s</a>" \ %(url.absoluteURL(item, common.get_request()), item.short_name), "notes": lambda item: "", } def __init__(self, context, request, view, manager): super(TimeLineViewlet, self).__init__(context, request, view, manager) self.formatter = self.get_date_formatter("dateTime", "medium") def handle_event_add_action(self, action, data): self.request.response.redirect(self.addurl) def update(self): self.items = itertools.chain(*[ load_formatted_container_items(self.context.changes, self.changes_getter), load_formatted_container_items(self.context.event, self.events_getter) ]) self.items = sorted(self.items, key=lambda item: item["adate"], reverse=True) def update_sql(self): """Refresh the query. """ #!+_TIMELINE(mb, aug-2011) to deprecate this function and use # sub-container listings as shown above to acess timeline items # evaluate serialization of a dict, failure returns an empty dict def _eval_as_dict(s): try: d = eval(s) assert isinstance(d, dict) return d except (SyntaxError, TypeError, AssertionError): #debug.log_exc(sys.exc_info(), log_handler=log.info) return {} # !+CHANGE_EXTRAS(mr, dec-2010) # only *Change records have an extras dict (as "notes" str attr) and the # content of this depends on the value of "atype" (see core/audit.py) item_id = self.context.parliamentary_item_id self.items = [ dict(atype=action, item_id=piid, description=desc, adate=date, notes=_eval_as_dict(notes)) for action, piid, desc, date, notes in queries.execute_sql(self.sql_timeline, item_id=item_id) ] # Filter out workflow draft items for anonymous users if get_principal_id() in ("zope.anybody", ): _draft_states = ("draft", "working_draft") def show_timeline_item(item): if item["atype"] == "workflow": if item["notes"].get("destination") in _draft_states: return False return True self.items = [ item for item in self.items if show_timeline_item(item) ] #change_cls = getattr(domain, "%sChange" % (self.context.__class__.__name__)) for r in self.items: # workflow if r["atype"] == "workflow": # description # the workflow transition change log stores the (unlocalized) # human title for the transition's destination workflow state # -- here we just localize what is supplied: r["description"] = _(r["description"]) # NOTE: we could elaborate an entirely custom description # from scratch e.g via interpolation of a template string: ''' if r["notes"].get("destination", ""): description = "%s %s" % ( _("some text"), _(misc.get_wf_state( self.context, r["notes"]["destination"]))) ''' # event elif r["atype"] == "event": # description r["description"] = """<a href="event/obj-%s">%s</a>""" % ( r["item_id"], _(r["description"])) # version elif r["atype"] == "version": # description try: r["description"] = """<a href="versions/obj-%s">%s</a>""" % ( r["notes"]["version_id"], _(r["description"])) except (KeyError, ): # no recorded version_id, just localize what is supplied r["description"] = _(r["description"]) # path = url.absoluteURL(self.context, self.request) self.addurl = "%s/event/add" % (path)
class TimeLineViewlet(viewlet.ViewletBase): """ tracker/timeline view: Chronological changes are aggregated from : bill workflow, bill audit, bill scheduling and bill event records. """ # evoque render = z3evoque.ViewTemplateFile("workspace_viewlets.html#timeline") # zpt #render = ViewPageTemplateFile('templates/timeline_viewlet.pt') # sqlalchemy give me a rough time sorting a union, # with hand coded sql it is much easier. # !+ get rid of the hard-coded sql sql_timeline = "" add_action = form.Actions( form.Action(_(u'add event'), success='handle_event_add_action'), ) for_display = True view_name = "Timeline" view_id = "unknown-timeline" def __init__(self, context, request, view, manager): self.context = context self.request = request self.__parent__ = view self.manager = manager self.query = None self.formatter = date.getLocaleFormatter(self.request, "dateTime", "medium") def handle_event_add_action(self, action, data): self.request.response.redirect(self.addurl) def update(self): """Refresh the query. """ # evaluate serialization of a dict, failure returns an empty dict def _eval_as_dict(s): try: d = eval(s) assert isinstance(d, dict) return d except (SyntaxError, TypeError, AssertionError): #debug.log_exc(sys.exc_info(), log_handler=log.info) return {} # NOTE: only *Change records have a "notes" dict attribute and the # content of this depends on the value of "atype" (see core/audit.py) item_id = self.context.parliamentary_item_id self.results = [ dict(atype=action, item_id=piid, description=desc, adate=date, notes=_eval_as_dict(notes)) for action, piid, desc, date, notes in queries.execute_sql(self.sql_timeline, item_id=item_id) ] # Filter out workflow draft items for anonymous users if get_principal_id() in ("zope.anybody", ): _draft_states = ("draft", "working_draft") def show_timeline_item(result): if result["atype"] == "workflow": if result["notes"].get("destination") in _draft_states: return False return True self.results = [ result for result in self.results if show_timeline_item(result) ] #change_cls = getattr(domain, "%sChange" % (self.context.__class__.__name__)) for r in self.results: # workflow if r["atype"] == "workflow": # description # the workflow transition change log stores the (unlocalized) # human title for the transition's destination workflow state # -- here we just localize what is supplied: r["description"] = _(r["description"]) # NOTE: we could elaborate an entirely custom description # from scratch e.g via interpolation of a template string: ''' if r["notes"].get("destination", ""): description = "%s %s" % ( _("some text"), _(misc.get_wf_state( self.context, r["notes"]["destination"]))) ''' # event elif r["atype"] == "event": # description r["description"] = """<a href="event/obj-%s">%s</a>""" % ( r["item_id"], _(r["description"])) # version elif r["atype"] == "version": # description try: r["description"] = """<a href="versions/obj-%s">%s</a>""" % ( r["notes"]["version_id"], _(r["description"])) except (KeyError, ): # no recorded version_id, just localize what is supplied r["description"] = _(r["description"]) # path = url.absoluteURL(self.context, self.request) self.addurl = '%s/event/add' % (path)
class ContentsView(BatchFormMixin, EditFormBase): """Folder contents view""" template = ViewPageTemplateFile('folder_contents.pt') rename_template = ViewPageTemplateFile('folder_rename.pt') object_actions = form.Actions( form.Action( name='select_for_rename', label=_(u'Rename...'), validator='validate_items', condition='show_select_for_rename', success='handle_select_for_rename_success', failure='handle_failure'), form.Action( name='cut', label=_(u'Cut'), condition='show_basic', validator='validate_items', success='handle_cut_success', failure='handle_failure'), form.Action( name='copy', label=_(u'Copy'), condition='show_basic', validator='validate_items', success='handle_copy_success', failure='handle_failure'), form.Action( name='paste', label=_(u'Paste'), condition='show_paste', success='handle_paste_success', failure='handle_failure'), form.Action( name='delete', label=_(u'Delete'), condition='show_delete', validator='validate_items', success='handle_delete_success', failure='handle_failure') ) delta_actions = form.Actions( form.Action( name='up', label=_(u'Up'), condition='is_orderable', validator='validate_items', success='handle_up_success', failure='handle_failure'), form.Action( name='down', label=_(u'Down'), condition='is_orderable', validator='validate_items', success='handle_down_success', failure='handle_failure') ) absolute_actions = form.Actions( form.Action( name='top', label=_(u'Top'), condition='is_orderable', validator='validate_items', success='handle_top_success', failure='handle_failure'), form.Action( name='bottom', label=_(u'Bottom'), condition='is_orderable', validator='validate_items', success='handle_bottom_success', failure='handle_failure') ) sort_actions = form.Actions( form.Action( name='sort_order', label=_(u'Set as Default Sort'), condition='can_sort_be_changed', success='handle_sort_order_success', failure='handle_failure') ) rename_actions = form.Actions( form.Action( name='rename', label=_(u'Rename'), validator='validate_items', success='handle_rename_success', failure='handle_rename_failure'), form.Action( name='cancel', label=_(u'Cancel'), validator='handle_cancel_validate', success='handle_cancel_success')) actions = (object_actions + delta_actions + absolute_actions + sort_actions + rename_actions) form_fields = form.FormFields() delta_field = form.FormFields(IDeltaItem) description = u'' @property def label(self): return _(u'Folder Contents: ${obj_title}', mapping={'obj_title': self.title()}) @memoize def listBatchItems(self): """List batched items. """ show_checkboxes = self._checkPermission(ViewManagementScreens) contents = [] b_start = self._getBatchStart() key, _reverse = self._get_sorting() for idx, item in enumerate(self._getBatchObj()): content = ContentProxy(item) content.checkbox = show_checkboxes if key == 'position': content.position = b_start + idx + 1 else: content.position = '...' contents.append(content) return tuple(contents) @memoize def listSelectedItems(self): ids = self._get_ids() contents = [] for item in self._getBatchObj(): if not item.getId() in ids: continue if not item.cb_isMoveable(): continue contents.append(ContentProxy(item)) return tuple(contents) @memoize @decode def up_info(self): """Link to the contens view of the parent object""" up_obj = aq_parent(aq_inner(self.context)) mtool = getUtility(IMembershipTool) allowed = mtool.checkPermission(ListFolderContents, up_obj) if allowed: if IDynamicType.providedBy(up_obj): up_url = up_obj.getActionInfo('object/folderContents')['url'] return {'icon': '%s/UpFolder_icon.gif' % self._getPortalURL(), 'id': up_obj.getId(), 'url': up_url} else: return {'icon': '', 'id': 'Root', 'url': ''} else: return {} def setUpWidgets(self, ignore_request=False): """Create widgets for the folder contents.""" super(ContentsView, self).setUpWidgets(ignore_request) self.widgets = form.setUpWidgets( self.delta_field, self.prefix, self.context, self.request, ignore_request=ignore_request) @memoize def _get_sorting(self): """How should the contents be sorted""" data = self._getNavigationVars() key = data.get('sort_key') if key: return (key, data.get('reverse', 0)) else: return self.context.getDefaultSorting() @memoize def column_headings(self): key, reverse = self._get_sorting() columns = ({'sort_key': 'Type', 'title': _(u'Type'), 'class': 'contents_type_col', 'colspan': '2'}, {'sort_key': 'getId', 'title': _(u'Name'), 'class': 'contents_name_col'}, {'sort_key': 'modified', 'title': _(u'Last Modified'), 'class': 'contents_modified_col'}, {'sort_key': 'position', 'title': _(u'Position'), 'class': 'contents_position_col'}) for column in columns: paras = {'form.sort_key': column['sort_key']} if key == column['sort_key'] \ and not reverse and key != 'position': paras['form.reverse'] = 1 query = urllib.urlencode(paras) column['url'] = '%s?%s' % (self._getViewURL(), query) return tuple(columns) @memoize def _get_items(self): key, reverse = self._get_sorting() items = self.context.contentValues() return sort(items, ((key, 'cmp', reverse and 'desc' or 'asc'),)) @memoize def _get_ids(self): """Identify objects that have been selected""" ids = self.request.form.get('{0}.select_ids'.format(self.prefix), []) if isinstance(ids, basestring): ids = [ids] return [ str(id) for id in ids ] @memoize def _get_new_ids(self): ids = self.request.form.get('{0}.new_ids'.format(self.prefix), []) if isinstance(ids, basestring): ids = [ids] return [ str(id) for id in ids ] #Action conditions @memoize def show_basic(self, action=None): if not self._checkPermission(ViewManagementScreens): return False return bool(self._get_items()) @memoize def show_delete(self, action=None): if not self.show_basic(): return False return self._checkPermission(DeleteObjects) @memoize def show_paste(self, action=None): """Any data in the clipboard""" if not self._checkPermission(ViewManagementScreens): return False if not self._checkPermission(AddPortalContent): return False return bool(self.context.cb_dataValid()) @memoize def show_select_for_rename(self, action=None): if not self.show_basic(): return False if not self._checkPermission(AddPortalContent): return False return self.context.allowedContentTypes() @memoize def can_sort_be_changed(self, action=None): """Returns true if the default sort key may be changed may be sorted for display""" if not self._checkPermission(ViewManagementScreens): return False if not self._checkPermission(ManageProperties): return False return not self._get_sorting() == self.context.getDefaultSorting() @memoize def is_orderable(self, action=None): """Returns true if the displayed contents can be reorded.""" if not self._checkPermission(ViewManagementScreens): return False if not self._checkPermission(ManageProperties): return False key, _reverse = self._get_sorting() return key == 'position' and len(self._get_items()) > 1 #Action validators def validate_items(self, action=None, data=None): """Check whether any items have been selected for the requested action.""" errors = self.validate(action, data) if errors: return errors if self._get_ids() == []: errors.append(_(u"Please select one or more items first.")) return errors #Action handlers def handle_select_for_rename_success(self, action, data): """Redirect to rename template. """ return self.rename_template() def handle_cut_success(self, action, data): """Cut the selected objects and put them in the clipboard""" ids = self._get_ids() try: self.context.manage_cutObjects(ids, self.request) if len(ids) == 1: self.status = _(u'Item cut.') else: self.status = _(u'Items cut.') except CopyError: self.status = _(u'CopyError: Cut failed.') return self.handle_failure(action, data, ()) except zExceptions_Unauthorized: return self.handle_failure(action, data, ()) self.status = _(u'Unauthorized: Cut failed.') return self._setRedirect('portal_types', 'object/folderContents') def handle_copy_success(self, action, data): """Copy the selected objects to the clipboard""" ids = self._get_ids() try: self.context.manage_copyObjects(ids, self.request) if len(ids) == 1: self.status = _(u'Item copied.') else: self.status = _(u'Items copied.') except CopyError: self.status = _(u'CopyError: Copy failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_paste_success(self, action, data): """Paste the objects from the clipboard into the folder""" try: result = self.context.manage_pasteObjects(self.request['__cp']) if len(result) == 1: self.status = _(u'Item pasted.') else: self.status = _(u'Items pasted.') except CopyError: self.request.response.expireCookie('__cp', path='%s' % (self.request['BASEPATH1'] or "/")) self.status = _(u'CopyError: Paste failed.') except ValueError: self.status = _(u'ValueError: Paste failed.') return self.handle_failure(action, data, ()) except zExceptions_Unauthorized: self.status = _(u'Unauthorized: Paste failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_delete_success(self, action, data): """Delete the selected objects""" ids = self._get_ids() self.context.manage_delObjects(list(ids)) if len(ids) == 1: self.status = _(u'Item deleted.') else: self.status = _(u'Items deleted.') return self._setRedirect('portal_types', 'object/folderContents') def handle_up_success(self, action, data): """Move the selected objects up the selected number of places""" ids = self._get_ids() delta = data.get('delta', 1) subset_ids = [obj.getId() for obj in self.context.listFolderContents()] try: attempt = self.context.moveObjectsUp(ids, delta, subset_ids=subset_ids) if attempt == 1: self.status = _(u'Item moved up.') elif attempt > 1: self.status = _(u'Items moved up.') else: self.status = self.noChangesMessage except ValueError: self.status = _(u'ValueError: Move failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_down_success(self, action, data): """Move the selected objects down the selected number of places""" ids = self._get_ids() delta = data.get('delta', 1) subset_ids = [obj.getId() for obj in self.context.listFolderContents()] try: attempt = self.context.moveObjectsDown(ids, delta, subset_ids=subset_ids) if attempt == 1: self.status = _(u'Item moved down.') elif attempt > 1: self.status = _(u'Items moved down.') else: self.status = self.noChangesMessage except ValueError: self.status = _(u'ValueError: Move failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_top_success(self, action, data): """Move the selected objects to the top of the page""" ids = self._get_ids() subset_ids = [obj.getId() for obj in self.context.listFolderContents()] try: attempt = self.context.moveObjectsToTop(ids, subset_ids=subset_ids) if attempt == 1: self.status = _(u'Item moved to top.') elif attempt > 1: self.status = _(u'Items moved to top.') else: self.status = self.noChangesMessage except ValueError: self.status = _(u'ValueError: Move failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_bottom_success(self, action, data): """Move the selected objects to the bottom of the page""" ids = self._get_ids() subset_ids = [obj.getId() for obj in self.context.listFolderContents()] try: attempt = self.context.moveObjectsToBottom(ids, subset_ids=subset_ids) if attempt == 1: self.status = _(u'Item moved to bottom.') elif attempt > 1: self.status = _(u'Items moved to bottom.') else: self.status = self.noChangesMessage except ValueError: self.status = _(u'ValueError: Move failed.') return self.handle_failure(action, data, ()) return self._setRedirect('portal_types', 'object/folderContents') def handle_sort_order_success(self, action, data): """Set the sort options for the folder.""" self.context.setDefaultSorting(*self._get_sorting()) self.status = _(u'Default sort order changed.') return self._setRedirect('portal_types', 'object/folderContents') def handle_rename_success(self, action, data): """Rename objects in a folder. """ ids = self._get_ids() new_ids = self._get_new_ids() if not ids == new_ids: try: self.context.manage_renameObjects(ids, new_ids) if len(ids) == 1: self.status = _(u'Item renamed.') else: self.status = _(u'Items renamed.') except CopyError: self.status = _(u'CopyError: Rename failed.') return self.handle_rename_failure(action, data, ()) else: self.status = self.noChangesMessage return self._setRedirect('portal_types', 'object/folderContents', '{0}.b_start, {0}.sort_key, {0}.reverse'.format(self.prefix)) def handle_cancel_success(self, action, data): return self._setRedirect('portal_types', 'object/folderContents', '{0}.b_start, {0}.sort_key, {0}.reverse'.format(self.prefix)) def handle_rename_failure(self, action, data, errors): super(ContentsView, self).handle_failure(action, data, errors) return self.rename_template()
class Search(BatchFormMixin, EditFormBase): """Portal Search Form""" template = ViewPageTemplateFile("search.pt") results = ViewPageTemplateFile("results.pt") hidden_fields = form.FormFields(IBatchForm) form_fields = form.FormFields(ISearchSchema) form_fields['review_state'].custom_widget = ChoiceMultiSelectWidget form_fields['Subject'].custom_widget = ChoiceMultiSelectWidget form_fields['portal_type'].custom_widget = ChoiceMultiSelectWidget search = form.Actions( form.Action( name='search', label=_(u"Search"), success='handle_search', failure='handle_failure', ), ) # for handling searches from the search box image = form.Actions( form.Action( name='search.x', label=_(u"Search"), success='handle_search', failure='handle_failure', ), form.Action( name='search.y', label=_(u"Search"), success='handle_search', failure='handle_failure', ), ) actions = search + image @property @memoize def catalog(self): return getUtility(ICatalogTool) @property @memoize def is_anonymous(self): mtool = getUtility(IMembershipTool) return mtool.isAnonymousUser() @memoize def _getNavigationVars(self): data = {} if hasattr(self, 'hidden_widgets'): form.getWidgetsData(self.hidden_widgets, self.prefix, data) if hasattr(self, '_query'): data.update(self._query) else: data = self.request.form return data @property @memoize def search_fields(self): if self.is_anonymous: return self.form_fields.omit('review_state') else: return self.form_fields def setUpWidgets(self, ignore_request=False): if "form.b_start" in self.request.form \ or "b_start" in self.request.form: self.template = self.results super(Search, self).setUpWidgets(ignore_request) self.widgets = form.setUpWidgets(self.search_fields, self.prefix, self.context, self.request, ignore_request=ignore_request) def handle_search(self, action, data): for k, v in data.items(): if k in ('review_state', 'Title', 'Subject', 'Description', 'portal_type', 'listCreators', 'SearchableText'): if not v or v == u"None": del data[k] elif k == 'created' and v == EPOCH: del data[k] self._query = data self.template = self.results @memoize def _get_items(self): return self.catalog.searchResults(self._query) @memoize def listBatchItems(self): return ({ 'description': item.Description, 'icon': item.getIconURL, 'title': item.Title, 'type': item.Type, 'date': item.Date, 'url': item.getURL(), 'format': None } for item in self._getBatchObj())