Commit 06d2790c authored by Jérome Perrin's avatar Jérome Perrin

First prototype of integrating jsplumb to display graphs

In this prototype graph are visible in History tab
parent f64738a7
def ERP5Site_getGraphLayout(input_graph):
"""Uses graphviz to position nodes of the graph.
This uses pydot, which depends on pyparsing == 1.5.7 (latest versions of
pyparsing are for python 3).
Luckily, the python files from those packages can be dropped in
$INSTANCE_HOME/lib/python
"""
import pydot
graph = pydot.Dot()
for node_id in input_graph['nodes']:
graph.add_node(pydot.Node(node_id))
for transition in input_graph['edges']:
graph.add_edge(pydot.Edge(transition['source'], transition['destination']))
new_graph = pydot.graph_from_dot_data(graph.create_dot())
# calulate the ratio from the size of the bounding box
ratio = new_graph.get_bb()
origin_left, origin_top, max_left, max_top = [float(p) for p in
new_graph.get_bb()[1:-1].split(',')]
ratio_top = max_top - origin_top
ratio_left = max_left - origin_left
preference_dict = dict()
for node in new_graph.get_nodes():
# skip technical nodes
if node.get_name() in ('graph', 'node', 'edge'):
continue
left, top = [float(p) for p in node.get_pos()[1:-1].split(",")]
preference_dict[node.get_name()] = dict(
top=1-(top/ratio_top),
left=1-(left/ratio_left),)
return preference_dict
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>business_template_skin_layer_priority</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>float</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>business_template_skin_layer_priority</string> </key>
<value> <float>40.0</float> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_graph_editor</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from json import dumps\n
portal = context.getPortalObject()\n
\n
def getERP5WorkflowGraph(erp5_workflow):\n
graph = dict(nodes=dict(), edges=[], preferences=dict())\n
for state in erp5_workflow.contentValues(portal_type=\'State\'):\n
graph[\'nodes\'][state.getId()] = dict(name=state.getTranslatedTitle())\n
for transition in state.getDestinationValueList(portal_type=\'Transition\'):\n
graph[\'edges\'].append(dict(source=state.getId(),\n
destination=transition.getDestinationId(),\n
data=dict(name=transition.getTranslatedTitle())))\n
return graph\n
\n
def getDCWorkflowGraph(dc_workflow):\n
graph = dict(nodes=dict(), edges=[], preferences=dict())\n
for state in dc_workflow.states.objectValues():\n
graph[\'nodes\'][state.getId()] = dict(name=state.title_or_id())\n
for transition in state.transitions:\n
if transition in dc_workflow.transitions:\n
transition = dc_workflow.transitions[transition]\n
if transition.new_state_id:\n
graph[\'edges\'].append(dict(source=state.getId(),\n
destination=transition.new_state_id,\n
data=dict(name=transition.actbox_name or transition.title_or_id(),\n
description=transition.description,\n
actbox_url=transition.actbox_url,\n
)))\n
return graph\n
\n
def getWorkflowHistoryGraph(document, workflow_id):\n
portal_workflow = context.getPortalObject().portal_workflow\n
graph = getDCWorkflowGraph(portal_workflow[workflow_id])\n
history = portal_workflow.getInfoFor(document, \'history\', wf_id=workflow_id)\n
state = portal_workflow.getInfoFor(document, portal_workflow[workflow_id].variables.getStateVar(), wf_id=workflow_id)\n
graph[\'preferences\'].setdefault(state, {})[\'background-color\'] = \'#50AA50\' # XXX use a different style for the current state \n
\n
return graph\n
\n
visited_business_process_set = set() # prevent infinite recurisions\n
def getBusinessProcessGraph(business_process):\n
graph = dict(nodes=dict(), edges=[], preferences=dict())\n
if business_process in visited_business_process_set:\n
return graph\n
visited_business_process_set.add(business_process)\n
for link in business_process.contentValues(portal_type=\'Business Link\'):\n
for trade_state in (link.getPredecessorValue(), link.getSuccessorValue()):\n
if trade_state is not None:\n
graph[\'nodes\'][trade_state.getReference() or trade_state.getId()] = dict(name=trade_state.getTranslatedTitle())\n
if link.getPredecessor() and link.getSuccessor():\n
graph[\'edges\'].append(dict(source=link.getPredecessorReference() or link.getPredecessorId(),\n
destination=link.getSuccessorReference() or link.getSuccessorId(),\n
data=dict(name=link.getTranslatedTitle())))\n
for specialise in business_process.getSpecialiseValueList(portal_type=\'Business Process\'):\n
specialise_graph = getBusinessProcessGraph(specialise)\n
for node_id, node_data in specialise_graph[\'nodes\'].items():\n
graph[\'nodes\'].setdefault(node_id, node_data)\n
for node_id, pref in specialise_graph[\'preferences\'].items():\n
graph[\'preferences\'].setdefault(node_id, pref)\n
graph[\'edges\'].extend(specialise_graph[\'edges\'])\n
\n
return graph\n
\n
\n
\n
if context.meta_type == \'ERP5 Workflow\':\n
graph = getERP5WorkflowGraph(context)\n
elif context.meta_type == \'Workflow\':\n
graph = getDCWorkflowGraph(context)\n
elif context.meta_type == \'ERP5 Business Process\':\n
graph = getBusinessProcessGraph(context)\n
else:\n
# workflow history for the first workflow.\n
wf_id = None\n
graph = dict(nodes=dict(), edges=[], preferences=dict())\n
for wf in portal.portal_workflow.getWorkflowsFor(context):\n
if wf.variables.getStateVar() in (\'validation_state\', \'simulation_state\'):\n
wf_id = wf.getId()\n
graph = getWorkflowHistoryGraph(context, wf_id)\n
break\n
\n
# layout\n
for node_id, node_position in portal.ERP5Site_getGraphLayout(graph).items():\n
graph[\'preferences\'].setdefault(node_id, {}).update(node_position)\n
\n
container.REQUEST.RESPONSE.setHeader(\'content-type\', \'application/json\')\n
return dumps(graph)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_getJsonGraph</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list>
<string>your_graph_editor</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list>
<string>your_reportbox</string>
</list>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_viewHistory</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Base_viewHistory</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>report_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>History</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>report_method</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_reportbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>your_reportbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewReportFieldLibrary</string> </value>
</item>
<item>
<key> <string>report_method</string> </key>
<value> <string>Base_getWorkflowHistorySectionList</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return (\'erp5_knowledge_box.css\', \'erp5_graph_editor.css\')\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getCssRelativeUrlList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>ERP5Site_getGraphLayout</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GraphEditorUtils</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getGraphLayout</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return (\n
# we don\'t use minimized to ease development\n
\'jquery/core/jquery.js\', \'jquery/ui/js/jquery-ui.js\', \'jquery.jsPlumb-1.4.1-all.js\',\n
\'erp5.js\', \'erp5_knowledge_box.js\', \'erp5_graph_editor.js\',)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getJavaScriptRelativeUrlList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Change_cache_settings_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Change_permissions_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_EtagSupport__etag</string> </key>
<value> <string>ts73556426.53</string> </value>
</item>
<item>
<key> <string>_FTP_access_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Manage_WebDAV_Locks_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Manage_properties_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Take_ownership_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Undo_changes_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_View_management_screens_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_Lock_items_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_Unlock_items_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_access_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>erp5_graph_editor.css</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/css</string> </value>
</item>
<item>
<key> <string>data</string> </key>
<value> <string>/* the div used for the graph */\n
#erp5_graph_renderer {\n
z-index: 5000;\n
height: 600px;\n
width: 850px;\n
}\n
\n
\n
.graph_node {\n
z-index: 24;\n
background-color: #FFFF99;\n
box-shadow: 2px 2px 19px #AAAAAA;\n
border: 1px solid #000;\n
border-radius: 0.5em 0.5em 0.5em 0.5em;\n
\n
text-align: center;\n
font-size: small;\n
\n
position: absolute;\n
height: 2em;\n
width: 8em;\n
line-height: 2em;\n
\n
}\n
\n
</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>size</string> </key>
<value> <int>391</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Change_cache_settings_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Change_permissions_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_EtagSupport__etag</string> </key>
<value> <string>ts73556794.58</string> </value>
</item>
<item>
<key> <string>_FTP_access_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Manage_WebDAV_Locks_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Manage_properties_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Take_ownership_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_Undo_changes_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_View_management_screens_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_Lock_items_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_Unlock_items_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>_WebDAV_access_Permission</string> </key>
<value>
<list>
<string>Manager</string>
</list>
</value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>erp5_graph_editor.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>data</string> </key>
<value> <string encoding="cdata"><![CDATA[
(function($) {\n
"use strict";\n
\n
jsPlumb.bind("ready", function() {\n
\n
jsPlumb.setRenderMode(jsPlumb.SVG);\n
jsPlumb.importDefaults({\n
Endpoint: [ "Dot", {radius: 2} ],\n
ConnectionOverlays : [\n
[ "Arrow", { location:1, width:10, } ], \n
],\n
Anchor: "Continuous",\n
}); \n
\n
\n
/**\n
* The graph renderer class\n
*\n
* Initialise a graph by passing a jquery selector for the container\n
*/\n
function GraphRenderer(container) {\n
var self = { nodes: {},\n
edges: [],\n
preferences: {},\n
container: container};\n
\n
self.addNode = function(node_id, node_data) {\n
// FIXME: id needs a prefix to prevent clashes\n
var element = $(\'<div class="graph_node" id="\' + node_id + \'">\').text(node_data[\'name\'] || node_id),\n
preference = self.preferences[node_id];\n
if (preference) {\n
element.css(preference);\n
}\n
self.container.append(element);\n
self.nodes[node_id] = node_data\n
};\n
\n
self.addEdge = function(source_node_id, destination_node_id, edge_data) {\n
var edge_label = edge_data[\'name\'] || "";\n
if ((source_node_id && destination_node_id) && (source_node_id != destination_node_id)) {\n
jsPlumb.connect({\n
source: source_node_id,\n
target: destination_node_id,\n
paintStyle: { lineWidth: 1, strokeStyle: "#000", },\n
overlays : [["Label", {label: edge_label,}]],\n
});\n
self.edges.push({ source: source_node_id,\n
destination: destination_node_id,\n
data: edge_data });\n
} else {\n
console.error("Ignoring invalid edge", source_node_id, destination_node_id, edge_data);\n
}\n
}\n
\n
self.loadGraph = function(data) {\n
/** Load the graph from data, a dictionnary with \'edges\', \'nodes\' and\n
* \'preferences\' keys.\n
*/\n
$.each(data.preferences, function(node_id, pref) {\n
if (pref) {\n
// Positions from are from 0 to 1. Rescale them according to the\n
// size of the rendering div\n
// XXX 35 is taken from the size of a graph_node\n
pref.top = (Math.floor(pref.top*self.container.height()) - 35) + "px";\n
pref.left = Math.floor(pref.left*self.container.width()) + "px";\n
self.preferences[node_id] = $.extend(self.preferences[node_id] || {}, pref)\n
};\n
});\n
$.each(data.nodes, function(node_id, node) {\n
self.addNode(node_id, node);\n
});\n
$.each(data.edges, function(idx, edge) {\n
self.addEdge(edge.source, edge.destination, edge.data);\n
});\n
// XXX should not be always draggable. Global properties ?\n
jsPlumb.draggable(jsPlumb.getSelector(".graph_node"),\n
{ grid: [20, 20],\n
stop: function(element) { }, } );\n
\n
}\n
return self;\n
}\n
\n
\n
/** XXX create a graph renderer when there\'s an element with id \'erp5_graph_renderer\' in the page \n
*/\n
var renderer = $("#erp5_graph_renderer");\n
if (renderer.length) {\n
var graph = GraphRenderer(renderer);\n
$.getJSON(\'Base_getJsonGraph\', function(data) {\n
graph.loadGraph(data)\n
});\n
};\n
});\n
})(jQuery);\n
]]></string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>size</string> </key>
<value> <int>3321</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
Requires pydot
\ No newline at end of file
1
\ No newline at end of file
GraphEditorUtils
\ No newline at end of file
erp5_graph_editor
\ No newline at end of file
erp5_graph_editor
\ No newline at end of file
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