From 59bb401b8fdfe932b888596f9aceb88d73644193 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 10 Jun 2012 16:29:33 +0200 Subject: [PATCH 1/6] create follow-up event: extend form showing tasks of base event for selection --- locales/de/LC_MESSAGES/loops.mo | Bin 17622 -> 17737 bytes locales/de/LC_MESSAGES/loops.po | 8 +++++++- organize/browser/event.py | 33 ++++++++++++++++++++++++++++++-- organize/browser/view_macros.pt | 25 ++++++++++++++++++++++-- organize/work/meeting.pt | 15 ++++++++++++++- 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 149decde020c9b503dc31e062cd2feb934a0c96e..14888c38e0f6d21d09c267acea9c997e1a915c53 100644 GIT binary patch delta 6784 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 y>b!!l5f2eHa!Zz\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -242,6 +242,9 @@ msgstr "Folgetermin anlegen..." msgid "Create an event that is linked to this one." msgstr "Einen neuen Termin anlegen, der mit diesem verknüpft ist." +msgid "Create Follow-up Event for: $event" +msgstr "Folgetermin anlegen für: $event" + msgid "Edit Event..." msgstr "Termin bearbeiten..." @@ -395,6 +398,9 @@ msgstr "Thema" msgid "Task" msgstr "Aufgabe" +msgid "Tasks" +msgstr "Aufgaben" + msgid "Domain" msgstr "Bereich" diff --git a/organize/browser/event.py b/organize/browser/event.py index 470fe8a..004daeb 100644 --- a/organize/browser/event.py +++ b/organize/browser/event.py @@ -35,7 +35,9 @@ from loops.browser.form import CreateConceptPage, CreateConcept from loops.browser.form import EditConceptPage, EditConcept from loops.browser.node import NodeView from loops.common import adapted +from loops.organize.work.meeting import MeetingMinutes from loops.util import _ +from loops import util organize_macros = ViewPageTemplateFile('view_macros.pt') @@ -247,12 +249,39 @@ class CalendarInfo(NodeView): # special forms -class CreateFollowUpEventForm(CreateConceptPage): +class CreateFollowUpEventForm(CreateConceptPage, MeetingMinutes): fixedType = True typeToken = '.loops/concepts/event' form_action = 'create_followup_event' - showAssignments = True + showAssignments = False + + @Lazy + def macro(self): + return organize_macros.macros['create_followup_event'] + + @Lazy + def baseEvent(self): + return adapted(self.virtualTargetObject) + + @Lazy + def title(self): + event = self.baseEvent + evView = ConceptView(event, self.request) + eventTitle = u'%s, %s' % (event.title, evView.data['start']) + return _(u'Create Follow-up Event for: $event', + mapping=dict(event=eventTitle)) + + @Lazy + def data(self): + data = self.getData() + data['title'] = self.baseEvent.title + data['description'] = self.baseEvent.description + return data + + def results(self): + return self.reportInstance.getResults( + dict(tasks=util.getUidForObject(self.virtualTargetObject))) class EditFollowUpEventForm(EditConceptPage, CreateFollowUpEventForm): diff --git a/organize/browser/view_macros.pt b/organize/browser/view_macros.pt index 51f5434..93631a0 100644 --- a/organize/browser/view_macros.pt +++ b/organize/browser/view_macros.pt @@ -1,5 +1,4 @@ - - + @@ -56,6 +55,25 @@ +
+

+ + +

Tasks

