From 4c746b272c6cdc16e70ab7251761b523dd32a7b9 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Wed, 2 May 2012 16:39:57 +0200 Subject: [PATCH 1/8] add 'cssClass' property for controlling display of report fields --- composer/report/field.py | 1 + 1 file changed, 1 insertion(+) diff --git a/composer/report/field.py b/composer/report/field.py index 6257e00..8a26040 100644 --- a/composer/report/field.py +++ b/composer/report/field.py @@ -44,6 +44,7 @@ class Field(Component): storeData = True renderer = 'standard' operator = 'in' + cssClass = '' executionSteps = ['query', 'sort', 'output'] # , 'totals'] From 601fda98bf3b2a6fc0c3d85ff16b8871e90a9080 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 7 May 2012 15:11:24 +0200 Subject: [PATCH 2/8] provide auxiliary method for retrieving first row of result set, e.g. for populating header fields --- composer/report/result.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/composer/report/result.py b/composer/report/result.py index f947ce4..d5dc2af 100644 --- a/composer/report/result.py +++ b/composer/report/result.py @@ -75,8 +75,15 @@ class ResultSet(object): row.sequenceNumber = idx + 1 return result + @Lazy + def result(self): + return self.getResult() + def __iter__(self): - return iter(self.getResult()) + return iter(self.result) + + def first(self): + return self.result[0] @Lazy def displayedColumns(self): From 3452ead6d3827993e3d22a87f3c8e89e31f9ed3c Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 7 May 2012 17:58:46 +0200 Subject: [PATCH 3/8] keep party on old (moved) item when moving work item to new task --- organize/work.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/organize/work.py b/organize/work.py index ba4bcb7..c3af27d 100644 --- a/organize/work.py +++ b/organize/work.py @@ -231,8 +231,10 @@ class WorkItem(Stateful, Track): def move(self, userName, **kw): moved = self.createNew('move', userName, **kw) + moved.userName = self.userName moved.state = 'moved' - moved.reindex('state') + #moved.reindex('state') + moved.reindex() task = kw.pop('task', None) new = moved.createNew(None, userName, taskId=task, runId=0, **kw) new.userName = self.userName From 78bdb5f6d025cdca6251c6f297bd8c6deeb3b897 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 7 May 2012 17:59:16 +0200 Subject: [PATCH 4/8] fix default retrieval of value used for sorting --- composer/report/field.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/composer/report/field.py b/composer/report/field.py index 8a26040..ae689ac 100644 --- a/composer/report/field.py +++ b/composer/report/field.py @@ -87,9 +87,8 @@ class Field(Component): return self.getValue(row) def getSortValue(self, row): - # TODO: consider 'descending' flag, use raw value instead of formatted one - return getattr(row, self.name, None) - #return self.getValue(row) + # TODO: consider 'descending' flag + return self.getValue(row) class CalculatedField(Field): From 3beae86d4de5e790bc24902469dfa0eae37f81c8 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Wed, 9 May 2012 13:39:09 +0200 Subject: [PATCH 5/8] tolerate empty result set when retrieving first row (e.g. for getting header information) --- composer/report/result.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer/report/result.py b/composer/report/result.py index d5dc2af..1bad061 100644 --- a/composer/report/result.py +++ b/composer/report/result.py @@ -83,7 +83,9 @@ class ResultSet(object): return iter(self.result) def first(self): - return self.result[0] + if len(self.result) > 0: + return self.result[0] + return self.rowFactory(None, self) @Lazy def displayedColumns(self): From 0e060bc34e87b397b4f7b1fb275f15867fe506d2 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 10 May 2012 10:19:12 +0200 Subject: [PATCH 6/8] sanitize HTML before stripping tags in order to avoid empty results with certain Word formattings --- util/html.py | 1 + 1 file changed, 1 insertion(+) diff --git a/util/html.py b/util/html.py index 51b15df..69aade7 100644 --- a/util/html.py +++ b/util/html.py @@ -79,6 +79,7 @@ def checkStyle(k): def stripAll(value): + value = sanitize(value) def collectText(tags): for tag in tags: if type(tag) is NavigableString: From ae04c1ec8d288a810142d6303648ce9f50eb432b Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 15 May 2012 16:48:01 +0200 Subject: [PATCH 7/8] fix merge conflict --- composer/report/field.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/composer/report/field.py b/composer/report/field.py index 737ff7c..cf9bf41 100644 --- a/composer/report/field.py +++ b/composer/report/field.py @@ -121,14 +121,8 @@ class Field(Component): return self.getValue(row) def getSortValue(self, row): -<<<<<<< HEAD - # TODO: consider 'descending' flag (?use raw value instead of formatted one?) - return self.getValue(row) - #return getattr(row, self.name, None) -======= # TODO: consider 'descending' flag return self.getValue(row) ->>>>>>> master class CalculatedField(Field): From 2058dcbf6a26f3c9cc55bb5ade769c5c70eee672 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 20 May 2012 12:05:49 +0200 Subject: [PATCH 8/8] make subclassing of WorkItem easier by parameterizing type interface --- organize/work.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/organize/work.py b/organize/work.py index c3af27d..7168006 100644 --- a/organize/work.py +++ b/organize/work.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2011 Helmut Merz helmutm@cy55.de +# Copyright (c) 2012 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,6 @@ """ Planning and recording activities (work items). - -$Id$ """ from zope import component @@ -42,7 +40,8 @@ _not_found = object() def workItemStates(): return StatesDefinition('workItemStates', State('new', 'new', - ('plan', 'accept', 'start', 'work', 'finish', 'delegate', 'cancel'), + ('plan', 'accept', 'start', 'work', 'finish', 'delegate', + 'cancel'), color='red'), State('planned', 'planned', ('plan', 'accept', 'start', 'work', 'finish', 'delegate', @@ -67,13 +66,13 @@ def workItemStates(): State('closed', 'closed', (), color='lightblue'), # not directly reachable states: State('delegated', 'delegated', - ('plan', 'accept', 'start', 'work', 'finish', 'close', 'delegate', - 'move', 'cancel', 'modify'), + ('plan', 'accept', 'start', 'work', 'finish', 'close', + 'delegate', 'move', 'cancel', 'modify'), color='purple'), State('delegated_x', 'delegated', (), color='purple'), State('moved', 'moved', - ('plan', 'accept', 'start', 'work', 'finish', 'close', 'delegate', - 'move', 'cancel', 'modify'), + ('plan', 'accept', 'start', 'work', 'finish', 'close', + 'delegate', 'move', 'cancel', 'modify'), color='grey'), State('moved_x', 'moved', (), color='grey'), State('replaced', 'replaced', (), color='grey'), @@ -95,7 +94,7 @@ def workItemStates(): fieldNames = ['title', 'description', 'start', 'end', 'duration', 'effort', - 'comment', 'party'] + 'comment', 'party'] # for use in editingRules # meaning: - not editable, value=default # / not editable, value=None @@ -125,11 +124,11 @@ class WorkItem(Stateful, Track): implements(IWorkItem) - statesDefinition = 'organize.workItemStates' - metadata_attributes = Track.metadata_attributes + ('state',) index_attributes = metadata_attributes typeName = 'WorkItem' + typeInterface = IWorkItem + statesDefinition = 'organize.workItemStates' initAttributes = set(['party', 'title', 'description', 'start', 'end', 'duration', 'effort']) @@ -141,7 +140,8 @@ class WorkItem(Stateful, Track): self.data['created'] = self.timeStamp def getStatesDefinition(self): - return component.getUtility(IStatesDefinition, name=self.statesDefinition) + return component.getUtility(IStatesDefinition, + name=self.statesDefinition) @property def party(self): @@ -165,7 +165,7 @@ class WorkItem(Stateful, Track): return self.data.get('effort') or self.duration def __getattr__(self, attr): - if attr not in IWorkItem: + if attr not in self.typeInterface: raise AttributeError(attr) return self.data.get(attr)