[Erp5-report] r7529 - /erp5/trunk/products/ERP5Form/PlanningBox.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Mon May 29 16:45:53 CEST 2006
Author: thomas
Date: Mon May 29 16:45:50 2006
New Revision: 7529
URL: http://svn.erp5.org?rev=7529&view=rev
Log:
Improved support for statistics using an external script
core bug fixes
Modified:
erp5/trunk/products/ERP5Form/PlanningBox.py
Modified: erp5/trunk/products/ERP5Form/PlanningBox.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Form/PlanningBox.py?rev=7529&r1=7528&r2=7529&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Form/PlanningBox.py (original)
+++ erp5/trunk/products/ERP5Form/PlanningBox.py Mon May 29 16:45:50 2006
@@ -509,19 +509,36 @@
property_names = Widget.Widget.property_names +\
- ['representation_type','main_axis_groups','size_header_height', 'size_border_width_left',
- 'size_planning_width', 'size_y_axis_width','size_y_axis_space','size_planning_height','size_x_axis_height',
- 'size_x_axis_space', 'y_axis_position', 'x_axis_position', 'delimiter',
+ [# kind of display : YX or XY
+ 'representation_type',
+ # number of groups over the main axis
+ 'main_axis_groups',
+ # width properties
+ 'size_border_width_left','size_planning_width','size_y_axis_space','size_y_axis_width',
+ # height properties
+ 'size_header_height', 'size_planning_height','size_x_axis_space','size_x_axis_height',
+ # axis position
+ 'y_axis_position', 'x_axis_position',
'report_root_list','selection_name',
'portal_types','sort',
'list_method',
- 'stat_method',
- 'title_line','x_start_bloc','x_stop_bloc',
- 'y_axis_method','constraint_method','split_method','color_script',
- 'round_script','sec_axis_script','info_center',
- 'info_topleft','info_topright','info_backleft','info_backright',
- 'security_index']
-
+ # method used to get title of each line
+ 'title_line',
+ # specific block properties
+ 'x_start_bloc','x_stop_bloc', 'y_size_block',
+ # name of scripts
+ 'stat_method','split_method','color_script','round_script','sec_axis_script',
+ # number of delimitations over the secondary axis
+ 'delimiter',
+ # specific methods for inserting info block
+ 'info_center', 'info_topleft','info_topright','info_backleft','info_backright'
+ ]
+
+ """
+ 'security_index'
+ # constraint method between block
+ 'constraint_method',
+ """
# Planning properties (accessed through Zope Management Interface)
@@ -620,7 +637,6 @@
required = 1)
-
default = fields.TextAreaField('default',
title='Default',
description=(
@@ -637,7 +653,6 @@
required=1)
-
report_root_list = fields.ListTextAreaField('report_root_list',
title="Report Root",
description=("A list of domains which define the possible root."),
@@ -645,36 +660,33 @@
required=0)
-
selection_name = fields.StringField('selection_name',
title='Selection Name',
description=("The name of the selection to store selections params"),
default='',
required=0)
+
portal_types = fields.ListTextAreaField('portal_types',
title="Portal Types",
description=("Portal Types of objects to list. Required."),
default=[],
required=0)
+
sort = fields.ListTextAreaField('sort',
title='Default Sort',
description=("The default sort keys and order"),
default=[],
required=0)
+
list_method = fields.MethodField('list_method',
title='List Method',
description=("Method to use to list objects"),
default='',
required=0)
- stat_method = fields.StringField('stat_method',
- title="specific method used to generate statistics:",
- description=("specific method for statistics"),
- default='',
- required=0)
title_line = fields.StringField('title_line',
title="specific method which fetches the title of each line: ",
@@ -699,10 +711,10 @@
default='stop_date',
required=0)
- y_axis_method = fields.StringField('y_axis_method',
- title='specific method of data type for creating height of blocks',
+ y_size_block = fields.StringField('y_size_block',
+ title='specific property to get height of blocks (ex.quantity)',
description=('Method for building height of blocks objects'),
- default='',
+ default='quantity',
required=0)
@@ -712,29 +724,37 @@
default='SET_DHTML',
required=1)
- split_method = fields.StringField('split_method',
- title='Method to split activities into blocks',
- description=("Method used to split activities into multiple blocks"),
+ stat_method = fields.StringField('stat_method',
+ title="name of script generating statistics:",
+ description=("script for statistics"),
default='',
required=0)
+ split_method = fields.StringField('split_method',
+ title='name of script splitting activities into blocks',
+ description=("script for splitting activities into multiple blocks"),
+ default='',
+ required=0)
+
color_script = fields.StringField('color_script',
- title='name of script which allow to colorize blocks',
+ title='name of script colorizing blocks',
description=('script for block colors object'),
default='',
required=0)
round_script = fields.StringField('round_script',
- title='name of script rounding block bounds when validating (ex. planning_roundBoundToDay)',
+ title='name of script rounding blocks during validation (ex. Planning_roundBoundToDay)',
description=('script for block bounds rounding when validating'),
default='',
required=0)
+
sec_axis_script = fields.StringField('sec_axis_script',
- title='name of script building secondary axis (ex. planning_generateAxis)',
+ title='name of script building secondary axis (ex. Planning_generateAxis)',
description=('script for building secondary axis'),
- default='planning_generateAxis',
+ default='Planning_generateAxis',
required=1)
+
info_center = fields.StringField('info_center',
title='specific method of data called for inserting info in\
@@ -831,14 +851,17 @@
# recover structure
structure = REQUEST.get('structure')
- #pdb.set_trace()
- # getting HTML rendering Page Template
- planning_html_method = getattr(REQUEST['here'],'planning_content')
-
- # recovering HTML data by calling Page Template document
- HTML_data = planning_html_method(struct=structure)
-
- return HTML_data
+ if structure != None:
+ #pdb.set_trace()
+ # getting HTML rendering Page Template
+ planning_html_method = getattr(REQUEST['here'],'planning_content')
+
+ # recovering HTML data by calling Page Template document
+ HTML_data = planning_html_method(struct=structure)
+
+ return HTML_data
+ else:
+ return 'error'
def render_structure(self, field, key, value, REQUEST, here):
@@ -885,7 +908,6 @@
#if selection.has_attribute('getParams'):
# params = selection.getParams()
-
# CALL CLASS METHODS TO BUILD BASIC STRUCTURE
# creating BasicStructure instance (and initializing its internal values)
self.basic = BasicStructure(here=here,form=form, field=field, REQUEST=REQUEST, list_method=list_method, selection=selection, params = params, selection_name=selection_name, report_root_list=report_root_list, portal_types=portal_types, sort=sort, list_error=list_error)
@@ -1040,29 +1062,15 @@
############## DEFINING STAT METHOD ##############
##################################################
# XXX implementing this new functionality
- #pdb.set_trace()
stat_method = self.field.get_value('stat_method')
-
- if hasattr(stat_method, 'method_name'):
- if stat_method.method_name == 'objectValues':
- stat_method = None # Nothing to do in this case
- show_stat = 0
- elif stat_method.method_name == 'portal_catalog':
- # We use the catalog count results
- stat_method = here.portal_catalog.countResults
- show_stat = 1
- else:
- # Try to get the method through acquisition
- try:
- stat_method = getattr(here, stat_method.method_name)
- show_stat = 1
- except (AttributeError, KeyError):
- show_stat = 0
- pass
+ #stat_method = getattr(self.REQUEST['here'],stat_method)
+ stat_method = getattr(self.here,stat_method, None)
+
+
+ if stat_method == None:
+ show_stat = 0
else:
- # No stat method defined means no statistics displayed
- stat_method = None
- show_stat = 0
+ show_stat = 1
@@ -1097,11 +1105,6 @@
report_depth=report_depth,is_report_opened=is_report_opened,
sort_on=self.selection.sort_on,form_id=self.form.id)
- # XXX fixing bug with make tree-list, unfolding reports to the 'n+1' level.
- # report_list is now built from the report_group list.
- #report_list = map(lambda s:s.getObject().getRelativeUrl(), report_tree_list)
- #self.selection.edit(report_list=report_list)
-
##################################################
########### BUILDING REPORT_GROUPS ###############
##################################################
@@ -1126,141 +1129,28 @@
- #pdb.set_trace()
- # now iterating through object_tree_list
-
-
- """
+
+ # now iterating through report_tree_list
for object_tree_line in report_tree_list:
# prepare query by defining selection report object
self.selection.edit(report = object_tree_line.getSelectDomainDict())
- #if object_tree_line.getIsPureSummary():
-
-
- if (object_tree_line.getIsPureSummary() and \
- selection_report_path=='parent'):
-
+ # defining info_dict, holding all information about the current object.
+ info_dict = None
+ info_dict = {}
+
+ if object_tree_line.getIsPureSummary() and show_stat:
+
+ info_dict['stat'] = 1
# push new select_expression
original_select_expression = kw.get('select_expression')
kw['select_expression'] = select_expression
self.selection.edit(params = kw)
- # XXX recovering statistics (will use them afterwards if necessary)
- #stat_temp = self.selection(method = stat_method, context=self.here, REQUEST=self.REQUEST)
- # pop new select_expression
- if original_select_expression is None:
- del kw['select_expression']
- else:
- kw['select_expression'] = original_select_expression
-
-
- # object_tree_line is Pure summary : does not have any activity
- stat_result = {}
- index=1
-
- # adding current line to report_section where
- # line is pure Summary
- self.report_groups += [object_tree_line]
- self.nbr_groups = self.nbr_groups + 1
-
-
- # resetting original value
- #self.selection.edit(report = None)
- else:
- # object_tree_line is not pure summary : it has activities
- # prepare query
- self.selection.edit(params = kw)
-
-
- if self.list_method not in (None,''):
- # valid list_method has been found
- self.selection.edit(exception_uid_list= \
- object_tree_line.getExceptionUidList())
- object_list = self.selection(method = self.list_method,
- context=self.here, REQUEST=self.REQUEST)
- else:
- # no list_method found
- object_list = self.here.portal_selections.getSelectionValueList(
- self.selection_name, context=self.here, REQUEST=self.REQUEST)
-
-
- exception_uid_list = object_tree_line.getExceptionUidList()
- if exception_uid_list is not None:
- # Filter folders if parent tree :
- # build new object_list for current line
- # (list of relative elements)
- new_object_list = []
- for selected_object in object_list:
- if selected_object.getUid() not in exception_uid_list:
- new_object_list.append(selected_object)
- object_list = new_object_list
-
-
- #object_list = []
- add=1
- new_list = [x.getObject() for x in object_list]
- object_list = new_list
-
- # comparing report_groups'object with object_tree_line to check
- # if the object is already present.
- # this has to be done as there seems to be a 'bug' with make_tree_list
- # returning two times the same object...
- already_in_list = 0
- for object in self.report_groups:
- if getattr(object_tree_line.getObject(),'uid') == \
- getattr(object.getObject(),'uid'): #and not(object_tree_line.getIsPureSummary()):
- # object already present, flag <= 0 to prevent new add
- already_in_list = 1
- #add=0
- break
-
- if add == 1: # testing : object not present, can add it
- # adding current line to report_section where
- # line is report_tree
- if already_in_list:
- pass
- #self.report_groups = self.report_groups[:-1]
- else:
- self.report_groups += [object_tree_line]
- self.nbr_groups += 1
- #for p_object in object_list:
- #iterating and adding each object to current_list
- # object_list.append(p_object)
- # XXX This not a good idea at all to use the title as a key of the
- # dictionnary
- self.report_activity_dict[object_tree_line.getObject().getTitle()] = object_list
-
-
- # resetting original value
- self.selection.edit(report = None)
- """
-
- # XXX just for testing
- show_stat = 0
-
- for object_tree_line in report_tree_list:
- # prepare query by defining selection report object
- self.selection.edit(report = object_tree_line.getSelectDomainDict())
-
- # defining info_dict, holding all information about the current object.
- info_dict = None
- info_dict = {}
-
- if object_tree_line.getIsPureSummary() and show_stat:
-
- info_dict['stat'] = 1
-
- # push new select_expression
- original_select_expression = kw.get('select_expression')
- kw['select_expression'] = select_expression
- self.selection.edit(params = kw)
- # XXX recovering statistics
- # need to recover a list of temporary objects
- # should be improved to take several more parameters into account
- #stat_list = self.selection(method = stat_method, context=self.here, REQUEST=self.REQUEST)
- stat_list = self.stat_method(selection= self.selection, report_tree_list=report_tree_list, object_tree_line= object_tree_line, context=self.here, REQUEST=self.REQUEST)
- # pop new select_expression
+ # recovering statistics if needed
+ # getting list of statistic blocks
+ stat_list = stat_method(selection=self.selection, list_method=self.list_method, selection_context=self.here, report_tree_list=report_tree_list, object_tree_line=object_tree_line, REQUEST=self.REQUEST, field=self.field)
+
if original_select_expression is None:
del kw['select_expression']
else:
@@ -1316,13 +1206,6 @@
pass
else:
# object is pure summary !
-
- # XXX useless as properties are recovered while creating AxisGroup
- # recovering object_line properties to display good link
- #stat_context = object_tree_line.getObject().asContext()
- #stat_context.absolute_url = object_tree_line.getObject().absolute_url()
- #stat_context.domain_url = object_tree_line.getObject().getRelativeUrl()
-
if len(object_list) and object_tree_line.is_open:
# pure summary, open, and has object_list
# case = ?!?
@@ -1347,10 +1230,7 @@
self.selection.edit(report = None)
self.selection.edit(report_list=None)
- #LOG('self.report_activity_dict',0,self.report_activity_dict)
-
-
- #pdb.set_trace()
+
# update report list if report_depth was specified
if report_depth is not None:
unfolded_list = []
@@ -1368,6 +1248,8 @@
# for main to be able to generate a 'smart' structure taking into account
# only the area that need to be rendered. This prevents from useless processing
+
+
# calculating main axis bounds
self.getMainAxisInfo(self.main_axis_info)
@@ -1397,7 +1279,6 @@
self.getSecondaryAxisInfo(self.secondary_axis_info)
-
##################################################
####### SAVING NEW PROPERTIES INTO REQUEST #######
##################################################
@@ -1421,45 +1302,6 @@
return 1
- def stat_method(self, selection=None, report_tree_list = None, object_tree_line=None, context=None, REQUEST=None):
- """
- XXX temporary function to recover statistics when needed
- returns a list with temporary objects
- """
- from Products.ERP5Type.Document import newTempBase
-
-
- # first recovering methods to apply on tasks
- start_property_id = self.field.get_value('x_start_bloc')
- stop_property_id= self.field.get_value('x_stop_bloc')
-
- # XXX need to find a way to get all related objects with their sub-objects
- # this list of objects must be stored in a list
- # for now considering applying statistics on object_list
- self.selection.edit(exception_uid_list= object_tree_line.getExceptionUidList())
- input_object_list = self.selection(method = self.list_method,context=self.here,
- REQUEST=self.REQUEST)
-
-
- temp_object_list = []
- temp_object_id = 0
- # now applying statictic rule.
- # for now statistic rules are static
- for input_object in input_object_list:
- # recovering input_object attributes
- block_begin = input_object.getObject().getProperty(start_property_id)
- block_end = input_object.getObject().getProperty(stop_property_id)
- # creating new object
- temp_object = newTempBase(context.getPortalObject(),temp_object_id)
- # editing object with new values
- setattr(temp_object,start_property_id,block_begin)
- setattr(temp_object,stop_property_id, block_end)
- # adding new object to list
- temp_object_list.append(temp_object)
- temp_object_id += 1
-
- return temp_object_list
-
def getSecondaryAxisOccurence(self):
"""
@@ -1471,49 +1313,23 @@
start_property_id = self.field.get_value('x_start_bloc')
stop_property_id= self.field.get_value('x_stop_bloc')
for (object_tree_group, object_list, info_dict) in self.report_groups:
- # recover method to et begin and end limits
-
-
- #try:
- # child_activity_list = self.report_activity_dict[object_tree_group.getObject().getTitle()]
- #except (AttributeError, KeyError):
- # child_activity_list = None
+ # recover method to get begin and end limits
#if method_start == None and child_activity_list != None:
if object_list not in (None, [], {}) :
- if not info_dict['stat']:
- for object_request in object_list:
-
- if start_property_id != None:
- block_begin = object_request.getObject().getProperty(start_property_id)
- else:
- block_begin = None
-
- if stop_property_id != None:
- block_stop = object_request.getObject().getProperty(stop_property_id)
- else:
- block_stop = None
- secondary_axis_occurence.append([block_begin,block_stop])
- else:
- # in case stat line
- for temp_object in object_list:
-
- if start_property_id != None:
- block_begin = getattr(temp_object.getObject(),start_property_id)
- else:
- block_begin = None
-
- if stop_property_id != None:
- block_stop = getattr(temp_object.getObject(),stop_property_id)
- else:
- block_stop = None
- secondary_axis_occurence.append([block_begin,block_stop])
-
+ for object_request in object_list:
+
+ if start_property_id != None:
+ block_begin = object_request.getObject().getProperty(start_property_id)
+ else:
+ block_begin = None
+
+ if stop_property_id != None:
+ block_stop = object_request.getObject().getProperty(stop_property_id)
+ else:
+ block_stop = None
+ secondary_axis_occurence.append([block_begin,block_stop])
else:
-
- #elif not info_dict['stat'] :
- # method sucessfully recovered
- # getting values
if start_property_id != None:
block_begin = object_tree_group.object.getObject().getProperty(start_property_id)
else:
@@ -1526,9 +1342,8 @@
secondary_axis_occurence.append([block_begin,block_stop])
-
-
return secondary_axis_occurence
+
def getSecondaryAxisInfo(self, axis_dict):
@@ -1538,7 +1353,6 @@
it is now possible to recover begin and end value of the planning and then
apply selection informations to get start and stop.
"""
-
axis_dict['zoom_start'] = int(self.params.get('zoom_start',0))
axis_dict['zoom_level'] = float(self.params.get('zoom_level',1))
@@ -1550,6 +1364,12 @@
axis_dict['bound_begin'] = occurence[0]
if (occurence[1] > axis_dict['bound_end'] or axis_dict['bound_end'] == None) and occurence[1] != None:
axis_dict['bound_end'] = occurence[1]
+
+ if axis_dict['bound_end']==None or axis_dict['bound_begin']==None:
+ # XXX need to handle this kind of error :
+ # no bounds over the secondary axis have been defined
+ return PlanningError(error_name,error_message)
+
axis_dict['bound_range'] = axis_dict['bound_end'] - axis_dict['bound_begin']
# now start and stop have the extreme values of the second axis bound.
# this represents in fact the size of the Planning
@@ -1577,6 +1397,7 @@
self.params['zoom_start'] = axis_dict['zoom_start']
+
def getMainAxisInfo(self, axis_dict):
"""
getting main axis properties (total pages, current page, groups per page)
@@ -1586,11 +1407,9 @@
case of report tree (if the first element is a sub group of a report for
example).
"""
-
-
axis_dict['bound_axis_groups'] = self.field.get_value('main_axis_groups')
if axis_dict['bound_axis_groups'] == None:
- #XXX raise exception : no group defined
+ #XXX raise exception : no group nb/page defined
pass
@@ -1752,10 +1571,10 @@
info_backright_method = getattr(self.object.getObject(),info_backright,None)
# if method recovered is not null, then updating
- if info_center_method!=None: info['info_center']=str(info_center_method())
- if info_topright_method!=None: info['info_topright']=str(info_topright_method())
- if info_topleft_method!=None: info['info_topleft']=str(info_topleft_method())
- if info_backleft_method!=None: info['info_backleft'] =str(info_backleft_method())
+ if info_center_method!=None: info['info_center'] =str(info_center_method())
+ if info_topright_method!=None: info['info_topright'] =str(info_topright_method())
+ if info_topleft_method!=None: info['info_topleft'] =str(info_topleft_method())
+ if info_backleft_method!=None: info['info_backleft'] =str(info_backleft_method())
if info_backright_method!=None: info['info_backright']=str(info_backright_method())
@@ -1779,12 +1598,12 @@
block_begin = None
block_end = None
if object_property_begin !=None:
- block_begin = activity_content.getObject().getProperty(object_property_begin)
+ block_begin = getattr(activity_content.getObject(),object_property_begin)
else:
block_begin = None
if object_property_end != None:
- block_end = activity_content.getObject().getProperty(object_property_end)
+ block_end = getattr(activity_content.getObject(),object_property_end)
else:
block_end = None
@@ -1814,43 +1633,68 @@
block_stop = block_end
# defining name
- name = "Activity_%s_%s" % (self.object.getObject().getTitle(),str(indic))
-
- # getting info text from activity itself if exists
- info_center_method = getattr(activity_content,info_center,None)
- info_topright_method = getattr(activity_content,info_topright,None)
- info_topleft_method = getattr(activity_content,info_topleft,None)
- info_backleft_method = getattr(activity_content,info_backleft,None)
- info_backright_method = getattr(activity_content,info_backright,None)
-
- # if value recovered is not null, then updating
- if info_center_method!=None: info['info_center']=str(info_center_method())
- if info_topright_method!=None: info['info_topright']=str(info_topright_method())
- if info_topleft_method!=None: info['info_topleft']=str(info_topleft_method())
- if info_backleft_method!=None: info['info_backleft'] =str(info_backleft_method())
- if info_backright_method!=None: info['info_backright']=str(info_backright_method())
-
- color_script = getattr(activity_content.getObject(), self.field.get_value('color_script'),None)
- # calling color script if exists to set up activity_color
+ #name = "Activity_%s_%s" % (self.object.getObject().getTitle(),str(indic))
+ name = "Activity_%s" % (str(indic))
+
+ error = 'false'
current_color=''
- if color_script !=None:
- current_color = color_script(activity_content.getObject())
-
- # testing if some activities have errors
- error = 'false'
- if list_error not in (None, []):
- for activity_error in list_error:
- if activity_error[0][0] == name:
- error = 'true'
- break
-
- stat_result = {}
- stat_context = activity_content.getObject().asContext(**stat_result)
- stat_context.domain_url = activity_content.getObject().getRelativeUrl()
- stat_context.absolute_url = lambda x: activity_content.getObject().absolute_url()
+
+ if self.property_dict['stat'] == 1:
+ info = None
+ info = {}
+ info['info_center'] = ''
+ info['info_topright'] = ''
+ info['info_topleft'] = ''
+ info['info_backleft'] = ''
+ info['info_backright'] = ''
+ title = ''
+ object = activity_content
+ url=''
+ object_property_height = self.field.get_value('y_size_block')
+ height = getattr(activity_content.getObject(),object_property_height)
+ else:
+ info = None
+ info = {}
+ # getting info text from activity itself if exists
+ info_center_method = getattr(activity_content,info_center,None)
+ info_topright_method = getattr(activity_content,info_topright,None)
+ info_topleft_method = getattr(activity_content,info_topleft,None)
+ info_backleft_method = getattr(activity_content,info_backleft,None)
+ info_backright_method = getattr(activity_content,info_backright,None)
+
+ # if value recovered is not null, then updating
+ if info_center_method!=None: info['info_center']=str(info_center_method())
+ if info_topright_method!=None: info['info_topright']=str(info_topright_method())
+ if info_topleft_method!=None: info['info_topleft']=str(info_topleft_method())
+ if info_backleft_method!=None: info['info_backleft'] =str(info_backleft_method())
+ if info_backright_method!=None: info['info_backright']=str(info_backright_method())
+
+ title = info['info_center']
+
+ color_script = getattr(activity_content.getObject(), self.field.get_value('color_script'),None)
+ # calling color script if exists to set up activity_color
+ if color_script !=None:
+ current_color = color_script(activity_content.getObject())
+
+ # testing if some activities have errors
+ if list_error not in (None, []):
+ for activity_error in list_error:
+ if activity_error[0][0] == name:
+ error = 'true'
+ break
+
+ stat_result = {}
+ stat_context = activity_content.getObject().asContext(**stat_result)
+ stat_context.domain_url = activity_content.getObject().getRelativeUrl()
+ stat_context.absolute_url = lambda x: activity_content.getObject().absolute_url()
+ object = stat_context.getObject()
+ url = stat_context.getUrl()
+
+ # XXX should define height of block here
+ height = None
# creating new activity instance
- activity = BasicActivity(title=info['info_center'],name=name,object = stat_context.getObject(), url=stat_context.getUrl(),absolute_begin=block_begin, absolute_end=block_end, absolute_start = block_start, absolute_stop = block_stop, color = current_color, info_dict=info, error=error)
+ activity = BasicActivity(title=title, name=name, object=object, url=url, absolute_begin=block_begin, absolute_end=block_end, absolute_start=block_start, absolute_stop=block_stop, height = height, color=current_color, info_dict=info, error=error, property_dict=self.property_dict)
# adding new activity to personal group activity list
@@ -1863,8 +1707,6 @@
# group (used for Activity naming)
indic += 1
- info = None
- info = {}
else:
@@ -1924,8 +1766,11 @@
# defining name
name = "Activity_%s" % (self.object.getObject().getTitle())
+ # height should be implemented here
+ height = None
+
# creating new activity instance
- activity = BasicActivity(title=info['info_center'], name=name, object = self.object.object, url=self.url, absolute_begin=block_begin, absolute_end=block_end, absolute_start=block_start, absolute_stop=block_stop,color = current_color, info_dict=info, error=error)
+ activity=BasicActivity(title=info['info_center'], name=name, object=self.object.object, url=self.url, absolute_begin=block_begin, absolute_end=block_end, absolute_start=block_start, absolute_stop=block_stop, height=height, color=current_color, info_dict=info, error=error, property_dict=self.property_dict)
# adding new activity to personal group activity list
try:
@@ -1943,7 +1788,7 @@
nothing about multitask rendering. """
def __init__ (self, title='', name='',object = None, url='', absolute_begin=None,
- absolute_end=None,absolute_start=None,absolute_stop=None, constraints='', color=None, error='false', info_dict= None):
+ absolute_end=None,absolute_start=None,absolute_stop=None, height=None, constraints='', color=None, error='false', info_dict= None, property_dict = {}):
self.title = title
self.name = name
self.object = object
@@ -1953,10 +1798,12 @@
self.absolute_end = absolute_end
self.absolute_start = absolute_start
self.absolute_stop = absolute_stop
+ self.height = height
self.constraints = constraints# constraints specific to the current Activity
self.color = color
self.info_dict = info_dict
self.error = error
+ self.property_dict = property_dict # dict containing specific properties
@@ -1969,7 +1816,7 @@
"""
- def __init__ (self,):
+ def __init__ (self):
self.main_axis = ''
self.secondary_axis = ''
self.content = []
@@ -2056,10 +1903,7 @@
# just need to pass start, stop, and the minimum number of delimiter wanted.
# a structure is returned : list of delimiters, each delimiter defined by a
# list [ relative position, title, tooltip , delimiter_type]
-
delimiter_list = axis_script(axis_start,axis_stop,delimiter_min_number)
-
-
axis_stop = int(axis_stop)
axis_start = int(axis_start)
@@ -2131,10 +1975,11 @@
build groups from activities saved in the structure groups.
"""
axis_group_number = 0
+ #pdb.set_trace()
axis_element_already_present=0
for basic_group_object in basic_structure.basic_group_list:
axis_group_number += 1
- axis_group = AxisGroup(name='Group_' + str(axis_group_number), title=basic_group_object.title, object = basic_group_object.object, axis_group_number = axis_group_number, is_open=basic_group_object.is_open, is_pure_summary=basic_group_object.is_pure_summary, url = basic_group_object.url,depth = basic_group_object.depth, secondary_axis_start= self.secondary_axis.start, secondary_axis_stop= self.secondary_axis.stop)
+ axis_group = AxisGroup(name='Group_' + str(axis_group_number), title=basic_group_object.title, object = basic_group_object.object, axis_group_number = axis_group_number, is_open=basic_group_object.is_open, is_pure_summary=basic_group_object.is_pure_summary, url = basic_group_object.url,depth = basic_group_object.depth, secondary_axis_start= self.secondary_axis.start, secondary_axis_stop= self.secondary_axis.stop, property_dict = basic_group_object.property_dict)
if self.render_format == 'YX':
axis_group.position_y = axis_group.position_main
axis_group.position_x = axis_group.position_secondary
@@ -2155,12 +2000,25 @@
if basic_group_object.basic_activity_list != None:
# need to check if activity list is not empty : possible in case zoom
# selection is used over the secondary axis
- for basic_activity_object in basic_group_object.basic_activity_list:
- activity_number += 1
- # create new activity in the PlanningStructure
- activity = Activity(name='Group_' + str(axis_group_number) + '_Activity_' + str(activity_number), title=basic_activity_object.title, object=basic_activity_object.object, color=basic_activity_object.color, link=basic_activity_object.url, secondary_axis_begin=basic_activity_object.absolute_begin, secondary_axis_end=basic_activity_object.absolute_end, secondary_axis_start=basic_activity_object.absolute_start, secondary_axis_stop=basic_activity_object.absolute_stop, primary_axis_block=self, info=basic_activity_object.info_dict, render_format=self.render_format)
- # adding activity to the current group
- axis_group.addActivity(activity,axis_element_already_present)
+ if axis_group.property_dict['stat'] == 0:
+ # case group is task group. Using default method that
+ # generates automatically the necessary axis elements
+ for basic_activity_object in basic_group_object.basic_activity_list:
+ activity_number += 1
+ # create new activity in the PlanningStructure
+ activity = Activity(name='Group_' + str(axis_group_number) + '_Activity_' + str(activity_number), title=basic_activity_object.title, object=basic_activity_object.object, color=basic_activity_object.color, link=basic_activity_object.url, secondary_axis_begin=basic_activity_object.absolute_begin, secondary_axis_end=basic_activity_object.absolute_end, secondary_axis_start=basic_activity_object.absolute_start, secondary_axis_stop=basic_activity_object.absolute_stop, primary_axis_block=self, info=basic_activity_object.info_dict, render_format=self.render_format, property_dict = basic_group_object.property_dict)
+ # adding activity to the current group
+ axis_group.addActivity(activity,axis_element_already_present)
+ else:
+ # case group is stat group. Using special method that prevent
+ # from generating more than 1 axis element and divide tasks size if
+ # necessary
+ axis_group.addStatActivities(basic_activity_list=basic_group_object.basic_activity_list,
+ axis_group_number=axis_group_number,
+ axis_element_already_present = axis_element_already_present,
+ render_format = self.render_format,
+ primary_axis_block=self,
+ property_dict = basic_group_object.property_dict)
else:
# basic_activity_list is empty : need to add a empty axis_element to
# prevent bug or crash
@@ -2191,18 +2049,22 @@
error_block_list = REQUEST.get('error_block_list',[])
error_info_dict = REQUEST.get('error_info_dict',{})
-
- try:
- for axis_group_object in self.main_axis.axis_group:
- for axis_element_object in axis_group_object.axis_element_list:
- for activity in axis_element_object.activity_list:
- if activity.name in warning_activity_list:
- warning = 1
- else:
- warning = 0
- activity.addBlocs(main_axis_start=0, main_axis_stop=self.main_axis.size, secondary_axis_start=self.secondary_axis.start, secondary_axis_stop=self.secondary_axis.stop,planning=self, warning=warning, error_block_list=error_block_list, error_info_dict=error_info_dict)
- except TypeError:
- pass
+
+
+ for axis_group_object in self.main_axis.axis_group:
+ for axis_element_object in axis_group_object.axis_element_list:
+ for activity in axis_element_object.activity_list:
+ if activity.name in warning_activity_list:
+ warning = 1
+ else:
+ warning = 0
+ # generate activity_info
+ activity.addBlocs(main_axis_start=0, main_axis_stop=self.main_axis.size, secondary_axis_start=self.secondary_axis.start, secondary_axis_stop=self.secondary_axis.stop,planning=self, warning=warning, error_block_list=error_block_list, error_info_dict=error_info_dict)
+ if axis_group_object.property_dict['stat'] == 1:
+ # case stat group_object, need to update block size to display
+ # stats informations
+ axis_group_object.updateStatBlocks()
+
@@ -2216,7 +2078,7 @@
structure is used for rebuilding tasks from bloc positions when
validating the Planning.
"""
- def __init__ (self,name=None, title=None, object=None, types=None, color=None, link=None, secondary_axis_begin=None, secondary_axis_end=None, secondary_axis_start=None, secondary_axis_stop=None, primary_axis_block=None, info=None, render_format='YX'):
+ def __init__ (self,name=None, title=None, object=None, types=None, color=None, link=None, height=None, secondary_axis_begin=None, secondary_axis_end=None, secondary_axis_start=None, secondary_axis_stop=None, primary_axis_block=None, info=None, render_format='YX', property_dict={} ):
self.name = name # internal activity_name
self.id = self.name
self.title = title # displayed activity_name
@@ -2224,6 +2086,7 @@
self.types = types # activity, activity_error, info
self.color = color # color used to render all Blocs
self.link = link # link to the ERP5 object
+ self.height = height
# self.constraints = constraints
self.block_list = None # contains all the blocs used to render the activity
self.secondary_axis_begin =secondary_axis_begin
@@ -2235,11 +2098,12 @@
self.info = info
self.parent_axis_element = None
self.render_format= render_format
+ self.property_dict = property_dict
def get_error_message (self, Error):
# need to update the error message
- return 'et paf, à coté de la ligne !'
+ return 'task %s (%s)not validated' % (self.name, self.title)
def isValidPosition(self, bound_begin, bound_end):
@@ -2255,7 +2119,6 @@
return 1
else:
return 2
-
def addBlocs(self, main_axis_start=None, main_axis_stop=None, secondary_axis_start=None, secondary_axis_stop=None,planning=None, warning=0, error_block_list=[], error_info_dict={}):
"""
@@ -2275,7 +2138,6 @@
block_number = 0
# iterating resulting list
- #pdb.set_trace()
for (start,stop,zone) in secondary_block_bounds:
block_number += 1
@@ -2290,16 +2152,21 @@
error = 0
error_text=''
-
- block_color = self.color
- block_link = self.link
- #if zone == 1:
- # block_color = ''
- # block_link = self.link
- #else:
- # block_color = '#D1E8FF'
- # block_link = ''
- new_block = Bloc(name= block_name,color=block_color,link=block_link, number = block_number, render_format=self.render_format, parent_activity=self, warning=warning, error=error, error_text=error_text,zone=zone)
+ # zone property is used to check if block is a representative block or a
+ # display block. This value is associaded to each block returned through
+ # the splitActivity function.
+ # representative => standard block representing an active part of the task
+ # display => block representing a passive part of the task (week end, etc.)
+ if zone == 1:
+ # active
+ block_color = self.color
+ block_link = self.link
+ else:
+ # passive
+ block_color = '#D1E8FF'
+ block_link = ''
+
+ new_block = Bloc(name= block_name,color=block_color,link=block_link, number = block_number, render_format=self.render_format, parent_activity=self, warning=warning, error=error, error_text=error_text,zone=zone, property_dict = self.property_dict)
new_block.buildInfoDict(info_dict = self.info)
@@ -2376,7 +2243,6 @@
# defining usefull list of data
break_list = ['Saturday','Sunday']
worked_list = ['Monday','Tuesday','Wednesday','Thursday','Friday']
- switch_list = ['Monday','Saturday']
if temp_start.Day() in break_list:
# temp_start is in weekend,
@@ -2435,7 +2301,7 @@
color=None, info=None, link=None, number=0,
constraints=None, secondary_start=None, secondary_stop=None,
render_format='YX', parent_activity = None, warning=0, error=0,
- error_text='', zone=1):
+ error_text='', zone=1, property_dict ={} ):
"""
creates a Bloc object
"""
@@ -2446,7 +2312,7 @@
self.link = link # on clic link
self.number = number
self.title=''
- self.zone = zone
+ self.zone = zone # 1 = usefull area : 0 = useless one => splitting activities
self.parent_activity = parent_activity
self.constraints = constraints
# setting warning and error flags in case parent_activity or block itself
@@ -2467,22 +2333,29 @@
self.position_y = self.position_secondary
self.position_x = self.position_main
self.render_dict = None
+ self.property_dict = property_dict # dict containing internal properties
def buildInfoDict (self, info_dict=[]):
"""
create Info objects to display text & images, then link them to the current object
"""
#XXX /4
- self.info = {}
- title_list = []
-
- title_list.append(self.buildInfo(info_dict=info_dict, area='info_topleft'))
- title_list.append(self.buildInfo(info_dict=info_dict, area='info_topright'))
- title_list.append(self.buildInfo(info_dict=info_dict, area='info_center'))
- title_list.append(self.buildInfo(info_dict=info_dict, area='info_botleft'))
- title_list.append(self.buildInfo(info_dict=info_dict, area='info_botright'))
+
# updating title
- self.title = " | ".join(title_list)
+ if self.property_dict['stat'] == 1:
+ self.title = str(self.parent_activity.height)
+ self.info = None
+ else:
+ self.info = {}
+ title_list = []
+ title_list.append(self.buildInfo(info_dict=info_dict, area='info_topleft'))
+ title_list.append(self.buildInfo(info_dict=info_dict, area='info_topright'))
+ title_list.append(self.buildInfo(info_dict=info_dict, area='info_center'))
+ title_list.append(self.buildInfo(info_dict=info_dict, area='info_botleft'))
+ title_list.append(self.buildInfo(info_dict=info_dict, area='info_botright'))
+ self.title = " | ".join(title_list)
+
+
if self.error != 0:
# field has error
# adding text_error
@@ -2559,7 +2432,7 @@
def __init__ (self, name='', title='', object = None,
axis_group_list=None, axis_group_number=0,
- axis_element_list=None, axis_element_number=0, delimiter_type = 0, is_open=0, is_pure_summary=1,depth=0, url=None, axis_element_already_insered= 0, secondary_axis_start=None, secondary_axis_stop=None):
+ axis_element_list=None, axis_element_number=0, delimiter_type = 0, is_open=0, is_pure_summary=1,depth=0, url=None, axis_element_already_insered= 0, secondary_axis_start=None, secondary_axis_stop=None, property_dict={}):
self.name = name
self.title = title
self.link = None # link to fold or unfold current report in report-tree mode
@@ -2590,6 +2463,7 @@
# calendar output( were each axis_group has its own start and stop)
self.secondary_axis_start = secondary_axis_start
self.secondary_axis_stop = secondary_axis_stop
+ self.property_dict = property_dict
security = ClassSecurityInfo()
@@ -2615,15 +2489,15 @@
#for i in range(self.depth):
# self.title = '| ' + self.title
self.info_title.title = self.info_title.info
-
+
self.tooltip = self.info_title.info
def addActivity(self, activity=None, axis_element_already_insered= 0):
"""
- procedure that permits to add activity to the corresponding AxisElement.
- can create new Axis Element in the actual Axisgroup if necessary.
- Permits representation of MULTITASKING
+ procedure that permits to add activity to the corresponding AxisElement in
+ an AxisGroup. can create new Axis Element in the actual Axisgroup if
+ necessary. Permits representation of MULTITASKING
"""
# declaring variable used to check if activity has already been added
@@ -2691,6 +2565,84 @@
# register the axis_element to the actual group.
self.axis_element_list = []
self.axis_element_list.append(new_axis_element)
+
+
+ def addStatActivities(self, basic_activity_list=None, axis_group_number=0, axis_element_already_present= 0, render_format=None, primary_axis_block=None, property_dict={}):
+ """
+ Permits to add stat block to the current AxisGroup. In this way use the
+ single AxisElement present to fit the blocks
+ """
+ # first adding axis_element to the current group
+ self.axis_element_number += 1
+ new_axis_element=AxisElement(name='Group_' + str(self.axis_group_number) + '_AxisElement_1', relative_number=self.axis_element_number, absolute_number=axis_element_already_present + self.axis_element_number, parent_axis_group=self)
+ new_axis_element.activity_list = []
+
+ self.axis_element_list = []
+ self.axis_element_list.append(new_axis_element)
+
+ activity_number = 0
+ # add all activities to the same axis_element
+ for basic_activity_object in basic_activity_list:
+
+ # defining Activity from basic_activity_object
+ activity = Activity(name= 'Group_%s_Activity_%s' %(str(axis_group_number),
+ str(activity_number)),
+ title=basic_activity_object.title,
+ object=basic_activity_object.object,
+ color=basic_activity_object.color,
+ link=basic_activity_object.url,
+ secondary_axis_begin=basic_activity_object.absolute_begin,
+ secondary_axis_end=basic_activity_object.absolute_end,
+ secondary_axis_start=basic_activity_object.absolute_start,
+ secondary_axis_stop=basic_activity_object.absolute_stop,
+ height=basic_activity_object.height,
+ primary_axis_block=primary_axis_block,
+ info=basic_activity_object.info_dict,
+ render_format=render_format,
+ property_dict = property_dict)
+ activity.parent_axis_element = new_axis_element
+
+ # append activity to current axis_element
+ new_axis_element.activity_list.append(activity)
+
+ activity_number +=1
+
+
+ def updateStatBlocks(self):
+ """
+ called once the blocks have been defined on all activities
+ if the current group is stat group, then this method is called
+ process :
+ - find the largest element to display
+ - update size of all other elements
+ """
+ # usually should get only 1 axis_element : all stats are displayed on the
+ # same line.
+ max_activity_height = 0
+ for activity in self.axis_element_list[0].activity_list:
+ if activity.height > max_activity_height:
+ max_activity_height = activity.height
+
+ # now max height is known, just need to adapt size of all the blocks
+ # composing the activities
+ for activity in self.axis_element_list[0].activity_list:
+ if activity.height in (0,None):
+ relative_size = 1
+ else:
+ relative_size = float(activity.height) / max_activity_height
+ for block in activity.block_list:
+ # recovering original values
+ block_range = block.position_main.relative_range
+ block_begin = block.position_main.relative_begin
+ block_end = block.position_main.relative_end
+ # calculating values
+ final_range = relative_size * block_range
+ final_loss = block_range - final_range
+ final_begin = block_begin + final_loss
+ # saving new values
+ block.position_main.relative_begin = final_begin
+ block.position_main.relative_range = final_range
+
class AxisElement:
More information about the Erp5-report
mailing list