Commit 11096b11 authored by Thomas Bernard's avatar Thomas Bernard

Updates PlanningBox properties : it is now possible to update directly

all PlanningBox Properties through the /manage interface
Updates Report group processing to handle multi acivities per group
Implements support for multilines display in case several actiities are
rendered per group
Corrects block text display : do not use Group properties but acivity
properties instead
Updates Validator to handle modifications over multitasking


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@7058 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 2a3105de
...@@ -42,6 +42,7 @@ from Products.Formulator.Field import ZMIField ...@@ -42,6 +42,7 @@ from Products.Formulator.Field import ZMIField
from Products.Formulator.DummyField import fields from Products.Formulator.DummyField import fields
from Products.Formulator.MethodField import BoundMethod from Products.Formulator.MethodField import BoundMethod
from DateTime import DateTime from DateTime import DateTime
#import DateUtils
from Products.Formulator import Widget, Validator from Products.Formulator import Widget, Validator
from Products.Formulator.Errors import FormValidationError, ValidationError from Products.Formulator.Errors import FormValidationError, ValidationError
from SelectionTool import makeTreeList,TreeListLine from SelectionTool import makeTreeList,TreeListLine
...@@ -80,7 +81,7 @@ class PlanningBoxValidator(Validator.StringBaseValidator): ...@@ -80,7 +81,7 @@ class PlanningBoxValidator(Validator.StringBaseValidator):
old_delta1 = REQUEST.get('old_delta1') old_delta1 = REQUEST.get('old_delta1')
old_delta2 = REQUEST.get('old_delta2') old_delta2 = REQUEST.get('old_delta2')
#pdb.set_trace()
################################################## ##################################################
############## REBUILD STRUCTURE ################# ############## REBUILD STRUCTURE #################
...@@ -231,7 +232,7 @@ class PlanningBoxValidator(Validator.StringBaseValidator): ...@@ -231,7 +232,7 @@ class PlanningBoxValidator(Validator.StringBaseValidator):
# XXX call specific external method to round value in case hh:mn:s are useless # XXX call specific external method to round value in case hh:mn:s are useless
# saving updating informations in the final dict # saving updating informations in the final dict
update_dict[activity_object.link]={'start_date':new_bounds[0],'stop_date':new_bounds[1]} update_dict[activity_object.object.getUrl()]={'start_date':new_bounds[0],'stop_date':new_bounds[1]}
# all process is now finished, just need to return final dict # all process is now finished, just need to return final dict
return update_dict return update_dict
...@@ -366,11 +367,12 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -366,11 +367,12 @@ class PlanningBoxWidget(Widget.Widget):
property_names = Widget.Widget.property_names +\ property_names = Widget.Widget.property_names +\
['height_header', 'height_global_div','height_axis_x', 'width_line', ['representation_type','main_axis_groups','size_header_height', 'size_border_width_left',
'space_line','list_method','report_root_list','selection_name', 'size_planning_width', 'size_y_axis_width','size_y_axis_space','size_planning_height','size_x_axis_height',
'portal_types','sort','title_line','y_unity','y_axis_width', 'size_x_axis_space'
'y_range','x_range','x_axis_script_id','x_start_bloc','x_stop_bloc', ,'list_method','report_root_list','selection_name',
'y_axis_method','max_y','constraint_method','color_script','info_center', 'portal_types','sort','title_line','x_start_bloc','x_stop_bloc',
'y_axis_method','constraint_method','color_script','info_center',
'info_topleft','info_topright','info_backleft','info_backright', 'info_topleft','info_topright','info_backleft','info_backright',
'security_index'] 'security_index']
...@@ -379,10 +381,10 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -379,10 +381,10 @@ class PlanningBoxWidget(Widget.Widget):
# kind of representation to render : # kind of representation to render :
# Planning or Calendar # Planning or Calendar
representation_type = fields.Stringfield('representation_type', representation_type = fields.TextAreaField('representation_type',
title='', title='representtion Type (YX or XY)',
description='', description='YX for horizontal or XY for vertical',
default='Planning', default='YX',
required=1) required=1)
# added especially for new Planning Structure generation # added especially for new Planning Structure generation
...@@ -492,8 +494,6 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -492,8 +494,6 @@ class PlanningBoxWidget(Widget.Widget):
default=50, default=50,
required=1) required=1)
width_line = fields.IntegerField('width_line', width_line = fields.IntegerField('width_line',
title='width of the graphic (px):', title='width of the graphic (px):',
description=( description=(
...@@ -507,12 +507,16 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -507,12 +507,16 @@ class PlanningBoxWidget(Widget.Widget):
default=10, default=10,
required=0) required=0)
report_root_list = fields.ListTextAreaField('report_root_list', report_root_list = fields.ListTextAreaField('report_root_list',
title="Report Root", title="Report Root",
description=("A list of domains which define the possible root."), description=("A list of domains which define the possible root."),
default=[], default=[],
required=0) required=0)
selection_name = fields.StringField('selection_name', selection_name = fields.StringField('selection_name',
title='Selection Name', title='Selection Name',
description=("The name of the selection to store selections params"), description=("The name of the selection to store selections params"),
...@@ -672,18 +676,17 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -672,18 +676,17 @@ class PlanningBoxWidget(Widget.Widget):
relative to the structure that need to be rendered relative to the structure that need to be rendered
""" """
#pdb.set_trace()
# build structure # build structure
here = REQUEST['here'] here = REQUEST['here']
structure = self.render_structure(field=field, key=key, value=value, REQUEST=REQUEST, here=here) structure = self.render_structure(field=field, key=key, value=value, REQUEST=REQUEST, here=here)
if structure != None:
# getting CSS script generator # getting CSS script generator
planning_css_method = getattr(REQUEST['here'],'planning_css') planning_css_method = getattr(REQUEST['here'],'planning_css')
# recover CSS data buy calling DTML document # recover CSS data buy calling DTML document
#pdb.set_trace()
CSS_data = planning_css_method(structure=structure) CSS_data = planning_css_method(structure=structure)
# saving structure inside the request to be able to recover it afterwards when needing # saving structure inside the request to be able to recover it afterwards when needing
...@@ -692,6 +695,9 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -692,6 +695,9 @@ class PlanningBoxWidget(Widget.Widget):
# return CSS data # return CSS data
return CSS_data return CSS_data
else:
REQUEST.set('structure',None)
return None
def render(self,field,key,value,REQUEST): def render(self,field,key,value,REQUEST):
""" """
...@@ -707,7 +713,6 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -707,7 +713,6 @@ class PlanningBoxWidget(Widget.Widget):
structure = REQUEST.get('structure') structure = REQUEST.get('structure')
#pdb.set_trace() #pdb.set_trace()
if structure != None:
# getting HTML rendering Page Template # getting HTML rendering Page Template
planning_html_method = getattr(REQUEST['here'],'planning_content') planning_html_method = getattr(REQUEST['here'],'planning_content')
...@@ -762,12 +767,15 @@ class PlanningBoxWidget(Widget.Widget): ...@@ -762,12 +767,15 @@ class PlanningBoxWidget(Widget.Widget):
#if selection.has_attribute('getParams'): #if selection.has_attribute('getParams'):
# params = selection.getParams() # params = selection.getParams()
# CALL CLASS METHODS TO BUILD BASIC STRUCTURE # CALL CLASS METHODS TO BUILD BASIC STRUCTURE
# creating BasicStructure instance (and initializing its internal values) # 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) 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)
# call build method to generate BasicStructure # call build method to generate BasicStructure
self.basic.build() returned_value = self.basic.build()
if returned_value == None:
# in case group list is empty
return None
# CALL CLASS METHODS TO BUILD PLANNING STRUCTURE # CALL CLASS METHODS TO BUILD PLANNING STRUCTURE
# creating PlanningStructure instance and initializing its internal values # creating PlanningStructure instance and initializing its internal values
...@@ -877,12 +885,11 @@ class BasicStructure: ...@@ -877,12 +885,11 @@ class BasicStructure:
del kw['select_expression'] del kw['select_expression']
if hasattr(self.list_method, 'method_name'): if hasattr(self.list_method, 'method_name'):
if self.list_method.method_name == 'ObjectValues': if self.list_method.method_name == 'ObjectValues':
# list_method is available # list_method is available
self.list_method = self.here.objectValues self.list_method = self.here.objectValues
kw = copy(params) kw = copy(self.params)
else: else:
# building a complex query so we should not pass too many variables # building a complex query so we should not pass too many variables
kw={} kw={}
...@@ -1028,30 +1035,41 @@ class BasicStructure: ...@@ -1028,30 +1035,41 @@ class BasicStructure:
new_object_list.append(selected_object) new_object_list.append(selected_object)
object_list = new_object_list object_list = new_object_list
object_list = [] #object_list = []
add=1 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 # comparing report_groups'object with object_tree_line to check
# if the object is already present. # if the object is already present.
# this has to be done as there seems to be a 'bug' with make_tree_list # this has to be done as there seems to be a 'bug' with make_tree_list
# returning two times the same object... # returning two times the same object...
already_in_list = 0
for object in self.report_groups: for object in self.report_groups:
if getattr(object_tree_line.getObject(),'uid') == \ if getattr(object_tree_line.getObject(),'uid') == \
getattr(object.getObject(),'uid'): getattr(object.getObject(),'uid') and \
not(object_tree_line.getIsPureSummary()):
# object already present, flag <= 0 to prevent new add # object already present, flag <= 0 to prevent new add
add=0 already_in_list = 1
#add=0
break break
#pdb.set_trace()
if add == 1: # testing : object not present, can add it if add == 1: # testing : object not present, can add it
# adding current line to report_section where # adding current line to report_section where
# line is report_tree # line is report_tree
if already_in_list:
self.report_groups = self.report_groups[:-1]
self.report_groups += [object_tree_line] self.report_groups += [object_tree_line]
self.nbr_groups += 1 self.nbr_groups += 1
for p_object in object_list: #for p_object in object_list:
#iterating and adding each object to current_list #iterating and adding each object to current_list
object_list.append(p_object) # 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 self.report_activity_dict[object_tree_line.getObject().getTitle()] = object_list
self.selection.edit(report=None) self.selection.edit(report=None)
LOG('self.report_activity_dict',0,self.report_activity_dict)
################################################## ##################################################
...@@ -1065,8 +1083,13 @@ class BasicStructure: ...@@ -1065,8 +1083,13 @@ class BasicStructure:
self.getMainAxisInfo(self.main_axis_info) self.getMainAxisInfo(self.main_axis_info)
# applying main axis selection # applying main axis selection
if self.report_groups != []:
self.report_groups = self.report_groups[self.main_axis_info['bound_start']: self.report_groups = self.report_groups[self.main_axis_info['bound_start']:
self.main_axis_info['bound_stop']] self.main_axis_info['bound_stop']]
else:
# XXX need to handle this kind of error:
# no group is available so the Y and X axis will be empty...
return None
################################################## ##################################################
...@@ -1105,6 +1128,9 @@ class BasicStructure: ...@@ -1105,6 +1128,9 @@ class BasicStructure:
# be built # be built
self.buildGroupStructure() self.buildGroupStructure()
# everything is fine
return 1
def getSecondaryAxisOccurence(self): def getSecondaryAxisOccurence(self):
""" """
...@@ -1121,13 +1147,17 @@ class BasicStructure: ...@@ -1121,13 +1147,17 @@ class BasicStructure:
method_stop = getattr(object_tree_group.getObject(),stop_method_id,None) method_stop = getattr(object_tree_group.getObject(),stop_method_id,None)
try: try:
child_activity_list = self.report_activity_dict[object_tree_group.title] child_activity_list = self.report_activity_dict[object_tree_group.getObject().getTitle()]
except AttributeError: except AttributeError:
child_activity_list = None child_activity_list = None
if method_start == None and child_activity_list != None: #if method_start == None and child_activity_list != None:
if child_activity_list != None:
# can not recover method from object_tree_group itself, trying # can not recover method from object_tree_group itself, trying
# over the activity list # over the activity list
# XXX in fact can not fail to recover method from object_tree_group
# get : <bound method ImplicitAcquirerWrapper.(?) of <Project at /erp5/project_module/planning>>
# so just trying if children exist
for child_activity in child_activity_list: for child_activity in child_activity_list:
method_start = getattr(child_activity,start_method_id,None) method_start = getattr(child_activity,start_method_id,None)
method_stop = getattr(child_activity,stop_method_id,None) method_stop = getattr(child_activity,stop_method_id,None)
...@@ -1179,9 +1209,9 @@ class BasicStructure: ...@@ -1179,9 +1209,9 @@ class BasicStructure:
axis_dict['bound_begin'] = self.secondary_axis_occurence[0][0] axis_dict['bound_begin'] = self.secondary_axis_occurence[0][0]
axis_dict['bound_end'] = axis_dict['bound_begin'] axis_dict['bound_end'] = axis_dict['bound_begin']
for occurence in self.secondary_axis_occurence: for occurence in self.secondary_axis_occurence:
if occurence[0] < axis_dict['bound_begin']: if (occurence[0] < axis_dict['bound_begin'] or axis_dict['bound_begin'] == None) and occurence[0] != None:
axis_dict['bound_begin'] = occurence[0] axis_dict['bound_begin'] = occurence[0]
if occurence[1] > axis_dict['bound_end']: if (occurence[1] > axis_dict['bound_end'] or axis_dict['bound_end'] == None) and occurence[1] != None:
axis_dict['bound_end'] = occurence[1] axis_dict['bound_end'] = occurence[1]
axis_dict['bound_range'] = axis_dict['bound_end'] - axis_dict['bound_begin'] 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. # now start and stop have the extreme values of the second axis bound.
...@@ -1221,11 +1251,10 @@ class BasicStructure: ...@@ -1221,11 +1251,10 @@ class BasicStructure:
""" """
#pdb.set_trace() #pdb.set_trace()
# recovering number of groups displayed per page axis_dict['bound_axis_groups'] = self.field.get_value('main_axis_groups')
axis_dict['bound_axis_groups'] = self.REQUEST.get('list_lines',None)
if axis_dict['bound_axis_groups'] == None: if axis_dict['bound_axis_groups'] == None:
# XXX default value is 10: #XXX raise exception : no group defined
axis_dict['bound_axis_groups'] = self.params.get('list_lines',10) pass
# setting begin & end bounds # setting begin & end bounds
...@@ -1302,7 +1331,7 @@ class BasicStructure: ...@@ -1302,7 +1331,7 @@ class BasicStructure:
# first recovering activity list if exists # first recovering activity list if exists
report_activity_list = [] report_activity_list = []
if title in self.report_activity_dict.keys(): if title in self.report_activity_dict.keys():
report_activity_list = self.report_activity_dict[child_group.title] report_activity_list = self.report_activity_dict[title]
# linking activities to the bloc. the parameter is a list of elements # linking activities to the bloc. the parameter is a list of elements
# to link to the child_group object. # to link to the child_group object.
child_group.setBasicActivities(report_activity_list,self.list_error,self.secondary_axis_info) child_group.setBasicActivities(report_activity_list,self.list_error,self.secondary_axis_info)
...@@ -1314,8 +1343,6 @@ class BasicStructure: ...@@ -1314,8 +1343,6 @@ class BasicStructure:
self.basic_group_list.append(child_group) self.basic_group_list.append(child_group)
class BasicGroup: class BasicGroup:
""" """
A BasicGroup holds informations about an ERP5Object and is stored A BasicGroup holds informations about an ERP5Object and is stored
...@@ -1328,7 +1355,7 @@ class BasicGroup: ...@@ -1328,7 +1355,7 @@ class BasicGroup:
ReportTree mode to handle child groups. ReportTree mode to handle child groups.
""" """
def __init__ (self, title='', name='', url='', constraints='', depth=0, position=0, field = None, object = None, is_open=0, is_pure_summary=1): def __init__ (self, title='', name='',url='', constraints='', depth=0, position=0, field = None, object = None, is_open=0, is_pure_summary=1):
self.title = title self.title = title
self.name = name self.name = name
self.url = url self.url = url
...@@ -1399,7 +1426,8 @@ class BasicGroup: ...@@ -1399,7 +1426,8 @@ class BasicGroup:
if color_script !=None: if color_script !=None:
current_color = color_script(self) current_color = color_script(self)
if method_begin == None and activity_list not in ([],None): #if method_begin == None and activity_list not in ([],None):
if activity_list not in ([],None):
# modifying iterating mode from original PlanningBox.py script to prevent # modifying iterating mode from original PlanningBox.py script to prevent
# useless and repetitive tests. # useless and repetitive tests.
...@@ -1417,8 +1445,8 @@ class BasicGroup: ...@@ -1417,8 +1445,8 @@ class BasicGroup:
# interpreting results and getting begin and end values from # interpreting results and getting begin and end values from
# previously recovered method # previously recovered method
block_begin = '' block_begin = None
block_end = '' block_end = None
if method_begin !=None: if method_begin !=None:
block_begin = method_begin() block_begin = method_begin()
else: else:
...@@ -1429,6 +1457,14 @@ class BasicGroup: ...@@ -1429,6 +1457,14 @@ class BasicGroup:
else: else:
block_end = None block_end = None
# ahndling case where activity bound is not defined
if block_begin == None:
block_begin = secondary_axis_info['bound_start']
current_color='#E4CCE1'
if block_end == None:
block_end = secondary_axis_info['bound_stop']
current_color='#E4CCE1'
# testing if activity is visible according to the current zoom selection over # testing if activity is visible according to the current zoom selection over
# the secondary_axis # the secondary_axis
if block_begin > secondary_axis_info['bound_stop'] or block_end < secondary_axis_info['bound_start']: if block_begin > secondary_axis_info['bound_stop'] or block_end < secondary_axis_info['bound_start']:
...@@ -1470,15 +1506,19 @@ class BasicGroup: ...@@ -1470,15 +1506,19 @@ class BasicGroup:
# testing if some activities have errors # testing if some activities have errors
error = 'false' error = 'false'
if list_error !=None: if list_error not in (None, []):
for activity_error in list_error: for activity_error in list_error:
if activity_error[0][0] == name: if activity_error[0][0] == name:
error = 'true' error = 'true'
break 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()
# creating new activity instance # creating new activity instance
activity = BasicActivity(title=info['info_center'],name=name, url=self.url,absolute_begin=block_begin, absolute_end=block_end,color = current_color, info_dict=info, error=error) 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)
# adding new activity to personal group activity list # adding new activity to personal group activity list
...@@ -1491,6 +1531,9 @@ class BasicGroup: ...@@ -1491,6 +1531,9 @@ class BasicGroup:
# group (used for Activity naming) # group (used for Activity naming)
indic += 1 indic += 1
info = None
info = {}
else: else:
...@@ -1507,8 +1550,14 @@ class BasicGroup: ...@@ -1507,8 +1550,14 @@ class BasicGroup:
# testing if activity is visible according to the current zoom selection over # testing if activity is visible according to the current zoom selection over
# the secondary_axis # the secondary_axis
if block_begin > secondary_axis_info['bound_stop'] or block_end < secondary_axis_info['bound_start']: if block_begin == None:
# activity will not be displayed, stopping process block_begin = secondary_axis_info['bound_start']
current_color='#E4CCE1'
if block_end == None:
block_end = secondary_axis_info['bound_stop']
current_color='#E4CCE1'
if (block_begin > secondary_axis_info['bound_stop'] or block_end < secondary_axis_info['bound_start']):
# # activity will not be displayed, stopping process
pass pass
else: else:
# activity is somehow displayed. checking if need to cut its bounds # activity is somehow displayed. checking if need to cut its bounds
...@@ -1524,7 +1573,7 @@ class BasicGroup: ...@@ -1524,7 +1573,7 @@ class BasicGroup:
# testing if some activities have errors # testing if some activities have errors
error = 'false' error = 'false'
if list_error !=None: if list_error not in (None,[]):
for activity_error in list_error: for activity_error in list_error:
if activity_error[0][0] == name: if activity_error[0][0] == name:
error = 'true' error = 'true'
...@@ -1534,7 +1583,7 @@ class BasicGroup: ...@@ -1534,7 +1583,7 @@ class BasicGroup:
name = "Activity_%s" % (self.object.getObject().getTitle()) name = "Activity_%s" % (self.object.getObject().getTitle())
# creating new activity instance # creating new activity instance
activity = BasicActivity(title=info['info_center'],name=name, 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,color = current_color, info_dict=info, error=error)
# adding new activity to personal group activity list # adding new activity to personal group activity list
try: try:
...@@ -1551,10 +1600,11 @@ class BasicActivity: ...@@ -1551,10 +1600,11 @@ class BasicActivity:
""" Represents an activity, a task, in the group it belongs to. Beware """ Represents an activity, a task, in the group it belongs to. Beware
nothing about multitask rendering. """ nothing about multitask rendering. """
def __init__ (self, title='', name='', url='', absolute_begin=None, 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, constraints='', color=None, error='false', info_dict= None):
self.title = title self.title = title
self.name = name self.name = name
self.object = object
self.url = url self.url = url
self.absolute_begin = absolute_begin # absolute values independant of any self.absolute_begin = absolute_begin # absolute values independant of any
# hypothetic zoom # hypothetic zoom
...@@ -1597,7 +1647,10 @@ class PlanningStructure: ...@@ -1597,7 +1647,10 @@ class PlanningStructure:
# afterwards will be defined as a planningBox's property field or (perhaps even better) # afterwards will be defined as a planningBox's property field or (perhaps even better)
# a on the fly button integrated over the planning representation # a on the fly button integrated over the planning representation
#render_format = field.get_value('render_format') #render_format = field.get_value('render_format')
self.render_format = 'YX' self.render_format = field.get_value('representation_type')
#self.render_format = 'YX'
# declaring main axis # declaring main axis
self.main_axis = Axis(title='main axis', name='axis', self.main_axis = Axis(title='main axis', name='axis',
...@@ -1635,7 +1688,7 @@ class PlanningStructure: ...@@ -1635,7 +1688,7 @@ class PlanningStructure:
# completing axisgroup informations according to their bounds # completing axisgroup informations according to their bounds
self.buildAxis() self.buildMainAxis()
# the whole structure is almost completed : axis_groups are defined, as # the whole structure is almost completed : axis_groups are defined, as
# axis_elements with their activities. Just need to create blocks related to # axis_elements with their activities. Just need to create blocks related to
...@@ -1648,7 +1701,48 @@ class PlanningStructure: ...@@ -1648,7 +1701,48 @@ class PlanningStructure:
""" """
build secondary axis structure build secondary axis structure
""" """
#pdb.set_trace() """
pdb.set_trace()
# defining min and max delimiter number
delimiter_min_number = 4
date_stop = self.secondary_axis.stop
date_start = self.secondary_axis.start
date_range = date_stop - date_start
# testing delimiter_type to apply (day, week, month, year)
# from smallest type to biggest
type_list = [['year', 365],
['month', 30],
['week', 7],
['day', 1]
]
# default good_type is last one (if nothing else matches)
good_type = type_list[-1]
for date_type in type_list:
# iterating each delimiter_type and testing if it matches the delimitation
# number definition
if date_range / date_type[1] >= delimiter_min_number:
good_type = date_type
break
# good type is known need to get first delimiter after start_date
# for that use special function getClosestDate (cf. DateUtils.py)
first_delimiter = getClosestDate(date=None, target_date=date_start, precision=good_type[0], before=0)
delimiter_list = []
current_delimiter = first_delimiter
while current_delimiter.Date() < date_stop.Date():
delimiter_list.append(current_delimiter.Date())
#DateUtils.addToDate(current_delimiter,
self.secondary_axis.axis_group.append(axis_group)
return None
"""
# getting secondary axis script generator # getting secondary axis script generator
planning_secondary_axis_method = getattr(basic_structure.here,'planning_secondary_axis') planning_secondary_axis_method = getattr(basic_structure.here,'planning_secondary_axis')
# calling script to generate axis_group_list # calling script to generate axis_group_list
...@@ -1668,7 +1762,7 @@ class PlanningStructure: ...@@ -1668,7 +1762,7 @@ class PlanningStructure:
axis_group_number += 1 axis_group_number += 1
def buildAxis (self): def buildMainAxis (self):
""" """
complete axis infomations (and more precisely axis position objects) thanks complete axis infomations (and more precisely axis position objects) thanks
to the actual planning structure to the actual planning structure
...@@ -1700,7 +1794,7 @@ class PlanningStructure: ...@@ -1700,7 +1794,7 @@ class PlanningStructure:
axis_element_already_present=0 axis_element_already_present=0
for basic_group_object in basic_structure.basic_group_list: for basic_group_object in basic_structure.basic_group_list:
axis_group_number += 1 axis_group_number += 1
axis_group = AxisGroup(name='Group_' + str(axis_group_number), title=basic_group_object.title, AxisGroup_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)
if self.render_format == 'YX': if self.render_format == 'YX':
axis_group.position_y = axis_group.position_main axis_group.position_y = axis_group.position_main
axis_group.position_x = axis_group.position_secondary axis_group.position_x = axis_group.position_secondary
...@@ -1724,7 +1818,7 @@ class PlanningStructure: ...@@ -1724,7 +1818,7 @@ class PlanningStructure:
for basic_activity_object in basic_group_object.basic_activity_list: for basic_activity_object in basic_group_object.basic_activity_list:
activity_number += 1 activity_number += 1
# create new activity in the PlanningStructure # create new activity in the PlanningStructure
activity = Activity(name='Group_' + str(axis_group_number) + '_Activity_' + str(activity_number), title=basic_activity_object.title, 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) 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 # adding activity to the current group
axis_group.addActivity(activity,axis_element_already_present) axis_group.addActivity(activity,axis_element_already_present)
else: else:
...@@ -1772,9 +1866,10 @@ class Activity: ...@@ -1772,9 +1866,10 @@ class Activity:
structure is used for rebuilding tasks from bloc positions when structure is used for rebuilding tasks from bloc positions when
validating the Planning. validating the Planning.
""" """
def __init__ (self,name=None,title=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, 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'):
self.name = name # internal activity_name self.name = name # internal activity_name
self.title = title # displayed activity_name self.title = title # displayed activity_name
self.object = object
self.types = types # activity, activity_error, info self.types = types # activity, activity_error, info
self.color = color # color used to render all Blocs self.color = color # color used to render all Blocs
self.link = link # link to the ERP5 object self.link = link # link to the ERP5 object
...@@ -1790,7 +1885,6 @@ class Activity: ...@@ -1790,7 +1885,6 @@ class Activity:
self.parent_axis_element = None self.parent_axis_element = None
self.render_format= render_format self.render_format= render_format
def isValidPosition(self, bound_begin, bound_end): def isValidPosition(self, bound_begin, bound_end):
""" """
can check if actual activity can fit within the bounds, returns : can check if actual activity can fit within the bounds, returns :
...@@ -1798,9 +1892,9 @@ class Activity: ...@@ -1798,9 +1892,9 @@ class Activity:
- 1 if partially ( need to cut the activity bounds to make it fit) - 1 if partially ( need to cut the activity bounds to make it fit)
- 2 definitely - 2 definitely
""" """
if self.begin > range_end or self.end < range_begin: if self.secondary_axis_begin > bound_end or self.secondary_axis_end < bound_begin:
return 0 return 0
elif self.begin > range_begin and self.end < range_end: elif self.secondary_axis_begin > bound_begin and self.secondary_axis_end < bound_end:
return 1 return 1
else: else:
return 2 return 2
...@@ -1813,7 +1907,10 @@ class Activity: ...@@ -1813,7 +1907,10 @@ class Activity:
""" """
# recover list of bounds # recover list of bounds
if self.secondary_axis_start != None or self.secondary_axis_stop != None:
secondary_block_bounds = self.splitActivity() secondary_block_bounds = self.splitActivity()
else:
secondary_block_bounds = [[self.secondary_axis_start,self.secondary_axis_stop]]
block_number = 0 block_number = 0
# iterating resulting list # iterating resulting list
...@@ -1827,8 +1924,14 @@ class Activity: ...@@ -1827,8 +1924,14 @@ class Activity:
new_block.buildInfoDict(info_dict = self.info) new_block.buildInfoDict(info_dict = self.info)
# updating secondary_axis block position # updating secondary_axis block position
if self.secondary_axis_start != None:
new_block.position_secondary.absolute_begin = start new_block.position_secondary.absolute_begin = start
else:
new_block.position_secondary.absolute_begin = secondary_axis_start
if self.secondary_axis_stop != None:
new_block.position_secondary.absolute_end = stop new_block.position_secondary.absolute_end = stop
else:
new_block.position_secondary.absolute_end = secondary_axis_stop
new_block.position_secondary.absolute_range = stop - start new_block.position_secondary.absolute_range = stop - start
# updating main_axis block position # updating main_axis block position
new_block.position_main.absolute_begin = self.parent_axis_element.absolute_number - 1 new_block.position_main.absolute_begin = self.parent_axis_element.absolute_number - 1
...@@ -2004,15 +2107,16 @@ class AxisGroup: ...@@ -2004,15 +2107,16 @@ class AxisGroup:
to hold sub groups elements. to hold sub groups elements.
""" """
def __init__ (self, name='', title='', def __init__ (self, name='', title='', object = None,
AxisGroup_list=None, AxisGroup_number=0, axis_group_list=None, axis_group_number=0,
AxisElement_list=None,AxisElement_number=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, is_open=0, is_pure_summary=1,depth=0, url=None, axis_element_already_insered= 0, secondary_axis_start=None, secondary_axis_stop=None):
self.name = name self.name = name
self.title = title self.title = title
self.axis_group_list = AxisGroup_list # ReportTree self.object = object # physical object related to the current group (used to validate modifications)
self.axis_group_number = AxisGroup_number self.axis_group_list = axis_group_list # ReportTree
self.axis_element_list = AxisElement_list # Multitasking self.axis_group_number = axis_group_number
self.axis_element_number = AxisElement_number self.axis_element_list = axis_element_list # Multitasking
self.axis_element_number = axis_element_number
self.axis_element_start = None self.axis_element_start = None
self.axis_element_stop = None self.axis_element_stop = None
# dict containing all class properties with their values # dict containing all class properties with their values
...@@ -2065,10 +2169,10 @@ class AxisGroup: ...@@ -2065,10 +2169,10 @@ class AxisGroup:
# iterating through them to check if one of them crosses the new one # iterating through them to check if one of them crosses the new one
for activity_statement in axis_element.activity_list: for activity_statement in axis_element.activity_list:
if activity_statement.isValidPosition(activity.begin, activity.end) != 0: if activity_statement.isValidPosition(activity.secondary_axis_begin, activity.secondary_axis_end) != 0:
# isValidPosition returned 1 or 2, this means the activity already # isValidPosition returned 1 or 2, this means the activity already
# present does prevent from adding the new activity as there is # present does prevent from adding the new activity as there is
# coverage. # coverage on the current axis_element.
# stop iterating actual axis_element and try with the next one # stop iterating actual axis_element and try with the next one
can_add = 0 can_add = 0
break break
...@@ -2083,6 +2187,10 @@ class AxisGroup: ...@@ -2083,6 +2187,10 @@ class AxisGroup:
# updating activity properties # updating activity properties
activity.parent_axis_element = axis_element activity.parent_axis_element = axis_element
# no need to check the next axis_elements to know if they can hold the
# new activity as it is already added to an axis_element
break
if not added: if not added:
# all axis_elements of the current group have been tested and no one can # all axis_elements of the current group have been tested and no one can
# contain the new activity. # contain the new activity.
...@@ -2100,7 +2208,7 @@ class AxisGroup: ...@@ -2100,7 +2208,7 @@ class AxisGroup:
# register the axis_element to the actual group. # register the axis_element to the actual group.
self.axis_element_list.append(new_axis_element) self.axis_element_list.append(new_axis_element)
except TypeError: except TypeError:
# in case axis_element_list is None # in case axis_element_list is Empty (first activity to the group)
# Need to create a new axis_element to hold the new activity # Need to create a new axis_element to hold the new activity
self.axis_element_number += 1 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_insered + self.axis_element_number, parent_axis_group=self) new_axis_element = AxisElement(name='Group_' + str(self.axis_group_number) + '_AxisElement_1', relative_number= self.axis_element_number, absolute_number = axis_element_already_insered + self.axis_element_number, parent_axis_group=self)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment