merge branch master

This commit is contained in:
Helmut Merz 2012-09-05 16:16:24 +02:00
commit 221ee291eb
10 changed files with 4515 additions and 35 deletions

View file

@ -25,6 +25,7 @@ from zope.cachedescriptors.property import Lazy
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
from cybertools.composer.report.base import BaseQueryCriteria from cybertools.composer.report.base import BaseQueryCriteria
from cybertools.util.jeep import Jeep
class BaseRow(object): class BaseRow(object):
@ -63,7 +64,7 @@ class Row(BaseRow):
@Lazy @Lazy
def allColumns(self): def allColumns(self):
return self.partent.context.getAllFields() return self.parent.context.getAllFields()
def useRowProperty(self, attr): def useRowProperty(self, attr):
return getattr(self, attr) return getattr(self, attr)
@ -192,7 +193,7 @@ class ResultSet(object):
@Lazy @Lazy
def displayedColumns(self): def displayedColumns(self):
return self.context.getActiveOutputFields() return Jeep(self.context.getActiveOutputFields())
@Lazy @Lazy
def groupColumns(self): def groupColumns(self):

View file

@ -187,6 +187,7 @@ class FieldInstance(object):
clientInstance = clientContext = request = None clientInstance = clientContext = request = None
value = undefined value = undefined
request = None
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
@ -433,5 +434,5 @@ class DropdownFieldInstance(FieldInstance):
for item in items: for item in items:
if str(item['token']) == str(value): if str(item['token']) == str(value):
return item['title'] return item['title']
return value return value or u''

View file

@ -21,11 +21,13 @@ View definitions for generation of documents.
""" """
import os import os
import quopri
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.publisher.browser import BrowserPage from zope.publisher.browser import BrowserPage
word_template = ViewPageTemplateFile('word_page.pt') word_template = ViewPageTemplateFile('word_page.pt')
body_template = ViewPageTemplateFile('word_body.pt')
class Base(BrowserPage): class Base(BrowserPage):
@ -34,17 +36,38 @@ class Base(BrowserPage):
encoding = 'ISO8859-15' encoding = 'ISO8859-15'
def __call__(self, *args, **kw): def __call__(self, *args, **kw):
data = self.index(*args, **kw).encode(self.encoding) content = self.index(*args, **kw).encode(self.encoding)
self.setHeader(data) self.setHeader(content)
return data return content
class WordDocument(Base): class WordDocument(Base):
isToplevel = True isToplevel = True
index = word_template index = word_template
bodyTemplate = body_template
showLinks = False showLinks = False
def embed(self, *args, **kw):
self.encoding = 'Windows-1252'
bodyMarker = 'lxdoc_body'
content = self.bodyTemplate(*args, **kw).encode(self.encoding)
baseDocument = self.readDocTemplate()
document = baseDocument.replace(bodyMarker,
self.quopri(content))
self.setHeader(document)
return document
def quopri(self, s):
return s.replace('="', '=3D"')
def readDocTemplate(self):
path = os.path.join(os.path.dirname(__file__), 'document.mht')
f = open(path, 'r')
doc = f.read()
f.close()
return doc
def setHeader(self, data, filename='document'): def setHeader(self, data, filename='document'):
fn = '%s.doc' % filename fn = '%s.doc' % filename
response = self.request.response response = self.request.response
@ -75,4 +98,3 @@ class WordDocument(Base):
css = f.read() css = f.read()
f.close() f.close()
return css return css

4399
docgen/document.mht Executable file

File diff suppressed because it is too large Load diff

View file

