/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var NORMAL_STROKE = 2; var SEQUENCEFLOW_STROKE = 2; var ASSOCIATION_STROKE = 2; var TASK_STROKE = 2; var TASK_HIGHLIGHT_STROKE = 4; var CALL_ACTIVITY_STROKE = 4; var ENDEVENT_STROKE = 4; var COMPLETED_COLOR = "#2632aa"; var TEXT_COLOR = "#373e48"; var CURRENT_COLOR = "#017501"; var HOVER_COLOR = "#666666"; var ACTIVITY_STROKE_COLOR = "#000000"; var ACTIVITY_FILL_COLOR = "#ffffff"; var MAIN_STROKE_COLOR = "#585858"; var TEXT_PADDING = 3; var ARROW_WIDTH = 4; var MARKER_WIDTH = 12; var TASK_FONT = {font: "11px Arial", opacity: 1, fill: Raphael.rgb(0, 0, 0)}; // icons var ICON_SIZE = 16; var ICON_PADDING = 4; var INITIAL_CANVAS_WIDTH; var INITIAL_CANVAS_HEIGHT; var paper; var viewBox; var viewBoxWidth; var viewBoxHeight; var canvasWidth; var canvasHeight; var modelDiv = jQuery('#bpmnModel'); var modelId = modelDiv.attr('data-model-id'); var historyModelId = modelDiv.attr('data-history-id'); var processDefinitionId = modelDiv.attr('data-process-definition-id'); var modelType = modelDiv.attr('data-model-type'); var isDebuggerEnabled = angular.element(document.querySelector('#bpmnModel')).scope().model.isDebuggerEnabled; // Support for custom background colors for activities var customActivityColors = modelDiv.attr('data-activity-color-mapping'); if (customActivityColors !== null && customActivityColors !== undefined && customActivityColors.length > 0) { // Stored on the attribute as a string customActivityColors = JSON.parse(customActivityColors); } var customActivityToolTips = modelDiv.attr('data-activity-tooltips'); if (customActivityToolTips !== null && customActivityToolTips !== undefined && customActivityToolTips.length > 0) { // Stored on the attribute as a string customActivityToolTips = JSON.parse(customActivityToolTips); } // Support for custom opacity for activity backgrounds var customActivityBackgroundOpacity = modelDiv.attr('data-activity-opacity'); var elementsAdded = new Array(); var elementsRemoved = new Array(); var selectedElement = undefined; var collapsedItemNavigation = new Array(); var bpmnData; function _showTip(htmlNode, element) { // Custom tooltip var documentation = undefined; if (customActivityToolTips) { if (customActivityToolTips[element.name]) { documentation = customActivityToolTips[element.name]; } else if (customActivityToolTips[element.id]) { documentation = customActivityToolTips[element.id]; } else { documentation = ''; // Show nothing if custom tool tips are enabled } } // Default tooltip, no custom tool tip set if (documentation === undefined) { var documentation = ""; if (element.name && element.name.length > 0) { documentation += "Name: " + element.name + "

