Example #1
0
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
Example #2
0
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
Example #5
0
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')
Example #6
0
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')
Example #8
0
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)
Example #9
0
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)
Example #10
0
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
Example #11
0
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')
Example #12
0
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'))
Example #13
0
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'))
Example #14
0
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'))
Example #15
0
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'))
Example #16
0
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'))
Example #17
0
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')
Example #18
0
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
Example #19
0
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')
Example #21
0
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
Example #22
0
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')
Example #23
0
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')
Example #24
0
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')
Example #25
0
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.')
Example #26
0
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))
Example #27
0
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)
Example #28
0
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)
Example #29
0
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()
Example #30
0
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())