@ -78,6 +78,10 @@ th {
font-weight: bold; font-weight: bold;
} }
table.MsoHeader, p.MsoHeader {
mso-style-noshow:yes;
}
span.MsoFootnoteReference { span.MsoFootnoteReference {
mso-style-noshow:yes; mso-style-noshow:yes;
vertical-align: super; vertical-align: super;

1
docgen/word_body.pt Normal file
View file

@ -0,0 +1 @@
<metal:content use-macro="view/content" />

View file

@ -17,7 +17,8 @@
</head> </head>
<body class="doc"> <body class="doc">
<div class="Section2"> <div class="Section2"
tal:omit-tag="view/omitSectionElement|nothing">
<metal:content use-macro="view/content" /> <metal:content use-macro="view/content" />
</div> </div>
</body> </body>

View file

@ -342,6 +342,7 @@ application/x-123 wk
application/x-abiword abw application/x-abiword abw
application/x-apple-diskimage dmg application/x-apple-diskimage dmg
application/x-bcpio bcpio application/x-bcpio bcpio
application/x-binary repx
application/x-bittorrent torrent application/x-bittorrent torrent
application/x-cdf cdf application/x-cdf cdf
application/x-cdlink vcd application/x-cdlink vcd

View file

@ -530,16 +530,21 @@ class IWorkItem(ITrack):
'by its name or ID.') 'by its name or ID.')
state = Attribute('The current state the work item is in.') state = Attribute('The current state the work item is in.')
# standard attributes # standard attributes
workItemType = Attribute('The type of the work item '
'(work, event, deadline).')
title = Attribute('A short text characterizing the work item.') title = Attribute('A short text characterizing the work item.')
description = Attribute('A note about what has to be done, and why...') description = Attribute('A note about what has to be done, and why...')
deadline = Attribute('When the work has to be finished.')
start = Attribute('When the work was started.') start = Attribute('When the work was started.')
end = Attribute('When the work was finished.') end = Attribute('When the work was finished.')
duration = Attribute('How long it took to finish the work.') duration = Attribute('How long it took to finish the work.')
effort = Attribute('How much effort (time units) it took to finish the work.') effort = Attribute('How much effort (time units) it took '
'to finish the work.')
comment = Attribute('A note about what has been done, and why...') comment = Attribute('A note about what has been done, and why...')
# work item handling # work item handling
creator = Attribute('The party that has set up the work item.') creator = Attribute('The party that has set up the work item.')
created = Attribute('The timeStamp of the initial creation of the work item.') created = Attribute('The timeStamp of the initial creation '
'of the work item.')
newTask = Attribute('Optional: a new task that has been created based ' newTask = Attribute('Optional: a new task that has been created based '
'on this work item.') 'on this work item.')

View file

