class TaskTemplateFoldersTab(BaseCatalogListingTab): """Tab for listing all task template folders on the template folder. """ columns = ( { 'column': '', 'column_title': '', 'transform': helper.path_checkbox, 'sortable': False, 'groupable': False, 'width': 30 }, { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title'), 'sort_index': 'sortable_title', 'transform': linked }, { 'column': 'review_state', 'column_title': _(u'label_review_state', default=u'Review state'), 'transform': translated_string() }, ) types = [ 'opengever.tasktemplates.tasktemplatefolder', ] enabled_actions = ['folder_delete_confirmation'] major_actions = []
class ISelectTaskTemplateFolder(model.Schema): tasktemplatefolder = schema.Choice( title=_('label_tasktemplatefolder', default=u'Tasktemplatefolder'), source='opengever.tasktemplates.active_tasktemplatefolders', required=True ) related_documents = RelationList( title=_(u'label_related_documents', default=u'Related documents'), default=[], missing_value=[], value_type=RelationChoice( title=u"Related", source=DossierPathSourceBinder( portal_type=("opengever.document.document", "ftw.mail.mail"), navigation_tree_query={ 'object_provides': ['opengever.dossier.behaviors.dossier.IDossierMarker', 'opengever.document.document.IDocumentSchema', 'opengever.task.task.ITask', 'ftw.mail.mail.IMail', ], }), ), required=False, )
def interactive_users(context): yield ('responsible', translate(_(u'interactive_user_responsible', default=u'Responsible'), context=getRequest())) yield ('current_user', translate(_(u'interactive_user_current_user', default=u'Current user'), context=getRequest()))
def interactive_users(): return { 'responsible': translate(_(u'interactive_user_responsible', default=u'Responsible'), context=getRequest()), 'current_user': translate(_(u'interactive_user_current_user', default=u'Current user'), context=getRequest()) }
class TaskTemplates(OpengeverCatalogListingTab): grok.name('tabbedview_view-tasktemplates') columns = ( { 'column': '', 'column_title': '', 'transform': helper.draggable, 'width': 30 }, { 'column': '', 'column_title': '', 'transform': helper.path_checkbox, 'width': 30 }, { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title'), 'sort_index': 'sortable_title', 'transform': linked }, { 'column': 'task_type', 'column_title': taskmsg(u'label_task_type', 'Task Type'), 'transform': task_type_helper }, { 'column': 'issuer', 'column_title': _(u'label_issuer', 'Issuer'), 'transform': interactive_user_helper }, { 'column': 'responsible', 'column_title': _(u'label_responsible_task', default=u'Responsible'), 'transform': interactive_user_helper }, { 'column': 'deadline', 'column_title': _(u"label_deadline", default=u"Deadline in Days") }, { 'column': 'preselected', 'column_title': _(u"label_preselected", default=u"Preselect"), 'transform': preselected_helper }, ) types = [ 'opengever.tasktemplates.tasktemplate', ] enabled_actions = [] major_actions = []
class ITaskTemplateFolderSchema(model.Schema): """Marker Schema for TaskTemplateFolder""" model.fieldset(u'common', label=_(u'fieldset_common', default=u'Common'), fields=[u'sequence_type']) directives.order_after(sequence_type='IOpenGeverBase.description') sequence_type = schema.Choice( title=_(u'label_sequence_type', default='Type'), vocabulary=sequence_type_vocabulary, required=True, )
class SelectTaskTemplateFolderWizardStep(BaseWizardStepForm, Form): step_name = 'select-tasktemplatefolder' label = _('label_select_tasktemplatefolder', default=u'Select tasktemplatefolder') steps = TRIGGER_TASKTEMPLATE_STEPS fields = Fields(ISelectTaskTemplateFolder) def update(self): # ignore unauthorized checks (they're called by the contenttree widget) if api.user.get_current() == nobody: pass elif not self.has_active_tasktemplates(): api.portal.show_message(_( u'msg_no_active_tasktemplatefolders', default=u'Currently there are no active task template ' 'folders registered.'), self.request, type='error') return self.request.RESPONSE.redirect(self.context.absolute_url()) self.fields['tasktemplatefolder'].widgetFactory[ INPUT_MODE] = radio.RadioFieldWidget return super(SelectTaskTemplateFolderWizardStep, self).update() @buttonAndHandler(_(u'button_continue', default=u'Continue'), name='save') def handle_continue(self, action): data, errors = self.extractData() if errors: return dm = getUtility(IWizardDataStorage) dm.update(get_datamanger_key(self.context), data) return self.request.RESPONSE.redirect('{}/select-tasktemplates'.format( self.context.absolute_url())) @buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def handle_cancel(self, action): dm = getUtility(IWizardDataStorage) dm.drop_data(get_datamanger_key(self.context)) return self.request.RESPONSE.redirect(self.context.absolute_url()) def has_active_tasktemplates(self): return bool( api.content.find( portal_type='opengever.tasktemplates.tasktemplatefolder', review_state='tasktemplatefolder-state-activ'))
def key_value_provider(self): yield ( "interactive_users", translate(_(u"client_interactive_users", default=u"Interactive users"), context=getRequest()), ) for item in super(ResponsibleOrgUnitVocabularyFactory, self).key_value_provider(): yield item
def preselected_helper(item, value): if value is True: return translate( _(u'preselected_yes', default=u'Yes'), context=getSite().REQUEST) else: return ''
def handle_continue(self, action): data, errors = self.extractData() if errors: return tasktemplatefolder = self.get_selected_task_templatefolder() related_documents = self.get_selected_related_documents() start_immediately = get_wizard_data(self.context, 'start_immediately') templates = self.get_selected_tasktemplates() responsibles = {} for template in templates: responsible_client, responsible = self.get_responsible( template, data) responsibles[template.id] = { 'responsible': responsible, 'responsible_client': responsible_client } tasktemplatefolder.trigger(self.context, templates, related_documents, responsibles, start_immediately) api.portal.show_message(_(u'message_tasks_created', default=u'tasks created'), self.request, type="info") return self.request.RESPONSE.redirect('{}#tasks'.format( self.context.absolute_url()))
def key_value_provider(self): yield ('interactive_users', translate(_(u'client_interactive_users', default=u'Interactive users'), context=getRequest())) for e in ClientsVocabularyFactory.key_value_provider(self): yield e
class ISelectTaskTemplates(form.Schema): tasktemplates = schema.List( title=_('label_tasktemplates', default=u'Tasktemplates'), required=True, value_type=schema.Choice( source='opengever.tasktemplates.tasktemplates', ), defaultFactory=get_preselected_tasktemplates)
def key_value_provider(self): yield (INTERACTIVE_USERS, translate(_(u'client_interactive_users', default=u'Interactive users'), context=getRequest())) org_units_vf = super(ResponsibleOrgUnitVocabularyFactory, self) for item in org_units_vf.key_value_provider(): yield item
class ISelectTaskTemplates(model.Schema): tasktemplates = schema.List( title=_('label_tasktemplates', default=u'Tasktemplates'), required=True, value_type=schema.Choice( source='opengever.tasktemplates.tasktemplates', ), missing_value=[]) start_immediately = schema.Bool( title=_(u'label_start_immediately', default=u'Start immediately'), description=_(u'description_start_immediately', default=u'Immediately ' 'open the first task after creation.'), default=True, required=True, )
def key_value_provider(self): yield ('interactive_users', translate(_(u'client_interactive_users', default=u'Interactive users'), context=getRequest())) for item in super(ResponsibleOrgUnitVocabularyFactory, self).key_value_provider(): yield item
def get_items(self): items = super(TaskTemplateFolderByline, self).get_items() items.append( {'class': 'sequence_type', 'label': _('label_sequence_type', default='Type'), 'content': self.sequence_type(), 'replace': False}) return items
def __call__(self): if not self.has_active_tasktemplatefolders(): api.portal.show_message(_(u'msg_no_active_tasktemplatefolders', default=u'Currently there are no active ' 'task template folders registered.'), request=self.request, type='error') return self.request.RESPONSE.redirect(self.context.absolute_url()) return self.template()
def get_items(self): items = super(TaskTemplateFolderByline, self).get_items() items.append({ 'class': 'sequence_type', 'label': _('label_sequence_type', default='Type'), 'content': self.sequence_type(), 'replace': False }) return items
def __call__(self): if not self.has_active_tasktemplatefolders(): api.portal.show_message( _( u"msg_no_active_tasktemplatefolders", default=u"Currently there are no active" "task template folders registered.", ), request=self.request, type="error", ) return self.request.RESPONSE.redirect(self.context.absolute_url()) return self.template()
class TaskTemplateFoldersTab(OpengeverCatalogListingTab): """Tab for listing all task template folders on the template dossier. """ grok.name('tabbedview_view-tasktemplatefolders') columns = ( { 'column': '', 'column_title': '', 'transform': helper.draggable, 'width': 30 }, { 'column': '', 'column_title': '', 'transform': helper.path_checkbox, 'width': 30 }, { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title'), 'sort_index': 'sortable_title', 'transform': linked }, { 'column': 'review_state', 'column_title': _(u'label_review_state', default=u'Review state'), 'transform': translated_string() }, ) types = [ 'opengever.tasktemplates.tasktemplatefolder', ] enabled_actions = [] major_actions = []
def update(self): # ignore unauthorized checks (they're called by the contenttree widget) if api.user.get_current() == nobody: pass elif not self.has_active_tasktemplates(): api.portal.show_message( _(u'msg_no_active_tasktemplatefolders', default=u'Currently there are no active task template ' 'folders registered.'), self.request, type='error') return self.request.RESPONSE.redirect(self.context.absolute_url()) self.fields['tasktemplatefolder'].widgetFactory[INPUT_MODE] = radio.RadioFieldWidget return super(SelectTaskTemplateFolderWizardStep, self).update()
def handle_continue(self, action): data, errors = self.extractData() if errors: return tasktemplatefolder = self.get_selected_task_templatefolder() related_documents = self.get_selected_related_documents() templates = self.get_selected_tasktemplates(data) main_task = self.create_main_task(tasktemplatefolder, templates) self.create_subtasks(main_task, templates, related_documents) api.portal.show_message( _(u'message_tasks_created', default=u'tasks created'), self.request, type="info") return self.request.RESPONSE.redirect( '{}#tasks'.format(self.context.absolute_url()))
def updateWidgets(self): """Change the label of the dynamically generated responsible fields. """ super(SelectResponsiblesWizardStep, self).updateWidgets() if IDeferSecurityCheck.providedBy(self.request): return for name in self.widgets: if not name.endswith('responsible'): continue widget = self.widgets[name] template_id = self.fields[name].prefix template = self.get_selected_task_templatefolder().get(template_id) widget.label = translate(_( 'label_responsible_for_task', default=u'Responsible \xab${template_title}\xbb', mapping={'template_title': template.title}), context=self.request) if template.responsible: widget.value = self.get_responsible_widget_value(template)
def updateWidgets(self): """Change the label of the dynamically generated responsible fields. """ super(SelectResponsiblesWizardStep, self).updateWidgets() if IDeferSecurityCheck.providedBy(self.request): return for name in self.widgets: if not name.endswith('responsible'): continue widget = self.widgets[name] template_id = self.fields[name].prefix template = self.get_selected_task_templatefolder().get(template_id) widget.label = translate( _('label_responsible_for_task', default=u'Responsible \xab${template_title}\xbb', mapping={'template_title': template.title}), context=self.request) if template.responsible: widget.value = self.get_responsible_widget_value(template)
def handle_continue(self, action): data, errors = self.extractData() if errors: return tasktemplatefolder = self.get_selected_task_templatefolder() related_documents = self.get_selected_related_documents() start_immediately = get_wizard_data(self.context, 'start_immediately') templates = self.get_selected_tasktemplates() responsibles = {} for template in templates: responsible_client, responsible = self.get_responsible(template, data) responsibles[template.id] = { 'responsible': responsible, 'responsible_client': responsible_client} tasktemplatefolder.trigger(self.context, templates, related_documents, responsibles, start_immediately) api.portal.show_message( _(u'message_tasks_created', default=u'tasks created'), self.request, type="info") return self.request.RESPONSE.redirect( '{}#tasks'.format(self.context.absolute_url()))
from z3c.relationfield.schema import RelationChoice from z3c.relationfield.schema import RelationList from zope import schema from zope.app.intid.interfaces import IIntIds from zope.component import getAdapter from zope.component import getUtility from zope.event import notify from zope.interface import alsoProvides from zope.interface import provider from zope.lifecycleevent import ObjectCreatedEvent from zope.schema.interfaces import IContextAwareDefaultFactory TRIGGER_TASKTEMPLATE_STEPS = ( ('select-tasktemplatefolder', _(u'label_tasktemplatefolder_selection', default=u'Tasktemplatefolder selection')), ('select-tasktemplate', _(u'label_tasktemplate_selection', default=u'Tasktemplate selection')) ) def get_datamanger_key(dossier): """Return the wizard-storage key used to store the selected data.""" return 'trigger_tasktemplatefolder:{}'.format(Oguid.for_object(dossier).id) def get_wizard_data(context, key): """Return the wizard-storage data with the given key.""" dm = getUtility(IWizardDataStorage)
def create(self, paths=[]): """generate the task templates""" if "abort" in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage( _(u"message_no_templates_selected", default=u"You have not selected any templates"), type="info" ) return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user("current_user"), responsible=self.replace_interactive_user("current_user"), responsible_client=get_current_org_unit().id(), task_type="direct-execution", deadline=date.today() + timedelta(highest_deadline + MAIN_TASK_DEADLINE_DELTA), ) main_task = createContent("opengever.task.task", **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) ogdsservice = ogds_service() # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, "portal_workflow") wft.doActionFor(main_task, "task-transition-open-in-progress") # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user(template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == "interactive_users": responsible_assigned_org_units = ogdsservice.assigned_org_units(data["responsible"]) current_org_unit = get_current_org_unit() if not responsible_assigned_org_units or current_org_unit in responsible_assigned_org_units: data["responsible_client"] = current_org_unit.id() else: data["responsible_client"] = responsible_assigned_org_units[0].id() else: data["responsible_client"] = template.responsible_client task = createContent("opengever.task.task", **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() # add activity record for subtask activity = TaskAddedActivity(task, self.request, self.context) activity.record() # add activity record for the main task activity = TaskAddedActivity(main_task, self.request, self.context) activity.record() IStatusMessage(self.request).addStatusMessage( _(u"message_tasks_created", default=u"tasks created"), type="info" ) return self.request.RESPONSE.redirect("%s#tasks" % self.context.absolute_url())
def interactive_users(context): yield ("responsible", translate(_(u"interactive_user_responsible", default=u"Responsible"), context=getRequest())) yield ( "current_user", translate(_(u"interactive_user_current_user", default=u"Current user"), context=getRequest()), )
def preselected_helper(item, value): if value is True: return translate(_(u"preselected_yes", default=u"Yes"), context=getSite().REQUEST) else: return ""
class ITaskTemplate(form.Schema): form.fieldset( u'common', label=_(u'fieldset_common', default=u'Common'), fields=[ u'title', u'issuer', u'task_type', u'responsible_client', u'responsible', u'deadline', u'text', u'preselected' ], ) title = schema.TextLine( title=_(u"label_title", default=u"Title"), description=_('help_title', default=u""), required=True, ) form.widget(issuer=AutocompleteFieldWidget) issuer = schema.Choice( title=_(u"label_issuer", default=u"Issuer"), description=_('help_issuer', default=u""), vocabulary=u'opengever.tasktemplates.IssuerVocabulary', required=True, ) form.widget(task_type='z3c.form.browser.radio.RadioFieldWidget') task_type = schema.Choice( title=_(u'label_task_type', default=u'Task Type'), description=_('help_task_type', default=u''), required=True, readonly=False, default=None, missing_value=None, source=util.getTaskTypeVocabulary, ) responsible_client = schema.Choice( title=_(u'label_resonsible_client', default=u'Responsible Client'), description=_(u'help_responsible_client', default=u''), vocabulary='opengever.tasktemplates.ResponsibleClientVocabulary', required=True) form.widget(responsible=AutocompleteFieldWidget) responsible = schema.Choice( title=_(u"label_responsible", default="Responsible"), description=_(u"help_responsible", default=""), vocabulary=u'opengever.tasktemplates.ResponsibleVocabulary', required=True, ) deadline = schema.Int( title=_(u"label_deadline", default=u"Deadline in Days"), description=_('help_deadline', default=u""), required=True, ) form.primary('text') text = schema.Text( title=_(u"label_text", default=u"Text"), description=_(u"help_text", default=u""), required=False, ) form.widget(preselected=checkbox.SingleCheckBoxFieldWidget) preselected = schema.Bool( title=_(u'label_preselected', default='Preselect'), description=_(u'help_preselected', default=''), required=False, )
class SelectTaskTemplatesWizardStep(BaseWizardStepForm, Form): step_name = 'select-tasktemplates' label = _('label_select_tasktemplates', default=u'Select tasktemplates') steps = TRIGGER_TASKTEMPLATE_STEPS fields = Fields(ISelectTaskTemplates) def update(self): self.fields['tasktemplates'].widgetFactory[ INPUT_MODE] = checkbox.CheckBoxFieldWidget return super(SelectTaskTemplatesWizardStep, self).update() def get_preselected_tasktemplates(self): templates = api.content.find( context=self.get_selected_task_templatefolder(), portal_type='opengever.tasktemplates.tasktemplate') return [ template.UID for template in templates if template.getObject().preselected ] def get_selected_task_templatefolder(self): uid = get_wizard_data(self.context, 'tasktemplatefolder') return api.content.get(UID=uid) def get_selected_related_documents(self): intids = getUtility(IIntIds) value = get_wizard_data(self.context, 'related_documents') return [RelationValue(intids.getId(obj)) for obj in value] def get_selected_tasktemplates(self, data): catalog = api.portal.get_tool('portal_catalog') return [ brain.getObject() for brain in catalog(UID=data.get('tasktemplates')) ] @buttonAndHandler(_(u'button_trigger', default=u'Trigger'), name='trigger') def handle_continue(self, action): data, errors = self.extractData() if errors: return tasktemplatefolder = self.get_selected_task_templatefolder() related_documents = self.get_selected_related_documents() templates = self.get_selected_tasktemplates(data) main_task = self.create_main_task(tasktemplatefolder, templates) self.create_subtasks(main_task, templates, related_documents) api.portal.show_message(_(u'message_tasks_created', default=u'tasks created'), self.request, type="info") return self.request.RESPONSE.redirect('{}#tasks'.format( self.context.absolute_url())) @buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def handle_cancel(self, action): return self.request.RESPONSE.redirect(self.context.absolute_url()) def create_main_task(self, templatefolder, selected_templates): highest_deadline = max( [template.deadline for template in selected_templates]) deadline_timedelta = api.portal.get_registry_record( 'deadline_timedelta', interface=ITaskSettings) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user('current_user'), responsible=self.replace_interactive_user('current_user'), responsible_client=get_current_org_unit().id(), task_type='direct-execution', deadline=date.today() + timedelta(highest_deadline + deadline_timedelta), ) main_task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) self.mark_as_generated_from_tasktemplate(main_task) # set the main_task in to the in progress state api.content.transition(obj=main_task, transition='task-transition-open-in-progress') return main_task def create_subtasks(self, main_task, selected_templates, related_documents): for template in selected_templates: self.create_subtask(main_task, template, related_documents) def create_subtask(self, main_task, template, related_documents): data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user(template.responsible), task_type=template.task_type, text=template.text, relatedItems=related_documents, deadline=date.today() + timedelta(template.deadline), ) data['responsible_client'] = self.get_responsible_client( template, data['responsible']) task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) self.mark_as_generated_from_tasktemplate(task) task.reindexObject() # add activity record for subtask activity = TaskAddedActivity(task, self.request, self.context) activity.record() def replace_interactive_user(self, principal): """The current systems knows two interactive users: `responsible`: the reponsible of the main dossier. `current_user`: the currently logged in user. """ if principal == 'responsible': finder = getAdapter(self.context, name='parent-dossier-finder') return IDossier(finder.find_dossier()).responsible elif principal == 'current_user': return api.user.get_current().getId() else: return principal def get_responsible_client(self, template, responsible): if template.responsible_client == 'interactive_users': current_org_unit = get_current_org_unit() responsible_org_units = ogds_service().assigned_org_units( responsible) if current_org_unit in responsible_org_units or \ not responsible_org_units: return current_org_unit.id() else: return responsible_org_units[0].id() return template.responsible_client def mark_as_generated_from_tasktemplate(self, task): alsoProvides(task, IFromTasktemplateGenerated)
class AddForm(BrowserView): __call__ = ViewPageTemplateFile("form.pt") steps = { 'templates': { 'columns': ( ('', helper.path_radiobutton), { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title') }, { 'column': 'created', 'column_title': _(u'label_created', default=u'Created'), 'transform': helper.readable_date }, ), 'types': ('TaskTemplateFolder', ), 'states': ('tasktemplatefolder-state-activ', ), }, 'tasks': { 'columns': ( ('', path_checkbox), { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title') }, { 'column': 'created', 'column_title': _(u'label_created', default=u'Created'), 'transform': helper.readable_date }, ), 'types': ('TaskTemplate', ), 'states': ('tasktemplate-state-active', ), } } def listing(self, show='templates', path='/'): """returns a listing of either TaskTemplateFolders or TaskTemplates""" sort_on = self.request.get('sort', 'getObjPositionInParent') sort_on = {'Title': 'sortable_title'}.get(sort_on, sort_on) sort_order = self.request.get('dir', 'ASC') sort_order = { 'ASC': 'asc', 'DESC': 'reverse' }.get(sort_order, sort_order) templates = self.context.portal_catalog( Type=self.steps[show]['types'], review_state=self.steps[show]['states'], sort_on=sort_on, sort_order=sort_order, path=path) table_options = {'auto_expand_column': 'Title'} generator = queryUtility(ITableGenerator, 'ftw.tablegenerator') return generator.generate(templates, self.steps[show]['columns'], sortable=True, selected=(sort_on, sort_order), options=table_options, output='json') def load_request_parameters(self): """Load parameters such as page or filter from request. """ # pagenumber self.batching_current_page = int(self.request.get('pagenumber', 1)) # XXX eliminate self.pagenumber self.pagenumber = self.batching_current_page # pagesize self.batching_pagesize = self.pagesize # set url self.url = self.context.absolute_url() # filtering if 'searchable_text' in self.request: self.filter_text = self.request.get('searchable_text') # ordering self.sort_on = self.request.get('sort', self.sort_on) if self.sort_on.startswith('header-'): self.sort_on = self.sort_on.split('header-')[1] # reverse default_sort_order = self.sort_reverse and 'reverse' or 'asc' sort_order = self.request.get('dir', default_sort_order) self.sort_order = { 'ASC': 'asc', 'DESC': 'reverse' }.get(sort_order, sort_order) self.sort_reverse = self.sort_order == 'reverse' def create(self, paths=[]): """generate the task templates""" if 'abort' in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage(_( u'message_no_templates_selected', default=u'You have not selected any templates'), type="info") return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user('current_user'), responsible=self.replace_interactive_user('current_user'), responsible_client=get_client_id(), task_type='direct-execution', deadline=date.today() + timedelta(highest_deadline + MAIN_TASK_DEADLINE_DELTA), ) main_task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, 'portal_workflow') wft.doActionFor(main_task, 'task-transition-open-in-progress') # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user( template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == 'interactive_users': info = getUtility(IContactInformation) responsible_assigned_clients = tuple( info.get_assigned_clients(data['responsible'])) current_client = get_current_client() if not responsible_assigned_clients or \ current_client in responsible_assigned_clients: data['responsible_client'] = current_client.client_id else: data['responsible_client'] = \ responsible_assigned_clients[0].client_id else: data['responsible_client'] = template.responsible_client task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() IStatusMessage(self.request).addStatusMessage(_( u'message_tasks_created', default=u'tasks created'), type="info") return self.request.RESPONSE.redirect('%s#tasks' % self.context.absolute_url()) def replace_interactive_user(self, principal): """Replaces interactive users in the principal. """ if principal == 'responsible': # find the dossier dossier = self.context while not IDossierMarker.providedBy(dossier): if IPloneSiteRoot.providedBy(dossier): raise ValueError('Could not find dossier') dossier = aq_parent(aq_inner(dossier)) # get the responsible of the dossier wrapped_dossier = IDossier(dossier) return wrapped_dossier.responsible elif principal == 'current_user': # get the current user mtool = getToolByName(self.context, 'portal_membership') member = mtool.getAuthenticatedMember() if not member: raise Unauthorized() return member.getId() else: return principal def javascript_url(self): """Returns the URL to the javascript file (form.js) for embedding in the template. It also adds the date / time as parameter when portal_javscript is in debug mode. """ url = getToolByName(self.context, 'portal_url')() url += '/++resource++tasktemplates.form.js' # debug mode on? jstool = getToolByName(self.context, 'portal_javascripts') if jstool.getDebugMode(): url += '?now=' + str(datetime.now()) return url
class TaskTemplates(BaseCatalogListingTab): columns = ( { 'column': '', 'column_title': '', 'transform': helper.draggable, 'sortable': False, 'width': 30 }, { 'column': '', 'column_title': '', 'transform': helper.path_checkbox, 'sortable': False, 'groupable': False, 'width': 30 }, { 'column': 'Title', 'column_title': _(u'label_title', default=u'Title'), 'sort_index': 'sortable_title', 'sortable': False, 'transform': linked }, { 'column': 'task_type', 'column_title': taskmsg(u'label_task_type', 'Task Type'), 'sortable': False, 'transform': task_type_helper }, { 'column': 'issuer', 'column_title': _(u'label_issuer', 'Issuer'), 'sortable': False, 'transform': interactive_user_helper }, { 'column': 'responsible', 'column_title': _(u'label_responsible_task', default=u'Responsible'), 'sortable': False, 'transform': interactive_user_helper }, { 'column': 'deadline', 'sortable': False, 'column_title': _(u"label_deadline", default=u"Deadline in Days") }, { 'column': 'preselected', 'column_title': _(u"label_preselected", default=u"Preselect"), 'sortable': False, 'transform': preselected_helper }, ) sort_on = 'draggable' types = [ 'opengever.tasktemplates.tasktemplate', ] enabled_actions = ['folder_delete_confirmation'] major_actions = ['folder_delete_confirmation']
class ITaskTemplate(model.Schema): model.fieldset( u'common', label=_(u'fieldset_common', default=u'Common'), fields=[ u'title', u'issuer', u'task_type', u'responsible_client', u'responsible', u'deadline', u'text', u'preselected' ], ) title = schema.TextLine( title=_(u"label_title", default=u"Title"), description=_('help_title', default=u""), required=True, ) form.widget('issuer', KeywordFieldWidget, async=True) issuer = schema.Choice( title=_(u"label_issuer", default=u"Issuer"), description=_('help_issuer', default=u""), source=TaskTemplateIssuerSourceBinder(), required=True, ) form.widget(task_type='z3c.form.browser.radio.RadioFieldWidget') task_type = schema.Choice( title=_(u'label_task_type', default=u'Task Type'), description=_('help_task_type', default=u''), required=True, readonly=False, default=None, missing_value=None, source=util.getTaskTypeVocabulary, ) form.mode(responsible_client='hidden') responsible_client = schema.Choice( title=_(u'label_resonsible_client', default=u'Responsible Client'), description=_(u'help_responsible_client', default=u''), vocabulary='opengever.tasktemplates.ResponsibleOrgUnitVocabulary', required=True) form.widget('responsible', KeywordFieldWidget, async=True) responsible = schema.Choice( title=_(u"label_responsible", default="Responsible"), description=_(u"help_responsible", default=""), source=TaskResponsibleSourceBinder(include_teams=True), required=True, ) deadline = schema.Int( title=_(u"label_deadline", default=u"Deadline in Days"), description=_('help_deadline', default=u""), required=True, ) model.primary('text') text = schema.Text( title=_(u"label_text", default=u"Text"), description=_(u"help_text", default=u""), required=False, ) form.widget(preselected=checkbox.SingleCheckBoxFieldWidget) preselected = schema.Bool( title=_(u'label_preselected', default='Preselect'), description=_(u'help_preselected', default=''), required=False, )
from opengever.tasktemplates import _ from plone.autoform import directives from plone.supermodel import model from zope import schema from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary sequence_type_vocabulary = SimpleVocabulary([ SimpleTerm(value=u'parallel', title=_(u'Parallel')), SimpleTerm(value=u'sequential', title=_(u'Sequential')) ]) class ITaskTemplateFolderSchema(model.Schema): """Marker Schema for TaskTemplateFolder""" model.fieldset(u'common', label=_(u'fieldset_common', default=u'Common'), fields=[u'sequence_type']) directives.order_after(sequence_type='IOpenGeverBase.description') sequence_type = schema.Choice( title=_(u'label_sequence_type', default='Type'), vocabulary=sequence_type_vocabulary, required=True, )
from z3c.relationfield.relation import RelationValue from z3c.relationfield.schema import RelationChoice from z3c.relationfield.schema import RelationList from zope import schema from zope.app.intid.interfaces import IIntIds from zope.component import getUtility from zope.i18n import translate from zope.interface import provider from zope.schema.interfaces import IContextAwareDefaultFactory import copy import re TRIGGER_TASKTEMPLATE_STEPS = ( ('select-tasktemplatefolder', _(u'label_tasktemplatefolder_selection', default=u'Tasktemplatefolder selection')), ('select-tasktemplate', _(u'label_tasktemplate_selection', default=u'Tasktemplate selection')), ('select-responsibles', _(u'label_responsibles_selection', default=u'Responsibles selection')) ) def get_datamanger_key(dossier): """Return the wizard-storage key used to store the selected data.""" return 'trigger_tasktemplatefolder:{}'.format(Oguid.for_object(dossier).id)
def preselected_helper(item, value): if value is True: return translate(_(u'preselected_yes', default=u'Yes'), context=getSite().REQUEST) else: return ''
class SelectTaskTemplatesWizardStep(BaseWizardStepForm, Form): step_name = 'select-tasktemplates' label = _('label_select_tasktemplates', default=u'Select tasktemplates') steps = TRIGGER_TASKTEMPLATE_STEPS fields = Fields(ISelectTaskTemplates) fields['tasktemplates'].widgetFactory[INPUT_MODE] = checkbox.CheckBoxFieldWidget fields['start_immediately'].widgetFactory[INPUT_MODE] = checkbox.SingleCheckBoxFieldWidget # noqa def updateWidgets(self): super(SelectTaskTemplatesWizardStep, self).updateWidgets() if not self.get_selected_task_templatefolder().is_sequential: self.widgets['start_immediately'].mode = HIDDEN_MODE def updateActions(self): super(SelectTaskTemplatesWizardStep, self).updateActions() self.actions['continue'].addClass("context") def get_preselected_tasktemplates(self): templates = api.content.find( context=self.get_selected_task_templatefolder(), portal_type='opengever.tasktemplates.tasktemplate') return [template.UID for template in templates if template.getObject().preselected] def get_selected_task_templatefolder(self): uid = get_wizard_data(self.context, 'tasktemplatefolder') return api.content.get(UID=uid) def get_selected_related_documents(self): intids = getUtility(IIntIds) value = get_wizard_data(self.context, 'related_documents') return [RelationValue(intids.getId(obj)) for obj in value] @buttonAndHandler(_(u'button_continue', default=u'Continue'), name='continue') def handle_continue(self, action): data, errors = self.extractData() if errors: return dm = getUtility(IWizardDataStorage) dm.update(get_datamanger_key(self.context), data) return self.request.RESPONSE.redirect( '{}/select-responsibles'.format(self.context.absolute_url())) @buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def handle_cancel(self, action): dm = getUtility(IWizardDataStorage) dm.drop_data(get_datamanger_key(self.context)) return self.request.RESPONSE.redirect(self.context.absolute_url()) def get_responsible_client(self, template, responsible): if template.responsible_client == INTERACTIVE_USERS: current_org_unit = get_current_org_unit() responsible_org_units = ogds_service().assigned_org_units(responsible) if current_org_unit in responsible_org_units or \ not responsible_org_units: return current_org_unit.id() else: return responsible_org_units[0].id() return template.responsible_client
from opengever.tasktemplates import _ from plone.autoform import directives from plone.supermodel import model from zope import schema from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary sequence_type_vocabulary = SimpleVocabulary( [SimpleTerm(value=u'parallel', title=_(u'Parallel')), SimpleTerm(value=u'sequential', title=_(u'Sequential'))]) class ITaskTemplateFolderSchema(model.Schema): """Marker Schema for TaskTemplateFolder""" model.fieldset( u'common', label=_(u'fieldset_common', default=u'Common'), fields=[u'sequence_type']) directives.order_after(sequence_type='IOpenGeverBase.description') sequence_type = schema.Choice( title=_(u'label_sequence_type', default='Type'), vocabulary=sequence_type_vocabulary, required=True, )
class SelectResponsiblesWizardStep(BaseWizardStepForm, Form): step_name = 'select-responsibles' label = _('label_select_responsibles', default=u'Select responsibles') steps = TRIGGER_TASKTEMPLATE_STEPS @property def fields(self): """Dynamically generate a responsible field with the Keywordwidget for each selected template. """ # When using the keywordwidget autocomplete search, the widget is # traversing anonymously. Therefore we're not able to get the selected # templates and generate all fields correctly. # Therefore we handle all responsible widget traversals "manually". responsible_field_match = re.match( r'^{}(.*?)\.responsible$'.format(re.escape('++widget++form.widgets.')), self.request._steps[-1]) if IDeferSecurityCheck.providedBy(self.request) and responsible_field_match: field = Field(ITaskTemplate['responsible'], prefix=responsible_field_match.group(1),) field.widgetFactory[INPUT_MODE] = ParameterizedWidget( KeywordWidget, async=True) return Fields(field) self.fallback_field = ITaskTemplate['responsible'] fields = [] for template in self.get_selected_tasktemplates(): schema_field = copy.copy(ITaskTemplate['responsible']) field = Field(schema_field, prefix=template.id) field.field.required = True field.widgetFactory[INPUT_MODE] = ParameterizedWidget( KeywordWidget, async=True) fields.append(field) return Fields(*fields) def updateActions(self): super(SelectResponsiblesWizardStep, self).updateActions() self.actions['trigger'].addClass("context") def updateWidgets(self): """Change the label of the dynamically generated responsible fields. """ super(SelectResponsiblesWizardStep, self).updateWidgets() if IDeferSecurityCheck.providedBy(self.request): return for name in self.widgets: if not name.endswith('responsible'): continue widget = self.widgets[name] template_id = self.fields[name].prefix template = self.get_selected_task_templatefolder().get(template_id) widget.label = translate( _('label_responsible_for_task', default=u'Responsible \xab${template_title}\xbb', mapping={'template_title': template.title}), context=self.request) if template.responsible: widget.value = (u'{}:{}'.format( template.responsible_client, template.responsible), ) def get_selected_task_templatefolder(self): uid = get_wizard_data(self.context, 'tasktemplatefolder') return api.content.get(UID=uid) def get_selected_related_documents(self): intids = getUtility(IIntIds) value = get_wizard_data(self.context, 'related_documents') return [RelationValue(intids.getId(obj)) for obj in value] def get_selected_tasktemplates(self): tasktemplates = get_wizard_data(self.context, 'tasktemplates') return [uuidToObject(uid) for uid in tasktemplates] @buttonAndHandler(_(u'button_trigger', default=u'Trigger'), name='trigger') def handle_continue(self, action): data, errors = self.extractData() if errors: return tasktemplatefolder = self.get_selected_task_templatefolder() related_documents = self.get_selected_related_documents() start_immediately = get_wizard_data(self.context, 'start_immediately') templates = self.get_selected_tasktemplates() responsibles = {} for template in templates: responsible_client, responsible = self.get_responsible(template, data) responsibles[template.id] = { 'responsible': responsible, 'responsible_client': responsible_client} tasktemplatefolder.trigger(self.context, templates, related_documents, responsibles, start_immediately) api.portal.show_message( _(u'message_tasks_created', default=u'tasks created'), self.request, type="info") return self.request.RESPONSE.redirect( '{}#tasks'.format(self.context.absolute_url())) @buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def handle_cancel(self, action): dm = getUtility(IWizardDataStorage) dm.drop_data(get_datamanger_key(self.context)) return self.request.RESPONSE.redirect(self.context.absolute_url()) def get_responsible(self, template, data): form_identifier = '{}.responsible'.format(template.id) value = data.get(form_identifier) return value.split(':')
def create(self, paths=[]): """generate the task templates""" if 'abort' in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage(_( u'message_no_templates_selected', default=u'You have not selected any templates'), type="info") return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user('current_user'), responsible=self.replace_interactive_user('current_user'), responsible_client=get_client_id(), task_type='direct-execution', deadline=date.today() + timedelta(highest_deadline + MAIN_TASK_DEADLINE_DELTA), ) main_task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, 'portal_workflow') wft.doActionFor(main_task, 'task-transition-open-in-progress') # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user( template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == 'interactive_users': info = getUtility(IContactInformation) responsible_assigned_clients = tuple( info.get_assigned_clients(data['responsible'])) current_client = get_current_client() if not responsible_assigned_clients or \ current_client in responsible_assigned_clients: data['responsible_client'] = current_client.client_id else: data['responsible_client'] = \ responsible_assigned_clients[0].client_id else: data['responsible_client'] = template.responsible_client task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() IStatusMessage(self.request).addStatusMessage(_( u'message_tasks_created', default=u'tasks created'), type="info") return self.request.RESPONSE.redirect('%s#tasks' % self.context.absolute_url())
def create(self, paths=[]): """generate the task templates""" if 'abort' in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage( _(u'message_no_templates_selected', default=u'You have not selected any templates'), type="info") return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user('current_user'), responsible=self.replace_interactive_user('current_user'), responsible_client=get_client_id(), task_type='direct-execution', deadline=date.today() + timedelta(highest_deadline + MAIN_TASK_DEADLINE_DELTA), ) main_task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer( self.context, main_task, checkConstraints=True) # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, 'portal_workflow') wft.doActionFor(main_task, 'task-transition-open-in-progress') # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user( template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == 'interactive_users': info = getUtility(IContactInformation) responsible_assigned_clients = tuple( info.get_assigned_clients(data['responsible'])) current_client = get_current_client() if not responsible_assigned_clients or \ current_client in responsible_assigned_clients: data['responsible_client'] = current_client.client_id else: data['responsible_client'] = \ responsible_assigned_clients[0].client_id else: data['responsible_client'] = template.responsible_client task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() IStatusMessage(self.request).addStatusMessage( _(u'message_tasks_created', default=u'tasks created'), type="info") return self.request.RESPONSE.redirect( '%s#tasks' % self.context.absolute_url())