예제 #1
0
    def __call__(self, milestone=None):
        context = aq_inner(self.context)
        self.can_edit = api.user.has_permission(
            'Modify portal content', obj=context)
        modified, errors = dexterity_update(context)
        self.workspace = parent_workspace(context)

        if self.workspace.is_case:
            if self.can_edit and milestone is not None \
               and milestone != context.milestone:
                context.milestone = milestone
                modified = True

        if modified:
            api.portal.show_message(
                _("Your changes have been saved."),
                request=self.request,
                type="success",
            )
            context.reindexObject()
            notify(ObjectModifiedEvent(context))

        if errors:
            api.portal.show_message(
                _("There was an error."), request=self.request, type="error")

        return super(TodoView, self).__call__()
예제 #2
0
    def __call__(self):
        """Display a list of Todo items in the Open workflow state, grouped by
        Workspace and ordered by Due date.
        {'workspace1': {'title': 'WS1', 'url': '...', 'tasks':[<brain>, ...]}}
        """
        pc = api.portal.get_tool('portal_catalog')
        me = api.user.get_current().getId()
        form = self.request.form

        if self.request.method == 'POST' and form:
            return update_task_status(self, return_status_message=True)

        tasks = pc(portal_type='todo',
                   review_state='open',
                   assignee=me,
                   sort_on='due')
        self.grouped_tasks = {}
        for task in tasks:
            obj = task.getObject()
            workspace = parent_workspace(obj)
            if workspace.id not in self.grouped_tasks:
                self.grouped_tasks[workspace.id] = {
                    'title': workspace.title,
                    'url': workspace.absolute_url(),
                    'tasks': [task],
                }
            else:
                self.grouped_tasks[workspace.id]['tasks'].append(task)
        return self.render()
예제 #3
0
    def __call__(self, title=None, description=None, tags=[]):
        """Render the default template and evaluate the form when editing."""
        context = aq_inner(self.context)
        self.workspace = parent_workspace(context)
        self.can_edit = api.user.has_permission(
            'Modify portal content',
            obj=context)
        if self.can_edit and title or description or tags:
            modified = False
            if title and safe_unicode(title) != context.title:
                context.title = safe_unicode(title)
                modified = True
            if description:
                if safe_unicode(description) != context.description:
                    context.description = safe_unicode(description)
                    modified = True
            if tags:
                tags = tuple([safe_unicode(tag) for tag in tags.split(',')])
                if tags != context.subject:
                    context.subject = tags
                    modified = True
            if modified:
                context.reindexObject()
                notify(ObjectModifiedEvent(context))

        return super(ContentView, self).__call__()
예제 #4
0
    def reopen(self):
        """
        This only applies to Todo items in Case Workspaces.

        Set the workflow state to "open" if the milestone of the Todo item is
        the same as the current, or earlier workflow state of the Case
        Workspace, otherwise set to "planned".

        Only Open items will appear in the dashboard.
        """
        todo_state = api.content.get_state(self)
        workspace = parent_workspace(self)
        if not ICase.providedBy(workspace):
            if todo_state != 'open':
                api.content.transition(self, 'set_to_open')
        else:
            milestone = self.milestone
            if milestone:
                case_state = api.content.get_state(workspace)
                mm = IMetroMap(workspace).metromap_sequence.keys()
                # A case could be set to a state which isn't included in the
                # metromap e.g. on-hold, rejected. If that happens we can treat
                # it as a future state and set all open tasks to planned
                mm_states = case_state in mm and milestone in mm
                future = (not mm_states
                          or mm.index(milestone) > mm.index(case_state))
                current_or_past = not future
                if current_or_past and todo_state != 'open':
                    api.content.transition(self, 'set_to_open')
                if future and todo_state != 'planned':
                    api.content.transition(self, 'set_to_planned')
            elif todo_state != 'planned':
                api.content.transition(self, 'set_to_planned')