@ -32,6 +32,7 @@ from cybertools.stateful.definition import State, Transition
from cybertools.stateful.interfaces import IStatesDefinition from cybertools.stateful.interfaces import IStatesDefinition
from cybertools.tracking.btree import Track, getTimeStamp from cybertools.tracking.btree import Track, getTimeStamp
from cybertools.tracking.interfaces import ITrackingStorage from cybertools.tracking.interfaces import ITrackingStorage
from cybertools.util.jeep import Jeep
_not_found = object() _not_found = object()
@ -41,7 +42,7 @@ def workItemStates():
return StatesDefinition('workItemStates', return StatesDefinition('workItemStates',
State('new', 'new', State('new', 'new',
('plan', 'accept', 'start', 'work', 'finish', 'delegate', ('plan', 'accept', 'start', 'work', 'finish', 'delegate',
'cancel'), 'cancel', 'reopen'),
color='red'), color='red'),
State('planned', 'planned', State('planned', 'planned',
('plan', 'accept', 'start', 'work', 'finish', 'delegate', ('plan', 'accept', 'start', 'work', 'finish', 'delegate',
@ -63,11 +64,11 @@ def workItemStates():
State('cancelled', 'cancelled', State('cancelled', 'cancelled',
('plan', 'accept', 'start', 'work', 'move', 'modify', 'close'), ('plan', 'accept', 'start', 'work', 'move', 'modify', 'close'),
color='grey'), color='grey'),
State('closed', 'closed', (), color='lightblue'), State('closed', 'closed', ('reopen',), color='lightblue'),
# not directly reachable states: # not directly reachable states:
State('delegated', 'delegated', State('delegated', 'delegated',
('plan', 'accept', 'start', 'work', 'finish', 'close', ('plan', 'accept', #'start', 'work', 'finish',
'delegate', 'move', 'cancel', 'modify'), 'close', 'delegate', 'move', 'cancel', 'modify'),
color='purple'), color='purple'),
State('delegated_x', 'delegated', (), color='purple'), State('delegated_x', 'delegated', (), color='purple'),
State('moved', 'moved', State('moved', 'moved',
@ -82,7 +83,7 @@ def workItemStates():
# transitions: # transitions:
Transition('plan', 'plan', 'planned'), Transition('plan', 'plan', 'planned'),
Transition('accept', 'accept', 'accepted'), Transition('accept', 'accept', 'accepted'),
Transition('start', 'start working', 'running'), Transition('start', 'start working', 'running'), # obsolete?
Transition('work', 'work', 'done'), Transition('work', 'work', 'done'),
Transition('finish', 'finish', 'finished'), Transition('finish', 'finish', 'finished'),
Transition('cancel', 'cancel', 'cancelled'), Transition('cancel', 'cancel', 'cancelled'),
@ -90,10 +91,12 @@ def workItemStates():
Transition('delegate', 'delegate', 'planned'), Transition('delegate', 'delegate', 'planned'),
Transition('move', 'move', 'planned'), Transition('move', 'move', 'planned'),
Transition('close', 'close', 'closed'), Transition('close', 'close', 'closed'),
Transition('reopen', 're-open', 'planned'),
initialState='new') initialState='new')
fieldNames = ['title', 'description', 'start', 'end', 'duration', 'effort', fieldNames = ['title', 'description', 'deadline', 'start', 'end',
'duration', 'effort',
'comment', 'party'] # for use in editingRules 'comment', 'party'] # for use in editingRules
# meaning: - not editable, value=default # meaning: - not editable, value=default
@ -102,22 +105,55 @@ fieldNames = ['title', 'description', 'start', 'end', 'duration', 'effort',
# . default (may be empty) # . default (may be empty)
editingRules = dict( editingRules = dict(
plan = {'*': '++.....+'}, plan = {'*': '+++.....+'},
accept = {'*': '++.....-', accept = {'*': '+++.....-',
'planned': '++++++.-', 'planned': '+++++++.-',
'accepted': '++++++.-'}, 'accepted': '+++++++.-'},
start = {'*': '++./...-'}, start = {'*': '+++./...-'},
work = {'*': '++.....-', work = {'*': '+++.....-',
'running': '+++....-'}, 'running': '++++....-'},
finish = {'*': '++.....-', finish = {'*': '+++.....-',
'running': '+++....-'}, 'running': '++++....-'},
cancel = {'*': '++////./'}, cancel = {'*': '+++////./'},
modify = {'*': '++++++++'}, modify = {'*': '+++++++++'},
delegate= {'*': '++......'}, delegate= {'*': '+++++++.+'},
close = {'*': '++////./'}, move = {'*': '+++++++.-'},
close = {'*': '+++////./'},
reopen = {'*': '+++////./'},
) )
class WorkItemType(object):
""" Specify the type of a work item.
The work item type controls which actions (transitions)
and fields are available for a certain work item.
"""
def __init__(self, name, title, description=u'',
actions=None, fields=None, indicator=None):
self.name = name
self.title = title
self.description = description
self.actions = actions or list(editingRules)
self.fields = fields or ('deadline', 'start-end', 'duration-effort')
self.indicator = indicator
workItemTypes = Jeep((
WorkItemType('work', u'Unit of Work', indicator='work_work'),
WorkItemType('scheduled', u'Scheduled Event',
actions=('plan', 'accept', 'finish', 'cancel',
'modify', 'delegate', 'move', 'close', 'reopen'),
fields =('start-end', 'duration-effort',),
indicator='work_event'),
WorkItemType('deadline', u'Deadline',
actions=('plan', 'accept', 'finish', 'cancel',
'modify', 'delegate', 'move', 'close', 'reopen'),
fields =('deadline',),
indicator='work_deadline')
))
class WorkItem(Stateful, Track): class WorkItem(Stateful, Track):
""" A work item that may be stored as a track in a tracking storage. """ A work item that may be stored as a track in a tracking storage.
""" """
@ -130,7 +166,8 @@ class WorkItem(Stateful, Track):
typeInterface = IWorkItem typeInterface = IWorkItem
statesDefinition = 'organize.workItemStates' statesDefinition = 'organize.workItemStates'
initAttributes = set(['party', 'title', 'description', 'start', 'end', initAttributes = set(['workItemType', 'party', 'title', 'description',
'deadline', 'start', 'end',
'duration', 'effort']) 'duration', 'effort'])
def __init__(self, taskId, runId, userName, data): def __init__(self, taskId, runId, userName, data):
@ -143,6 +180,10 @@ class WorkItem(Stateful, Track):
return component.getUtility(IStatesDefinition, return component.getUtility(IStatesDefinition,
name=self.statesDefinition) name=self.statesDefinition)
def getWorkItemType(self):
name = self.workItemType
return name and workItemTypes[name] or None
@property @property
def party(self): def party(self):
return self.userName return self.userName
@ -194,7 +235,6 @@ class WorkItem(Stateful, Track):
self.state = self.state + '_x' self.state = self.state + '_x'
self.reindex('state') self.reindex('state')
new.doTransition(action) new.doTransition(action)
#new.reindex('state')
new.reindex() new.reindex()
return new return new
@ -230,17 +270,18 @@ class WorkItem(Stateful, Track):
return new return new
def move(self, userName, **kw): def move(self, userName, **kw):
moved = self.createNew('move', userName, **kw) xkw = dict(kw)
for k in ('deadline', 'start', 'end'):
xkw.pop(k, None) # do not change on source item
moved = self.createNew('move', userName, **xkw)
moved.userName = self.userName moved.userName = self.userName
moved.state = 'moved' moved.state = 'moved'
#moved.reindex('state')
moved.reindex() moved.reindex()
task = kw.pop('task', None) task = kw.pop('task', None)
new = moved.createNew(None, userName, taskId=task, runId=0, **kw) new = moved.createNew(None, userName, taskId=task, runId=0, **kw)
new.userName = self.userName new.userName = self.userName
new.data['source'] = moved.name new.data['source'] = moved.name
new.state = self.state new.state = self.state
#new.reindex('state')
new.reindex() new.reindex()
moved.data['target'] = new.name moved.data['target'] = new.name
if self.state in ('planned', 'accepted', 'delegated', 'moved', 'done'): if self.state in ('planned', 'accepted', 'delegated', 'moved', 'done'):
@ -274,7 +315,7 @@ class WorkItem(Stateful, Track):
if party is not None: if party is not None:
self.userName = party self.userName = party
self.reindex('userName') self.reindex('userName')
start = kw.get('start') start = kw.get('start') or kw.get('deadline') # TODO: check OK?
if start is not None: if start is not None:
self.timeStamp = start self.timeStamp = start
self.reindex('timeStamp') self.reindex('timeStamp')
@ -293,6 +334,10 @@ class WorkItem(Stateful, Track):
if copyData is None: if copyData is None:
copyData = self.initAttributes copyData = self.initAttributes
newData = {} newData = {}
start = kw.get('start')
deadline = kw.get('deadline')
if not start and deadline:
kw['start'] = deadline
for k in self.initAttributes.union(set(['comment'])): for k in self.initAttributes.union(set(['comment'])):
v = kw.get(k, _not_found) v = kw.get(k, _not_found)
if v is _not_found and k in copyData: if v is _not_found and k in copyData: