diff --git a/gen/__init__.py b/gen/__init__.py
index 0d9776b..4c90018 100644
--- a/gen/__init__.py
+++ b/gen/__init__.py
@@ -1547,9 +1547,15 @@ class Date(Type):
def getFormattedValue(self, obj, value):
if self.isEmptyValue(value): return ''
- res = value.strftime('%d/%m/') + str(value.year())
+ tool = obj.getTool().appy()
+ # A problem may occur with some extreme year values. Replace the "year"
+ # part "by hand".
+ dateFormat = tool.dateFormat
+ if '%Y' in dateFormat:
+ dateFormat = dateFormat.replace('%Y', str(value.year()))
+ res = value.strftime(dateFormat)
if self.format == Date.WITH_HOUR:
- res += ' %s' % value.strftime('%H:%M')
+ res += ' %s' % value.strftime(tool.hourFormat)
return res
def getRequestValue(self, request, requestName=None):
diff --git a/gen/descriptors.py b/gen/descriptors.py
index 155edef..adbf5ad 100644
--- a/gen/descriptors.py
+++ b/gen/descriptors.py
@@ -539,18 +539,6 @@ class ToolClassDescriptor(ClassDescriptor):
fieldType = gen.Boolean(default=True, page='userInterface',
group=groupName)
self.addField(fieldName, fieldType)
- # Adds the boolean field for showing all states in current state or not.
- # If this boolean is True but the current phase counts only one state,
- # we will not show the state at all: the fact of knowing in what phase
- # we are is sufficient. If this boolean is False, we simply show the
- # current state.
- defaultValue = False
- if len(classDescr.getPhases()) > 1:
- defaultValue = True
- fieldName = 'showAllStatesInPhaseFor%s' % className
- fieldType = gen.Boolean(default=defaultValue, page='userInterface',
- group=groupName)
- self.addField(fieldName, fieldType)
class UserClassDescriptor(ClassDescriptor):
'''Appy-specific class for representing a user.'''
diff --git a/gen/generator.py b/gen/generator.py
index 86e2346..f62b263 100644
--- a/gen/generator.py
+++ b/gen/generator.py
@@ -502,6 +502,7 @@ class ZopeGenerator(Generator):
msg('object_history', '', msg.OBJECT_HISTORY),
msg('object_created_by', '', msg.OBJECT_CREATED_BY),
msg('object_created_on', '', msg.OBJECT_CREATED_ON),
+ msg('object_modified_on', '', msg.OBJECT_MODIFIED_ON),
msg('object_action', '', msg.OBJECT_ACTION),
msg('object_author', '', msg.OBJECT_AUTHOR),
msg('action_date', '', msg.ACTION_DATE),
diff --git a/gen/indexer.py b/gen/indexer.py
index 79d069b..21c5432 100644
--- a/gen/indexer.py
+++ b/gen/indexer.py
@@ -9,8 +9,8 @@ from appy.shared.utils import normalizeText
defaultIndexes = {
'State': 'ListIndex', 'UID': 'FieldIndex', 'Title': 'TextIndex',
'SortableTitle': 'FieldIndex', 'SearchableText': 'TextIndex',
- 'Creator': 'FieldIndex', 'Created': 'DateIndex', 'ClassName': 'FieldIndex',
- 'Allowed': 'KeywordIndex'}
+ 'Creator': 'FieldIndex', 'Created': 'DateIndex', 'Modified': 'DateIndex',
+ 'ClassName': 'FieldIndex', 'Allowed': 'KeywordIndex'}
# Stuff for creating or updating the indexes -----------------------------------
class TextIndexInfo:
diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py
index 5c33533..d7d2d9f 100644
--- a/gen/mixins/__init__.py
+++ b/gen/mixins/__init__.py
@@ -87,6 +87,10 @@ class BaseMixin:
appyObject = obj.appy()
if hasattr(appyObject, 'onEdit'):
msg = appyObject.onEdit(created)
+ # Update last modification date
+ if not created:
+ from DateTime import DateTime
+ obj.modified = DateTime()
obj.reindex()
return obj, msg
@@ -700,29 +704,6 @@ class BaseMixin:
res.append({'field':field, 'width':width, 'align': align})
return res
- def getAppyStates(self, phase, currentOnly=False):
- '''Returns information about the states that are related to p_phase.
- If p_currentOnly is True, we return the current state, even if not
- related to p_phase.'''
- currentState = self.State()
- if currentOnly:
- return [StateDescr(currentState, 'current').get()]
- res = []
- workflow = self.getWorkflow()
- stateStatus = 'done'
- for stateName in dir(workflow):
- if getattr(workflow, stateName).__class__.__name__ != 'State':
- continue
- if stateName == currentState:
- stateStatus = 'current'
- elif stateStatus != 'done':
- stateStatus = 'future'
- state = getattr(workflow, stateName)
- if (state.phase == phase) and \
- (self._appy_showState(workflow, state.show)):
- res.append(StateDescr(stateName, stateStatus).get())
- return res
-
def getAppyTransitions(self, includeFake=True, includeNotShowable=False):
'''This method returns info about transitions that one can trigger from
the user interface.
@@ -778,8 +759,7 @@ class BaseMixin:
for appyType in self.getAllAppyTypes():
typePhase = appyType.page.phase
if typePhase not in phases:
- states = self.getAppyStates(typePhase)
- phase = PhaseDescr(typePhase, states, self)
+ phase = PhaseDescr(typePhase, self)
res.append(phase.__dict__)
phases[typePhase] = phase
else:
@@ -1213,7 +1193,7 @@ class BaseMixin:
return wrapper
# --------------------------------------------------------------------------
- # Standard methods for computing values of standard Appy indexes
+ # Methods for computing values of standard Appy indexes
# --------------------------------------------------------------------------
def UID(self):
'''Returns the unique identifier for this object.'''
@@ -1246,6 +1226,11 @@ class BaseMixin:
'''When was this object created ?'''
return self.created
+ def Modified(self):
+ '''When was this object last modified ?'''
+ if hasattr(self.aq_base, 'modified'): return self.modified
+ return self.created
+
def State(self, name=True, initial=False):
'''Returns information about the current object state. If p_name is
True, the returned info is the state name. Else, it is the State
@@ -1291,11 +1276,12 @@ class BaseMixin:
res.add('user:%s' % id)
return list(res)
- def _appy_showState(self, workflow, stateShow):
- '''Must I show a state whose "show value" is p_stateShow?'''
+ def showState(self):
+ '''Must I show self's current state ?'''
+ stateShow = self.State(name=False).show
if callable(stateShow):
- return stateShow(workflow, self.appy())
- else: return stateShow
+ return stateShow(self.getWorkflow(), self.appy())
+ return stateShow
def _appy_listStates(self):
'''Lists the possible states for this object.'''
diff --git a/gen/model.py b/gen/model.py
index b1d1ddc..4d24717 100644
--- a/gen/model.py
+++ b/gen/model.py
@@ -210,7 +210,7 @@ setattr(Page, Page.pages.back.attribute, Page.pages.back)
# Prefixes of the fields generated on the Tool.
toolFieldPrefixes = ('podTemplate', 'formats', 'resultColumns',
'enableAdvancedSearch', 'numberOfSearchColumns',
- 'searchFields', 'showWorkflow', 'showAllStatesInPhase')
+ 'searchFields', 'showWorkflow')
defaultToolFields = ('title', 'mailHost', 'mailEnabled', 'mailFrom',
'appyVersion', 'dateFormat', 'hourFormat', 'users',
'connectedUsers', 'groups', 'translations',
diff --git a/gen/po.py b/gen/po.py
index 4073fbe..74eccbf 100644
--- a/gen/po.py
+++ b/gen/po.py
@@ -36,7 +36,6 @@ class PoMessage:
MSG_numberOfSearchColumns = "Number of search columns"
MSG_searchFields = "Search fields"
MSG_showWorkflow = 'Show workflow-related information'
- MSG_showAllStatesInPhase = 'Show all states in phase'
POD_ASKACTION = 'Trigger related action'
REF_NO = 'No object.'
REF_ADD = 'Add a new one'
@@ -163,6 +162,7 @@ class PoMessage:
OBJECT_HISTORY = 'History'
OBJECT_CREATED_BY = 'By'
OBJECT_CREATED_ON = 'On'
+ OBJECT_MODIFIED_ON = 'Last updated on'
OBJECT_ACTION = 'Action'
OBJECT_AUTHOR = 'Author'
ACTION_DATE = 'Date'
diff --git a/gen/ui/appy.css b/gen/ui/appy.css
index 35462a5..31104e0 100644
--- a/gen/ui/appy.css
+++ b/gen/ui/appy.css
@@ -115,7 +115,7 @@ img { border: 0; vertical-align: middle}
.summary {margin-bottom: 5px;}
.objectTitle { font-size: 11pt; border-bottom: 3px solid grey;
font-weight: bold;}
-.by { padding-top: 5px;}
+.by { padding-top: 5px; color: grey; font-size: 97% }
.workflow { text-align: center; border-top: 1px solid grey }
.underTitle { background-color: #e9e9e9 }
.objectNavigate { margin-top: 3px;}
diff --git a/gen/ui/nextState.png b/gen/ui/nextState.png
deleted file mode 100644
index bb8faf4..0000000
Binary files a/gen/ui/nextState.png and /dev/null differ
diff --git a/gen/ui/page.pt b/gen/ui/page.pt
index 475277b..4e88163 100644
--- a/gen/ui/page.pt
+++ b/gen/ui/page.pt
@@ -137,27 +137,6 @@
-
-
-
-
-
-
-
-
-
-