예제 #5
0
    def reopen(self):
        """
        This only applies to Todo items in Case Workspaces.

        Set the workflow state to "open" if the milestone of the Todo item is
        the same as the current, or earlier workflow state of the Case
        Workspace, otherwise set to "planned".

        Only Open items will appear in the dashboard.
        """
        wft = api.portal.get_tool("portal_workflow")
        todo_state = wft.getInfoFor(self, "review_state")
        workspace = parent_workspace(self)
        if not ICase.providedBy(workspace):
            if todo_state != 'open':
                api.content.transition(self, 'set_to_open')
        else:
            milestone = self.milestone
            if milestone:
                case_state = wft.getInfoFor(workspace, 'review_state')
                mm = IMetroMap(workspace).metromap_sequence.keys()
                future = mm.index(milestone) > mm.index(case_state)
                current_or_past = not future
                if current_or_past and todo_state != 'open':
                    api.content.transition(self, 'set_to_open')
                if future and todo_state != 'planned':
                    api.content.transition(self, 'set_to_planned')
            elif todo_state != 'planned':
                api.content.transition(self, 'set_to_planned')
예제 #6
0
    def __call__(self, milestone=None):
        context = aq_inner(self.context)
        self.can_edit = api.user.has_permission('Modify portal content',
                                                obj=context)
        modified, errors = dexterity_update(context)
        self.workspace = parent_workspace(context)

        if self.workspace.is_case:
            if self.can_edit and milestone is not None \
               and milestone != context.milestone:
                context.milestone = milestone
                modified = True

        if modified:
            api.portal.show_message(
                _("Your changes have been saved."),
                request=self.request,
                type="success",
            )
            context.reindexObject()
            notify(ObjectModifiedEvent(context))

        if errors:
            api.portal.show_message(_("There was an error."),
                                    request=self.request,
                                    type="error")

        return super(TodoView, self).__call__()
예제 #7
0
    def reopen(self):
        """
        This only applies to Todo items in Case Workspaces.

        Set the workflow state to "open" if the milestone of the Todo item is
        the same as the current, or earlier workflow state of the Case
        Workspace, otherwise set to "planned".

        Only Open items will appear in the dashboard.
        """
        wft = api.portal.get_tool("portal_workflow")
        state = wft.getInfoFor(self, "review_state")
        workspace = parent_workspace(self)
        if not ICase.providedBy(workspace):
            if state != "open":
                api.content.transition(self, "set_to_open")
        else:
            milestone = self.milestone
            if milestone:
                workspace_state = wft.getInfoFor(workspace, "review_state")
                mm_seq = IMetroMap(workspace).metromap_sequence.keys()
                if mm_seq.index(milestone) > mm_seq.index(workspace_state):
                    if state != "planned":
                        api.content.transition(self, "set_to_planned")
                elif state != "open":
                    api.content.transition(self, "set_to_open")
            elif state != "planned":
                api.content.transition(self, "set_to_planned")
예제 #8
0
    def __call__(self):
        """Display a list of Todo items in the Open workflow state, grouped by
        Workspace and ordered by Due date.
        {'workspace1': {'title': 'WS1', 'url': '...', 'tasks':[<brain>, ...]}}
        """
        pc = api.portal.get_tool("portal_catalog")
        me = api.user.get_current().getId()
        form = self.request.form

        if self.request.method == "POST" and form:
            return update_task_status(self, return_status_message=True)

        tasks = pc(portal_type="todo", review_state=["open", "planned"], assignee=me, sort_on="due")
        self.grouped_tasks = {}
        for task in tasks:
            obj = task.getObject()
            workspace = parent_workspace(obj)
            if workspace.id not in self.grouped_tasks:
                self.grouped_tasks[workspace.id] = {
                    "title": workspace.title,
                    "url": workspace.absolute_url(),
                    "tasks": [task],
                }
            else:
                self.grouped_tasks[workspace.id]["tasks"].append(task)
        return self.render()