+ + + + + + +
@@ -113,3 +131,6 @@
+ + + diff --git a/organize/work/meeting.pt b/organize/work/meeting.pt index acd924b..30ca9f9 100644 --- a/organize/work/meeting.pt +++ b/organize/work/meeting.pt @@ -14,8 +14,14 @@
+ tal:define="results reportView/results; + showCheckboxes cb_name|nothing"> + + +
+ Task/Action
+ @@ -49,6 +60,8 @@
From 4447ea04ef28aad4d77edd509ada5a5935b552da Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 10 Jun 2012 18:04:45 +0200 Subject: [PATCH 2/6] provide generation of meeting minutes Word document --- locales/de/LC_MESSAGES/loops.mo | Bin 17737 -> 17811 bytes locales/de/LC_MESSAGES/loops.po | 3 +++ organize/work/configure.zcml | 6 ++++++ organize/work/meeting.pt | 14 ++++++++++++++ organize/work/meeting.py | 24 ++++++++++++++++++++++++ 5 files changed, 47 insertions(+) diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 14888c38e0f6d21d09c267acea9c997e1a915c53..c90233031aa981a76556703f28f70f418b92d917 100644 GIT binary patch delta 6695 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 L+t8zJ@pAtI$a0Ye delta 6624 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 diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 02ef715..76f2957 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -293,6 +293,9 @@ msgstr "Besprechungsprotokoll anzeigen..." msgid "Show meeting minutes for this object." msgstr "Besprechungsprotokoll für dieses Objekt anzeigen." +msgid "Download Meeting Minutes" +msgstr "Besprechungsprotokoll generieren" + msgid "Task/Action" msgstr "Aufgabe" diff --git a/organize/work/configure.zcml b/organize/work/configure.zcml index a0df764..4c88e42 100644 --- a/organize/work/configure.zcml +++ b/organize/work/configure.zcml @@ -103,6 +103,12 @@ class="loops.organize.work.meeting.MeetingMinutes" permission="zope.View" /> + +
+ + Download Meeting Minutes +
  +