"; } if (element.properties) { for (var i = 0; i < element.properties.length; i++) { var propName = element.properties[i].name; if (element.properties[i].type && element.properties[i].type === 'list') { documentation += '' + propName + ':
'; for (var j = 0; j < element.properties[i].value.length; j++) { documentation += '' + element.properties[i].value[j] + '
'; } } else { documentation += '' + propName + ': ' + element.properties[i].value + '
'; } } } } var text = element.type + " "; if (element.name && element.name.length > 0) { text += element.name; } else { text += element.id; } htmlNode.qtip({ content: { text: documentation, title: { text: text } }, position: { my: 'top left', at: 'bottom center', viewport: jQuery('#bpmnModel') }, hide: { fixed: true, delay: 500, event: 'click mouseleave' }, style: { classes: 'ui-tooltip-kisbpm-bpmn' } }); } function _expandCollapsedElement(element) { if (bpmnData.collapsed) { for (var i = 0; i < bpmnData.collapsed.length; i++) { var collapsedItem = bpmnData.collapsed[i]; if (element.id == collapsedItem.id) { paper.clear(); var modelElements = collapsedItem.elements; for (var i = 0; i < modelElements.length; i++) { var subElement = modelElements[i]; var drawFunction = eval("_draw" + subElement.type); drawFunction(subElement); } if (collapsedItem.flows) { for (var i = 0; i < collapsedItem.flows.length; i++) { var subFlow = collapsedItem.flows[i]; _drawFlow(subFlow); } } var collapsedName; if (element.name) { collapsedName = element.name; } else { collapsedName = 'sub process ' + element.id; } collapsedItemNavigation.push({ "id": element.id, "name": collapsedName }); _buildNavigationTree(); break; } } } } function _navigateTo(elementId) { var modelElements = undefined; var modelFlows = undefined; newCollapsedItemNavigation = new Array(); if (elementId == 'FLOWABLE_ROOT_PROCESS') { modelElements = bpmnData.elements; modelFlows = bpmnData.flows; } else { for (var i = 0; i < bpmnData.collapsed.length; i++) { var collapsedItem = bpmnData.collapsed[i]; var collapsedName = undefined; for (var j = 0; j < collapsedItemNavigation.length; j++) { if (elementId == collapsedItemNavigation[j].id) { collapsedName = collapsedItemNavigation[j].name; break; } } if (!collapsedName) { continue; } newCollapsedItemNavigation.push({ "id": collapsedItem.id, "name": collapsedName }); if (elementId == collapsedItem.id) { modelElements = collapsedItem.elements; modelFlows = collapsedItem.flows; break; } } } if (modelElements) { paper.clear(); for (var i = 0; i < modelElements.length; i++) { var subElement = modelElements[i]; var drawFunction = eval("_draw" + subElement.type); drawFunction(subElement); } if (modelFlows) { for (var i = 0; i < modelFlows.length; i++) { var subFlow = modelFlows[i]; _drawFlow(subFlow); } } collapsedItemNavigation = newCollapsedItemNavigation; _buildNavigationTree(); } } function _buildNavigationTree() { var navigationUrl = '| Root'; for (var i = 0; i < collapsedItemNavigation.length; i++) { navigationUrl += ' > ' + collapsedItemNavigation[i].name + ''; } $('#navigationTree').html(navigationUrl); } function _addHoverLogic(element, type, defaultColor) { var strokeColor = _bpmnGetColor(element, defaultColor); var topBodyRect = null; if (type === "rect") { topBodyRect = paper.rect(element.x, element.y, element.width, element.height); } else if (type === "circle") { var x = element.x + (element.width / 2); var y = element.y + (element.height / 2); topBodyRect = paper.circle(x, y, 15); } else if (type === "rhombus") { topBodyRect = paper.path("M" + element.x + " " + (element.y + (element.height / 2)) + "L" + (element.x + (element.width / 2)) + " " + (element.y + element.height) + "L" + (element.x + element.width) + " " + (element.y + (element.height / 2)) + "L" + (element.x + (element.width / 2)) + " " + element.y + "z" ); } var opacity = 0; var fillColor = "#ffffff"; if (jQuery.inArray(element.id, elementsAdded) >= 0) { opacity = 0.2; fillColor = "green"; } if (jQuery.inArray(element.id, elementsRemoved) >= 0) { opacity = 0.2; fillColor = "red"; } topBodyRect.attr({ "opacity": opacity, "stroke" : "none", "fill" : fillColor }); _showTip(jQuery(topBodyRect.node), element); topBodyRect.mouseover(function () { paper.getById(element.id).attr({"stroke": HOVER_COLOR}); }); topBodyRect.mouseout(function () { paper.getById(element.id).attr({"stroke": _bpmnGetColor(element, defaultColor)}); }); if (isDebuggerEnabled) { if (element.current || element.brokenExecutions) { topBodyRect.click(function () { if (selectedElement != element.id) { paper.getById(element.id).attr({"stroke": "green"}); selectedElement = element.id; paper.getById(element.id).attr({"stroke": "red"}); _executionClicked(element.id); } else { selectedElement = undefined; paper.getById(element.id).attr({"stroke": "green"}); var scope = angular.element(document.querySelector('#bpmnModel')).scope(); modelDiv.attr("selected-execution", scope.model.processInstance.id); scope.model.selectedExecution = scope.model.processInstance.id; angular.element(document.querySelector('#variablesUi')).scope().loadVariables(); } }); } } } function _executionClicked(activityId) { var executions = angular.element(document.querySelector('#bpmnModel')).scope().model.executions; for (var i in executions) { if (executions[i]["activityId"] == activityId) { var activityToUnselect = modelDiv.attr("selected-activity"); if (activityToUnselect) { var rectangleToUnselect = paper.getById(activityToUnselect); if (rectangleToUnselect) { rectangleToUnselect.attr({"stroke": "green"}); } } modelDiv.attr("selected-execution", executions[i].id); modelDiv.attr("selected-activity", activityId); if (activityId) { paper.getById(activityId).attr({"stroke": "red"}); } var scope = angular.element(document.querySelector('#bpmnModel')).scope(); if (scope.gridExecutions.data) { for (var j = 0; j < scope.gridExecutions.data.length; j++) { if (executions[i].id == scope.gridExecutions.data[j].id) { scope.gridExecutionsApi.selection.selectRow(scope.gridExecutions.data[j]); j = scope.gridExecutions.data.length; } } } scope.loadVariables(); return; } } } function _breakpointRestCall(actionType, activityId) { $.ajax({ type: actionType, url: '../app/rest/debugger/breakpoints', contentType: 'application/json; charset=utf-8', data: JSON.stringify({ activityId: activityId }), success: function () { paper.clear(); angular.element(document.querySelector('#bpmnModel')).scope().getEventLog(); _showProcessDiagram(); } }) } function _drawBreakpoint(element, breakpoints) { var circle = paper.circle(element.x + 10, element.y - 10, 7); var breakpointFillColor = "white"; var breakpointStrokeColor = "gray"; var breakpointTipText = "Inactive element"; if (element.current) { breakpointFillColor = "red"; breakpointTipText = "Active execution" } if (element.breakpoint) { breakpointTipText = breakpointTipText + "
Click to remove breakpoint"; breakpointStrokeColor = "red"; circle.click(function () { _breakpointRestCall("DELETE", element.id); }); } else { breakpointTipText = breakpointTipText + "
Click to add breakpoint"; circle.click(function () { _breakpointRestCall("POST", element.id); }); } circle.attr("stroke", breakpointStrokeColor); circle.attr("stroke-width", "3"); circle.attr("fill", breakpointFillColor); var circleHtmlNode = jQuery(circle.node); circleHtmlNode.qtip({ content: { text: breakpointTipText, button: false }, position: { my: 'top left', at: 'bottom center', viewport: jQuery('#bpmnModel') }, hide: { fixed: true, delay: 500, event: 'click mouseleave' }, style: { classes: 'ui-tooltip-kisbpm-bpmn' } }); } function _zoom(zoomIn) { var tmpCanvasWidth, tmpCanvasHeight; if (zoomIn) { tmpCanvasWidth = canvasWidth * (1.0 / 0.90); tmpCanvasHeight = canvasHeight * (1.0 / 0.90); } else { tmpCanvasWidth = canvasWidth * (1.0 / 1.10); tmpCanvasHeight = canvasHeight * (1.0 / 1.10); } if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight) { canvasWidth = tmpCanvasWidth; canvasHeight = tmpCanvasHeight; paper.setSize(canvasWidth, canvasHeight); } } var modelUrl; if (modelType == 'runtime') { if (historyModelId) { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/history/' + historyModelId + '/model-json'; } else if (isDebuggerEnabled) { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/debugger/' + modelId + '/model-json'; } else { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + modelId + '/model-json'; } } else if (modelType == 'design') { if (historyModelId) { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + historyModelId + '/model-json'; } else { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/model-json'; } } else if (modelType == 'process-definition') { modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions/' + processDefinitionId + '/model-json'; } function _drawContinueExecution(x, y , executionId, activityId) { var arrow = paper.path("M "+ x +" "+ y + " L "+ (x+8) +" "+ (y+4) +" "+ x +" "+ (y+8) +" z"); arrow.click(function () { $.ajax({ type: 'PUT', url: '../app/rest/debugger/breakpoints/' + executionId + '/continue', contentType: 'application/json; charset=utf-8', success: function () { paper.clear(); var processInstanceId = angular.element(document.querySelector('#bpmnModel')).scope().model.processInstance.id; modelDiv.attr("selected-execution", processInstanceId); angular.element(document.querySelector('#bpmnModel')).scope().model.selectedExecution = processInstanceId; angular.element(document.querySelector('#bpmnModel')).scope().getExecutions(); angular.element(document.querySelector('#bpmnModel')).scope().model.variables = undefined; angular.element(document.querySelector('#bpmnModel')).scope().loadVariables(); angular.element(document.querySelector('#bpmnModel')).scope().getEventLog(); _showProcessDiagram(); }, error: function () { alert("error"); } }) } ); arrow.attr("stroke", "green"); arrow.attr("stroke-width", "3"); arrow.attr("fill", "green"); var arrowHtmlNode = jQuery(arrow.node); arrowHtmlNode.qtip({ content: { text: "Fire execution "+ executionId+", activity " + activityId, button: false }, position: { my: 'top left', at: 'bottom center', viewport: jQuery('#bpmnModel') }, hide: { fixed: true, delay: 500, event: 'click mouseleave' }, style: { classes: 'ui-tooltip-kisbpm-bpmn' } }); } function _showProcessDiagram() { var request = jQuery.ajax({ type: 'get', url: modelUrl + '?nocaching=' + new Date().getTime() }); request.success(function (data, textStatus, jqXHR) { if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return; INITIAL_CANVAS_WIDTH = data.diagramWidth; if (modelType == 'design') { INITIAL_CANVAS_WIDTH += 20; } else { INITIAL_CANVAS_WIDTH += 30; } INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50; canvasWidth = INITIAL_CANVAS_WIDTH; canvasHeight = INITIAL_CANVAS_HEIGHT; viewBoxWidth = INITIAL_CANVAS_WIDTH; viewBoxHeight = INITIAL_CANVAS_HEIGHT; if (modelType == 'design') { var headerBarHeight = 170; var offsetY = 0; if (jQuery(window).height() > (canvasHeight + headerBarHeight)) { offsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2; } if (offsetY > 50) { offsetY = 50; } jQuery('#bpmnModel').css('marginTop', offsetY); } jQuery('#bpmnModel').width(INITIAL_CANVAS_WIDTH); jQuery('#bpmnModel').height(INITIAL_CANVAS_HEIGHT); paper = Raphael(document.getElementById('bpmnModel'), canvasWidth, canvasHeight); paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false); paper.renderfix(); if (data.pools) { for (var i = 0; i < data.pools.length; i++) { var pool = data.pools[i]; _drawPool(pool); } } var modelElements = data.elements; for (var i = 0; i < modelElements.length; i++) { var element = modelElements[i]; // try { var drawFunction = eval("_draw" + element.type); drawFunction(element); if (isDebuggerEnabled) { _drawBreakpoint(element); if (element.brokenExecutions) { for (var j = 0; j < element.brokenExecutions.length; j++) { _drawContinueExecution(element.x + 25 + j * 10, element.y - 15, element.brokenExecutions[j], element.id); } } } // } catch(err) {console.log(err);} } if (data.flows) { for (var i = 0; i < data.flows.length; i++) { var flow = data.flows[i]; if (flow.type === 'sequenceFlow') { _drawFlow(flow); } else if (flow.type === 'association') { _drawAssociation(flow); } } } bpmnData = data; }); request.error(function (jqXHR, textStatus, errorThrown) { alert("error"); }); } _showProcessDiagram();