예제 #9
0
 def get_item_milestone_hr(self, item):
     ''' Given an item, try to get the milestone in a human readable form
     '''
     milestone = getattr(item, 'milestone', None)
     if not milestone:
         return ''
     ws = parent_workspace(item)
     return self.get_milestone_hr(ws, milestone)
예제 #10
0
 def safe_get_workspace(self):
     """ This will safely return a sane element, either a workspace, or
     app or portal object to call helper methods on
     """
     portal = api.portal.get()
     return parent_workspace(self.context) or \
         parent_app(self.context) or \
         portal
예제 #11
0
    def form_data_pat_redactor(self):
        ''' Return the options for pat-redactor in the format:

        key1: value1; key2: value2; ...
        '''
        workspace = parent_workspace(self.context)
        options = '; '.join(': '.join(option)
                            for option in self._pat_redactor_options)
        return options.format(workspace_url=workspace.absolute_url())
예제 #12
0
 def tasks_by_workspace(self):
     ''' Return the tasks inside workspaces grouped by workspace
     '''
     tasks = self.tasks
     tasks_by_workspace = defaultdict(list)
     for task in tasks:
         workspace = parent_workspace(task)
         tasks_by_workspace[workspace].append(task)
     return tasks_by_workspace
예제 #13
0
    def __call__(self, title=None, description=None, tags=[], text=None):
        """Render the default template and evaluate the form when editing."""
        context = aq_inner(self.context)
        self.workspace = parent_workspace(context)
        self.can_edit = api.user.has_permission('Modify portal content',
                                                obj=context)
        # When saving, force to POST
        if self.request.method == 'POST':
            self.update()

        return super(ContentView, self).__call__()
    def __call__(self, title=None, description=None, tags=[], text=None):
        """Render the default template and evaluate the form when editing."""
        context = aq_inner(self.context)
        self.workspace = parent_workspace(context)
        self.can_edit = api.user.has_permission(
            'Modify portal content',
            obj=context
        )
        # When saving, force to POST
        if self.request.method == 'POST':
            self.update()

        return super(ContentView, self).__call__()
예제 #15
0
def _update_workspace_groupings(obj, event):
    """ If the relevant object is inside a workspace, the workspace grouping
        parameters (for the sidebar) need to be updated.
    """
    parent = parent_workspace(obj)
    if parent is None or not IGroupingStoragable.providedBy(parent):
        return

    storage = getAdapter(parent, IGroupingStorage)
    if IObjectRemovedEvent.providedBy(event) or IObjectWillBeRemovedEvent.providedBy(event):
        storage.remove_from_groupings(obj)
    else:
        storage.update_groupings(obj)
예제 #16
0
def _update_workspace_groupings(obj, event):
    """ If the relevant object is inside a workspace, the workspace grouping
        parameters (for the sidebar) need to be updated.
    """
    parent = parent_workspace(obj)
    if parent is None or not IGroupingStoragable.providedBy(parent):
        return

    storage = getAdapter(parent, IGroupingStorage)
    if IObjectRemovedEvent.providedBy(event) or \
            IObjectWillBeRemovedEvent.providedBy(event):
        storage.remove_from_groupings(obj)
    else:
        storage.update_groupings(obj)
    def events(self):
        catalog = api.portal.get_tool("portal_catalog")
        workspace = parent_workspace(self.context)
        workspace_path = '/'.join(workspace.getPhysicalPath())
        now = DateTime()

        # Current and future events
        upcoming_events = catalog.searchResults(
            object_provides=IEvent.__identifier__,
            path=workspace_path,
            start={'query': (now), 'range': 'min'},
        )

        # Events which have finished
        older_events = catalog.searchResults(
            object_provides=IEvent.__identifier__,
            path=workspace_path,
            end={'query': (now), 'range': 'max'},
        )
        return {"upcoming": upcoming_events, "older": older_events}