+
+ + +
diff --git a/organize/work/meeting.py b/organize/work/meeting.py index cf4abf9..7aaa8a9 100644 --- a/organize/work/meeting.py +++ b/organize/work/meeting.py @@ -24,6 +24,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy from cybertools.browser.action import actions +from cybertools.docgen.base import WordDocument from loops.browser.action import TargetAction from loops.expert.browser.report import ResultsConceptView from loops.util import _ @@ -41,6 +42,7 @@ actions.register('meeting_minutes', 'portlet', TargetAction, class MeetingMinutes(ResultsConceptView): reportName = 'meeting_minutes' + reportDownload = 'meeting_minutes.doc' @Lazy def meeting_macros(self): @@ -59,3 +61,25 @@ class MeetingMinutes(ResultsConceptView): if renderer == 'subreport': return self.meeting_macros[renderer] return self.result_macros[renderer] + + +class MeetingMinutesDocument(WordDocument, MeetingMinutes): + + isToplevel = True + + def __init__(self, context, request): + MeetingMinutes.__init__(self, context, request) + + @Lazy + def macros(self): + return meeting_template.macros + + @Lazy + def reportRenderer(self): + return self.macros['document'] + + @Lazy + def content(self): + return self.reportRenderer + + From 707a1dd8c47cd37ede7df4839d5fb3760e336ced Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 11 Jun 2012 10:17:40 +0200 Subject: [PATCH 3/6] show meeting minutes as Word document --- expert/browser/report.py | 3 +- organize/browser/view_macros.pt | 1 + organize/work/meeting.pt | 29 +++++++++++--- organize/work/report.py | 68 +++++++++++++++++++++++++-------- 4 files changed, 79 insertions(+), 22 deletions(-) diff --git a/expert/browser/report.py b/expert/browser/report.py index b33c715..fbbb7c2 100644 --- a/expert/browser/report.py +++ b/expert/browser/report.py @@ -147,7 +147,8 @@ class ResultsConceptView(ConceptView): reportType = self.reportType or self.report.reportType ri = component.getAdapter(self.report, IReportInstance, name=reportType) - ri.view = self.nodeView + #ri.view = self.nodeView + ri.view = self return ri def results(self): diff --git a/organize/browser/view_macros.pt b/organize/browser/view_macros.pt index 93631a0..b3eb002 100644 --- a/organize/browser/view_macros.pt +++ b/organize/browser/view_macros.pt @@ -67,6 +67,7 @@

Tasks

diff --git a/organize/work/meeting.pt b/organize/work/meeting.pt index 0d5fe9e..036ccc4 100644 --- a/organize/work/meeting.pt +++ b/organize/work/meeting.pt @@ -3,7 +3,8 @@
+ reportView nocall:item; + results reportView/results">
@@ -21,15 +22,33 @@
-
+ reportView nocall:item; + results reportView/results; + fields results/context/fields"> + + +
+ + +
+

Meeting Minutes

+

+

+
+ + - + + +
+
+
+ tal:define="showCheckboxes cb_name|nothing">
diff --git a/organize/work/report.py b/organize/work/report.py index 4bbd9e0..9690dfd 100644 --- a/organize/work/report.py +++ b/organize/work/report.py @@ -26,14 +26,14 @@ from zope.component import adapter from cybertools.composer.report.base import Report from cybertools.composer.report.base import LeafQueryCriteria, CompoundQueryCriteria -from cybertools.composer.report.field import Field +from cybertools.composer.report.field import Field, CalculatedField from cybertools.composer.report.result import ResultSet, Row as BaseRow from cybertools.organize.interfaces import IWorkItems from cybertools.util.date import timeStamp2Date from cybertools.util.format import formatDate from cybertools.util.jeep import Jeep from loops.common import adapted, baseObject -from loops.expert.field import TargetField, TextField, UrlField +from loops.expert.field import TargetField, DateField, TextField, UrlField from loops.expert.field import SubReport, SubReportField from loops.expert.report import ReportInstance from loops import util @@ -44,7 +44,8 @@ class StateField(Field): value = self.getValue(row) return util._(value) -class DateField(Field): + +class TrackDateField(Field): part = 'date' format = 'short' @@ -65,7 +66,7 @@ class DateField(Field): return u'' -class TimeField(DateField): +class TrackTimeField(TrackDateField): part = 'time' @@ -105,14 +106,14 @@ dayFrom = Field('dayFrom', u'Start Day', dayTo = Field('dayTo', u'End Day', description=u'The last day until which to select work.', executionSteps=['query']) -day = DateField('day', u'Day', +day = TrackDateField('day', u'Day', description=u'The day the work was done.', cssClass='center', executionSteps=['sort', 'output']) -timeStart = TimeField('start', u'Start', +timeStart = TrackTimeField('start', u'Start', description=u'The time the unit of work was started.', executionSteps=['sort', 'output']) -timeEnd = TimeField('end', u'End', +timeEnd = TrackTimeField('end', u'End', description=u'The time the unit of work was finished.', executionSteps=['output']) task = TargetField('taskId', u'Task', @@ -272,7 +273,21 @@ class MeetingMinutesWork(WorkReportInstance, SubReport): return [] -taskTitle = UrlField('title', u'Title', +eventTitle = CalculatedField('eventTitle', u'Event Title', + description=u'', + executionSteps=(['header'])) +eventDescription = CalculatedField('eventDescription', u'Event Description', + description=u'', + executionSteps=(['header'])) +eventStart = DateField('eventStart', u'Event Start', + description=u'', + format=('dateTime', 'short'), + executionSteps=(['header'])) +eventEnd = DateField('eventEnd', u'Event End', + description=u'', + format=('dateTime', 'short'), + executionSteps=(['header'])) +taskTitle = UrlField('title', u'Task Title', description=u'The short description of the task.', cssClass='header-1', executionSteps=['output']) @@ -288,23 +303,44 @@ workItems = SubReportField('workItems', u'Work Items', class TaskRow(BaseRow): - pass + @Lazy + def event(self): + return self.parent.context.view.adapted + + @Lazy + def eventTitle(self): + return self.event.title + + @Lazy + def eventDescription(self): + return self.event.description + + @Lazy + def eventStart(self): + return self.event.start + + @Lazy + def eventEnd(self): + return self.event.end + + useRowProperty = BaseRow.useRowProperty + attributeHandlers = dict( + eventStart=useRowProperty, + eventEnd=useRowProperty, + ) + + class MeetingMinutes(WorkReportInstance): - # TODO: - # header (event) fields: title, description, from/to, - # location, participants (or put in description?) - # result set field for work items - # work item fields: title, description, party, deadline, state - type = "meeting_minutes" label = u'Meeting Minutes' rowFactory = TaskRow - fields = Jeep((tasks, taskTitle, taskDescription, workItems)) + fields = Jeep((eventTitle, eventStart, eventEnd, eventDescription, + tasks, taskTitle, taskDescription, workItems)) defaultOutputFields = fields states = ('planned', 'accepted', 'done', 'done_x', 'finished') From 719bd165aae0906424973e7edaf4586c3c432b66 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 11 Jun 2012 17:32:34 +0200 Subject: [PATCH 4/6] work in progress: Competence and Certification Management (CCM): fix structure, start with form for qualification record creation --- knowledge/browser.py | 3 ++ knowledge/configure.zcml | 13 ++++++ knowledge/data/loops_knowledge_de.dmp | 34 +++++++-------- knowledge/data/loops_knowledge_update_de.dmp | 44 ++++++++++++++++++++ knowledge/knowledge_macros.pt | 42 +++++++++++++++++++ knowledge/qualification.py | 11 ++++- organize/README.txt | 2 +- organize/work/browser.py | 7 +++- 8 files changed, 134 insertions(+), 22 deletions(-) create mode 100644 knowledge/data/loops_knowledge_update_de.dmp diff --git a/knowledge/browser.py b/knowledge/browser.py index ff9781e..8a7a281 100644 --- a/knowledge/browser.py +++ b/knowledge/browser.py @@ -32,6 +32,7 @@ from loops.browser.common import BaseView from loops.browser.concept import ConceptView from loops.expert.browser.report import ResultsConceptView from loops.knowledge.interfaces import IPerson, ITask +from loops.knowledge.qualification import QualificationRecord from loops.organize.work.browser import CreateWorkItemForm, CreateWorkItem from loops.organize.party import getPersonForUser from loops.util import _ @@ -120,6 +121,8 @@ class PersonQualificationView(ResultsConceptView): class CreateQualificationRecordForm(CreateWorkItemForm): macros = knowledge_macros + recordManagerName = 'qualification' + trackFactory = QualificationRecord @Lazy def macro(self): diff --git a/knowledge/configure.zcml b/knowledge/configure.zcml index 2552184..da2bb30 100644 --- a/knowledge/configure.zcml +++ b/knowledge/configure.zcml @@ -100,6 +100,19 @@ factory="loops.knowledge.browser.Candidates" permission="zope.View" /> + + + + diff --git a/knowledge/data/loops_knowledge_de.dmp b/knowledge/data/loops_knowledge_de.dmp index 2ca69b4..3b2ce7b 100644 --- a/knowledge/data/loops_knowledge_de.dmp +++ b/knowledge/data/loops_knowledge_de.dmp @@ -1,17 +1,17 @@ -type(u'competence', u'Competence', viewName=u'', - typeInterface=u'', options=u'action.portlet:edit_concept') +type(u'competence', u'Kompetenz', viewName=u'', + typeInterface=u'', options=u'action.portlet:create_subtype,edit_concept') type(u'person', u'Person', viewName=u'', typeInterface=u'loops.knowledge.interfaces.IPerson', - options=u'action.portlet:editPerson') + options=u'action.portlet:createQualification,editPerson') type(u'task', u'Aufgabe', viewName=u'', typeInterface=u'loops.knowledge.interfaces.ITask', - options=u'action.portlet:createTopic,editTopic') + options=u'action.portlet:createTask,editTask') type(u'topic', u'Thema', viewName=u'', typeInterface=u'loops.knowledge.interfaces.ITopic', - options=u'action.portlet:createTopic,editTopic') + options=u'action.portlet:createTask,createTopic,editTopic') type(u'training', u'Schulung', viewName=u'', typeInterface=u'loops.organize.interfaces.ITask', - options=u'action.portlet:create_subtype,edit_concept') + options=u'action.portlet:edit_concept') concept(u'general', u'Allgemein', u'domain') concept(u'system', u'System', u'domain') @@ -26,19 +26,19 @@ concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children', predicateInterface='loops.interfaces.IIsSubtype') # structure -child(u'competence', u'general', u'standard') -child(u'depends', u'general', u'standard') -child(u'knows', u'general', u'standard') -child(u'person', u'general', u'standard') -child(u'provides', u'general', u'standard') -child(u'requires', u'general', u'standard') -child(u'task', u'general', u'standard') -child(u'topic', u'general', u'standard') -child(u'training', u'general', u'standard') +child(u'general', u'competence', u'standard') +child(u'general', u'depends', u'standard') +child(u'general', u'knows', u'standard') +child(u'general', u'person', u'standard') +child(u'general', u'provides', u'standard') +child(u'general', u'requires', u'standard') +child(u'general', u'task', u'standard') +child(u'general', u'topic', u'standard') +child(u'general', u'training', u'standard') -child(u'issubtype', u'system', u'standard') +child(u'system', u'issubtype', u'standard') -child(u'training', u'competence', u'issubtype', usePredicate=u'provides') +child(u'competence', u'training', u'issubtype', usePredicate=u'provides') # records records(u'qualification', u'loops.knowledge.qualification.QualificationRecord') diff --git a/knowledge/data/loops_knowledge_update_de.dmp b/knowledge/data/loops_knowledge_update_de.dmp new file mode 100644 index 0000000..4080f43 --- /dev/null +++ b/knowledge/data/loops_knowledge_update_de.dmp @@ -0,0 +1,44 @@ +type(u'competence', u'Kompetenz', viewName=u'', + typeInterface=u'', options=u'action.portlet:create_subtype,edit_concept') +# type(u'person', u'Person', viewName=u'', +# typeInterface=u'loops.knowledge.interfaces.IPerson', +# options=u'action.portlet:editPerson') +# type(u'task', u'Aufgabe', viewName=u'', +# typeInterface=u'loops.knowledge.interfaces.ITask', +# options=u'action.portlet:createTask,editTask') +# type(u'topic', u'Thema', viewName=u'', +# typeInterface=u'loops.knowledge.interfaces.ITopic', +# options=u'action.portlet:createTask,createTopic,editTopic') +type(u'training', u'Schulung', viewName=u'', + typeInterface=u'loops.organize.interfaces.ITask', + options=u'action.portlet:edit_concept') + +concept(u'general', u'Allgemein', u'domain') +concept(u'system', u'System', u'domain') + +# predicates +concept(u'depends', u'depends', u'predicate') +concept(u'knows', u'knows', u'predicate') +concept(u'provides', u'provides', u'predicate') +concept(u'requires', u'requires', u'predicate') + +concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children', + predicateInterface='loops.interfaces.IIsSubtype') + +# structure +child(u'general', u'competence', u'standard') +child(u'general', u'depends', u'standard') +child(u'general', u'knows', u'standard') +#child(u'general', u'person', u'standard') +child(u'general', u'provides', u'standard') +child(u'general', u'requires', u'standard') +#child(u'general', u'task', u'standard') +#child(u'general', u'topic', u'standard') +child(u'general', u'training', u'standard') + +child(u'system', u'issubtype', u'standard') + +child(u'competence', u'training', u'issubtype', usePredicate=u'provides') + +# records +records(u'qualification', u'loops.knowledge.qualification.QualificationRecord') diff --git a/knowledge/knowledge_macros.pt b/knowledge/knowledge_macros.pt index 5d12f77..f775b71 100644 --- a/knowledge/knowledge_macros.pt +++ b/knowledge/knowledge_macros.pt @@ -62,6 +62,48 @@
+ + +
Add Qualification Record
+
+ +
+
+
+
+ + +   + + + + + +
+
+ +
+
+
diff --git a/knowledge/qualification.py b/knowledge/qualification.py index 62b115e..f123c39 100644 --- a/knowledge/qualification.py +++ b/knowledge/qualification.py @@ -38,8 +38,12 @@ from loops.organize.work.base import WorkItem, WorkItems @implementer(IStatesDefinition) def qualificationStates(): return StatesDefinition('qualification', + State('new', 'new', ('assign',), + color='grey'), State('open', 'open', - ('register', 'pass', 'fail', 'cancel', 'modify'), + ('register', + #'pass', 'fail', + 'cancel', 'modify'), color='red'), State('registered', 'registered', ('register', 'pass', 'fail', 'unregister', 'cancel', 'modify'), @@ -61,14 +65,17 @@ def qualificationStates(): State('open_x', 'open', ('modify',), color='red'), State('registered_x', 'registered', ('modify',), color='yellow'), # transitions: + Transition('assign', 'assign', 'open'), Transition('register', 'register', 'registered'), Transition('pass', 'pass', 'passed'), Transition('fail', 'fail', 'failed'), Transition('unregister', 'unregister', 'open'), Transition('cancel', 'cancel', 'cancelled'), + Transition('modify', 'modify', 'open'), Transition('close', 'close', 'closed'), Transition('open', 'open', 'open'), - initialState='open') + #initialState='open') + initialState='new') # TODO: handle assignment to competence class QualificationRecord(WorkItem): diff --git a/organize/README.txt b/organize/README.txt index 7857c1a..55bc758 100644 --- a/organize/README.txt +++ b/organize/README.txt @@ -260,7 +260,7 @@ Automatic security settings on persons >>> from zope.traversing.api import getName >>> list(sorted(getName(c) for c in concepts['person'].getChildren())) - [u'general', u'jim', u'john', u'martha', u'person.newuser'] + [u'jim', u'john', u'martha', u'person.newuser'] Person objects that have a user assigned to them receive this user (principal) as their owner. diff --git a/organize/work/browser.py b/organize/work/browser.py index dfcc9d1..f0d86fb 100644 --- a/organize/work/browser.py +++ b/organize/work/browser.py @@ -307,6 +307,8 @@ class UserWorkItems(PersonWorkItems): class CreateWorkItemForm(ObjectForm, BaseTrackView): template = work_macros + recordManagerName = 'work' + trackFactory = WorkItem def checkPermissions(self): return canAccessObject(self.task or self.target) @@ -325,9 +327,10 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView): def track(self): id = self.request.form.get('id') if id is not None: - workItems = self.loopsRoot.getRecordManager()['work'] + workItems = self.loopsRoot.getRecordManager()[ + self.recordManagerName] return workItems.get(id) - return WorkItem(None, 0, None, {}) + return self.trackFactory(None, 0, None, {}) @Lazy def title(self): From 2e8618b375ec73b9ca2b540d647a90aacde3b805 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 12 Jun 2012 18:20:16 +0200 Subject: [PATCH 5/6] creation of follow-up meeting with copying of tasks OK --- organize/README.txt | 5 ++++ organize/browser/event.py | 57 +++++++++++++++++++++++++++++++++++++-- organize/work/meeting.pt | 3 ++- organize/work/report.py | 4 +-- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/organize/README.txt b/organize/README.txt index 55bc758..0fc6988 100644 --- a/organize/README.txt +++ b/organize/README.txt @@ -390,6 +390,11 @@ Events listing >>> list(listing.events()) [] +Creation of follow-up event +--------------------------- + + >>> from loops.organize.browser.event import CreateFollowUpEvent + Send Email to Members ===================== diff --git a/organize/browser/event.py b/organize/browser/event.py index 004daeb..560abad 100644 --- a/organize/browser/event.py +++ b/organize/browser/event.py @@ -23,9 +23,11 @@ Definition of view classes and other browser related stuff for tasks. import calendar from datetime import date, datetime, timedelta from urllib import urlencode -from zope import interface, component +from zope.app.container.interfaces import INameChooser from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy +from zope import interface, component +from zope.traversing.api import getName from cybertools.browser.action import actions from cybertools.meta.interfaces import IOptions @@ -34,8 +36,10 @@ from loops.browser.concept import ConceptView from loops.browser.form import CreateConceptPage, CreateConcept from loops.browser.form import EditConceptPage, EditConcept from loops.browser.node import NodeView -from loops.common import adapted +from loops.common import adapted, baseObject +from loops.concept import Concept from loops.organize.work.meeting import MeetingMinutes +from loops.setup import addAndConfigureObject from loops.util import _ from loops import util @@ -300,6 +304,55 @@ class CreateFollowUpEvent(CreateConcept, BaseFollowUpController): defaultTypeToken = '.loops/concepts/event' + @Lazy + def followsPredicate(self): + return self.view.conceptManager['follows'] + + @Lazy + def baseEvent(self): + return adapted(self.view.virtualTargetObject) + + def update(self): + result = super(CreateFollowUpEvent, self).update() + form = self.request.form + toBeAssigned = form.get('cb_select_tasks') or [] + print '***', toBeAssigned + for uid in toBeAssigned: + task = util.getObjectForUid(uid) + self.createFollowUpTask(adapted(task)) + return result + + def createFollowUpTask(self, source): + cm = self.view.conceptManager + stask = baseObject(source) + bevt = baseObject(self.baseEvent) + taskType = stask.conceptType + taskName = getName(stask) + name = INameChooser(cm).chooseName(taskName, stask) + newTask = addAndConfigureObject(cm, Concept, name, + conceptType=taskType, + title=source.title, + description=source.description, + start=source.start, + end=source.end) + stask.assignChild(newTask, self.followsPredicate) + for rel in stask.getParentRelations(): + if rel.predicate != self.view.typePredicate: + if rel.first == bevt: + parent = self.object + else: + parent = rel.first + newTask.assignParent(parent, rel.predicate, + order=rel.order, relevance=rel.relevance) + return newTask + + def assignConcepts(self, obj): + bevt = baseObject(self.baseEvent) + bevt.assignChild(obj, self.followsPredicate) + for rel in bevt.getParentRelations(): + if rel.predicate != self.view.typePredicate: + obj.assignParent(rel.first, rel.predicate) + class EditFollowUpEvent(EditConcept, BaseFollowUpController): diff --git a/organize/work/meeting.pt b/organize/work/meeting.pt index 036ccc4..8361644 100644 --- a/organize/work/meeting.pt +++ b/organize/work/meeting.pt @@ -70,7 +70,8 @@ style="border: 1px solid grey"> + tal:attributes="name string:$cb_name:list; + value row/context/uid" />
diff --git a/organize/work/report.py b/organize/work/report.py index 9690dfd..deb8865 100644 --- a/organize/work/report.py +++ b/organize/work/report.py @@ -330,8 +330,6 @@ class TaskRow(BaseRow): ) - - class MeetingMinutes(WorkReportInstance): type = "meeting_minutes" @@ -345,6 +343,6 @@ class MeetingMinutes(WorkReportInstance): states = ('planned', 'accepted', 'done', 'done_x', 'finished') def selectObjects(self, parts): - return self.getTasks(parts)[1:] + return [adapted(t) for t in self.getTasks(parts)[1:]] From 49d2401bb45801e35bfb9d6b594e94ef79f753c0 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 18 Jun 2012 09:30:21 +0200 Subject: [PATCH 6/6] processing of 'limits' parameter, esp. when provided as form parameter --- expert/browser/report.py | 25 ++++++++++++++++++++++++- expert/report.py | 7 ++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/expert/browser/report.py b/expert/browser/report.py index fbbb7c2..ccfc26a 100644 --- a/expert/browser/report.py +++ b/expert/browser/report.py @@ -75,9 +75,32 @@ class ResultsView(NodeView): @Lazy def params(self): params = dict(self.request.form) - params.pop('report_execute', None) + params = self.parseParams(params) return params + def parseParams(self, params): + params.pop('report_execute', None) + if 'limits' in params: + params['limits'] = self.parseLimitsParam(params['limits']) + return params + + def parseLimitsParam(self, value): + if not value: + return None + if isinstance(value, basestring): + limits = value.split(',') + else: + limits = value + if len(limits) < 2: + limits.append(None) + result = [] + for p in limits[:2]: + if not p: + result.append(None) + else: + result.append(int(p)) + return result + @Lazy def report(self): return adapted(self.virtualTargetObject) diff --git a/expert/report.py b/expert/report.py index 516b21a..2255ce9 100644 --- a/expert/report.py +++ b/expert/report.py @@ -94,15 +94,20 @@ class ReportInstance(BaseReport): crit = self.queryCriteria if crit is None: return [] + limits = self.limits if dynaParams is not None: for k, v in dynaParams.items(): + if k == 'limits': + limits = v + break if k in crit.parts.keys(): crit.parts[k].comparisonValue = v parts = Jeep(crit.parts) result = list(self.selectObjects(parts)) # may modify parts qc = CompoundQueryCriteria(parts) return ResultSet(self, result, rowFactory=self.rowFactory, - sortCriteria=self.getSortCriteria(), queryCriteria=qc) + sortCriteria=self.getSortCriteria(), queryCriteria=qc, + limits=limits) def selectObjects(self, parts): # to be implemented by subclass