예제 #18
0
    def __call__(self):
        workspace = parent_workspace(self.context)
        wft = api.portal.get_tool('portal_workflow')
        case_milestone = wft.getInfoFor(workspace, 'review_state')

        catalog = api.portal.get_tool('portal_catalog')
        workspace_path = '/'.join(workspace.getPhysicalPath())
        open_tasks = catalog(
            path=workspace_path,
            portal_type='todo',
            review_state='open',
        )
        # Only prevent the current milestone from being closed if there are
        # open tasks assigned to the current milestone.
        # This ignores open tasks assigned to earlier milestones since they
        # aren't represented in the metromap.
        for task in open_tasks:
            if task.getObject().milestone == case_milestone:
                return False
        return True
예제 #19
0
def update_todo_state(obj, event):
    """
    After editing a Todo item, set the workflow state to either Open or Planned
    depending on the state of the Case.
    Also update access permissions on the Case, which might have changed due to
    a change in assignment.

    """
    # Do nothing on copy
    if IObjectCopiedEvent.providedBy(event):
        return

    if IObjectAddedEvent.providedBy(event):
        # This attribute is set when copying from a template
        # handle_case_workflow_state_changed will take care of everything
        if getattr(event.newParent, '_v_skip_update_todo_state', None):
            return
    obj.set_appropriate_state()
    obj.reindexObject()
    parent = parent_workspace(obj)
    if ICase.providedBy(parent):
        parent.update_case_access()
예제 #20
0
    def get_key_maker(self):
        ''' Return a function that will generate a key
        according to the selected browsing mode
        The key can be the parent workspace, an attribute value,
        the review state or whatever.

        As a fallback we return a function that returns None.
        '''
        browse_mode = self.browse_mode
        if browse_mode in ('origin', 'assigned', 'initiated'):
            return parent_workspace
        if browse_mode == 'origin_and_milestone':
            return lambda task: (parent_workspace(task), task.milestone)
        if browse_mode == 'task_state':
            return api.content.get_state
        if browse_mode in (
            'assignee',
            'initiator',
            'priority',
        ):
            return lambda task: getattr(task, browse_mode, None)
        return lambda task: None
예제 #21
0
 def __call__(self):
     """Display a list of Todo items in the Open workflow state, grouped by
     Workspace and ordered by Due date.
     {'workspace1': {'title': 'WS1', 'url': '...', 'tasks':[<brain>, ...]}}
     """
     pc = api.portal.get_tool('portal_catalog')
     me = api.user.get_current().getId()
     tasks = pc(portal_type='todo',
                review_state='open',
                assignee=me,
                sort_on='due')
     self.grouped_tasks = {}
     for task in tasks:
         obj = task.getObject()
         workspace = parent_workspace(obj)
         if workspace.id not in self.grouped_tasks:
             self.grouped_tasks[workspace.id] = {
                 'title': workspace.title,
                 'url': workspace.absolute_url(),
                 'tasks': [task],
             }
         else:
             self.grouped_tasks[workspace.id]['tasks'].append(task)
     return self.render()
예제 #22
0
 def workspace(self):
     ''' Return the parent workspace (if there is any)
     '''
     return parent_workspace(self.context)
예제 #23
0
 def parent_workspace(self):
     ''' Return the parent workspace
     '''
     return parent_workspace(self.context)
예제 #24
0
 def workspace(self):
     """Acquire the root workspace of the current context"""
     return parent_workspace(self.context)
예제 #25
0
 def destination(self):
     ''' Get the parent workspace
     '''
     return parent_workspace(self.context)
 def my_workspace(self):
     return parent_workspace(self)
예제 #27
0
 def workspace(self):
     """Acquire the root workspace of the current context"""
     return parent_workspace(self.context)
예제 #28
0
 def redirect(self, url):
     workspace = parent_workspace(self.context)
     return self.request.response.redirect(workspace.absolute_url() +
                                           '#workspace-events')
예제 #29
0
 def workspace(self):
     return parent_workspace(self.context)
예제 #30
0
 def redirect(self, url):
     workspace = parent_workspace(self.context)
     return self.request.response.redirect(workspace.absolute_url() +
                                           '#workspace-events')