电子档案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

615 lines
20 KiB

  1. /* Licensed under the Apache License, Version 2.0 (the "License");
  2. * you may not use this file except in compliance with the License.
  3. * You may obtain a copy of the License at
  4. *
  5. * http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Unless required by applicable law or agreed to in writing, software
  8. * distributed under the License is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. * See the License for the specific language governing permissions and
  11. * limitations under the License.
  12. */
  13. var NORMAL_STROKE = 2;
  14. var SEQUENCEFLOW_STROKE = 2;
  15. var ASSOCIATION_STROKE = 2;
  16. var TASK_STROKE = 2;
  17. var TASK_HIGHLIGHT_STROKE = 4;
  18. var CALL_ACTIVITY_STROKE = 4;
  19. var ENDEVENT_STROKE = 4;
  20. var COMPLETED_COLOR = "#2632aa";
  21. var TEXT_COLOR = "#373e48";
  22. var CURRENT_COLOR = "#017501";
  23. var HOVER_COLOR = "#666666";
  24. var ACTIVITY_STROKE_COLOR = "#000000";
  25. var ACTIVITY_FILL_COLOR = "#ffffff";
  26. var MAIN_STROKE_COLOR = "#585858";
  27. var TEXT_PADDING = 3;
  28. var ARROW_WIDTH = 4;
  29. var MARKER_WIDTH = 12;
  30. var TASK_FONT = {font: "11px Arial", opacity: 1, fill: Raphael.rgb(0, 0, 0)};
  31. // icons
  32. var ICON_SIZE = 16;
  33. var ICON_PADDING = 4;
  34. var INITIAL_CANVAS_WIDTH;
  35. var INITIAL_CANVAS_HEIGHT;
  36. var paper;
  37. var viewBox;
  38. var viewBoxWidth;
  39. var viewBoxHeight;
  40. var canvasWidth;
  41. var canvasHeight;
  42. var modelDiv = jQuery('#bpmnModel');
  43. var modelId = modelDiv.attr('data-model-id');
  44. var historyModelId = modelDiv.attr('data-history-id');
  45. var processDefinitionId = modelDiv.attr('data-process-definition-id');
  46. var modelType = modelDiv.attr('data-model-type');
  47. var isDebuggerEnabled = angular.element(document.querySelector('#bpmnModel')).scope().model.isDebuggerEnabled;
  48. // Support for custom background colors for activities
  49. var customActivityColors = modelDiv.attr('data-activity-color-mapping');
  50. if (customActivityColors !== null && customActivityColors !== undefined && customActivityColors.length > 0) {
  51. // Stored on the attribute as a string
  52. customActivityColors = JSON.parse(customActivityColors);
  53. }
  54. var customActivityToolTips = modelDiv.attr('data-activity-tooltips');
  55. if (customActivityToolTips !== null && customActivityToolTips !== undefined && customActivityToolTips.length > 0) {
  56. // Stored on the attribute as a string
  57. customActivityToolTips = JSON.parse(customActivityToolTips);
  58. }
  59. // Support for custom opacity for activity backgrounds
  60. var customActivityBackgroundOpacity = modelDiv.attr('data-activity-opacity');
  61. var elementsAdded = new Array();
  62. var elementsRemoved = new Array();
  63. var selectedElement = undefined;
  64. var collapsedItemNavigation = new Array();
  65. var bpmnData;
  66. function _showTip(htmlNode, element)
  67. {
  68. // Custom tooltip
  69. var documentation = undefined;
  70. if (customActivityToolTips) {
  71. if (customActivityToolTips[element.name]) {
  72. documentation = customActivityToolTips[element.name];
  73. } else if (customActivityToolTips[element.id]) {
  74. documentation = customActivityToolTips[element.id];
  75. } else {
  76. documentation = ''; // Show nothing if custom tool tips are enabled
  77. }
  78. }
  79. // Default tooltip, no custom tool tip set
  80. if (documentation === undefined) {
  81. var documentation = "";
  82. if (element.name && element.name.length > 0) {
  83. documentation += "<b>Name</b>: <i>" + element.name + "</i><br/><br/>";
  84. }
  85. if (element.properties) {
  86. for (var i = 0; i < element.properties.length; i++) {
  87. var propName = element.properties[i].name;
  88. if (element.properties[i].type && element.properties[i].type === 'list') {
  89. documentation += '<b>' + propName + '</b>:<br/>';
  90. for (var j = 0; j < element.properties[i].value.length; j++) {
  91. documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';
  92. }
  93. }
  94. else {
  95. documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';
  96. }
  97. }
  98. }
  99. }
  100. var text = element.type + " ";
  101. if (element.name && element.name.length > 0)
  102. {
  103. text += element.name;
  104. }
  105. else
  106. {
  107. text += element.id;
  108. }
  109. htmlNode.qtip({
  110. content: {
  111. text: documentation,
  112. title: {
  113. text: text
  114. }
  115. },
  116. position: {
  117. my: 'top left',
  118. at: 'bottom center',
  119. viewport: jQuery('#bpmnModel')
  120. },
  121. hide: {
  122. fixed: true, delay: 500,
  123. event: 'click mouseleave'
  124. },
  125. style: {
  126. classes: 'ui-tooltip-kisbpm-bpmn'
  127. }
  128. });
  129. }
  130. function _expandCollapsedElement(element) {
  131. if (bpmnData.collapsed) {
  132. for (var i = 0; i < bpmnData.collapsed.length; i++) {
  133. var collapsedItem = bpmnData.collapsed[i];
  134. if (element.id == collapsedItem.id) {
  135. paper.clear();
  136. var modelElements = collapsedItem.elements;
  137. for (var i = 0; i < modelElements.length; i++) {
  138. var subElement = modelElements[i];
  139. var drawFunction = eval("_draw" + subElement.type);
  140. drawFunction(subElement);
  141. }
  142. if (collapsedItem.flows) {
  143. for (var i = 0; i < collapsedItem.flows.length; i++) {
  144. var subFlow = collapsedItem.flows[i];
  145. _drawFlow(subFlow);
  146. }
  147. }
  148. var collapsedName;
  149. if (element.name) {
  150. collapsedName = element.name;
  151. } else {
  152. collapsedName = 'sub process ' + element.id;
  153. }
  154. collapsedItemNavigation.push({
  155. "id": element.id,
  156. "name": collapsedName
  157. });
  158. _buildNavigationTree();
  159. break;
  160. }
  161. }
  162. }
  163. }
  164. function _navigateTo(elementId) {
  165. var modelElements = undefined;
  166. var modelFlows = undefined;
  167. newCollapsedItemNavigation = new Array();
  168. if (elementId == 'FLOWABLE_ROOT_PROCESS') {
  169. modelElements = bpmnData.elements;
  170. modelFlows = bpmnData.flows;
  171. } else {
  172. for (var i = 0; i < bpmnData.collapsed.length; i++) {
  173. var collapsedItem = bpmnData.collapsed[i];
  174. var collapsedName = undefined;
  175. for (var j = 0; j < collapsedItemNavigation.length; j++) {
  176. if (elementId == collapsedItemNavigation[j].id) {
  177. collapsedName = collapsedItemNavigation[j].name;
  178. break;
  179. }
  180. }
  181. if (!collapsedName) {
  182. continue;
  183. }
  184. newCollapsedItemNavigation.push({
  185. "id": collapsedItem.id,
  186. "name": collapsedName
  187. });
  188. if (elementId == collapsedItem.id) {
  189. modelElements = collapsedItem.elements;
  190. modelFlows = collapsedItem.flows;
  191. break;
  192. }
  193. }
  194. }
  195. if (modelElements) {
  196. paper.clear();
  197. for (var i = 0; i < modelElements.length; i++) {
  198. var subElement = modelElements[i];
  199. var drawFunction = eval("_draw" + subElement.type);
  200. drawFunction(subElement);
  201. }
  202. if (modelFlows) {
  203. for (var i = 0; i < modelFlows.length; i++) {
  204. var subFlow = modelFlows[i];
  205. _drawFlow(subFlow);
  206. }
  207. }
  208. collapsedItemNavigation = newCollapsedItemNavigation;
  209. _buildNavigationTree();
  210. }
  211. }
  212. function _buildNavigationTree() {
  213. var navigationUrl = '| <a href="javascript:_navigateTo(\'FLOWABLE_ROOT_PROCESS\')">Root</a>';
  214. for (var i = 0; i < collapsedItemNavigation.length; i++) {
  215. navigationUrl += ' > <a href="javascript:_navigateTo(\'' + collapsedItemNavigation[i].id + '\')">' +
  216. collapsedItemNavigation[i].name + '</a>';
  217. }
  218. $('#navigationTree').html(navigationUrl);
  219. }
  220. function _addHoverLogic(element, type, defaultColor)
  221. {
  222. var strokeColor = _bpmnGetColor(element, defaultColor);
  223. var topBodyRect = null;
  224. if (type === "rect")
  225. {
  226. topBodyRect = paper.rect(element.x, element.y, element.width, element.height);
  227. }
  228. else if (type === "circle")
  229. {
  230. var x = element.x + (element.width / 2);
  231. var y = element.y + (element.height / 2);
  232. topBodyRect = paper.circle(x, y, 15);
  233. }
  234. else if (type === "rhombus")
  235. {
  236. topBodyRect = paper.path("M" + element.x + " " + (element.y + (element.height / 2)) +
  237. "L" + (element.x + (element.width / 2)) + " " + (element.y + element.height) +
  238. "L" + (element.x + element.width) + " " + (element.y + (element.height / 2)) +
  239. "L" + (element.x + (element.width / 2)) + " " + element.y + "z"
  240. );
  241. }
  242. var opacity = 0;
  243. var fillColor = "#ffffff";
  244. if (jQuery.inArray(element.id, elementsAdded) >= 0)
  245. {
  246. opacity = 0.2;
  247. fillColor = "green";
  248. }
  249. if (jQuery.inArray(element.id, elementsRemoved) >= 0)
  250. {
  251. opacity = 0.2;
  252. fillColor = "red";
  253. }
  254. topBodyRect.attr({
  255. "opacity": opacity,
  256. "stroke" : "none",
  257. "fill" : fillColor
  258. });
  259. _showTip(jQuery(topBodyRect.node), element);
  260. topBodyRect.mouseover(function () {
  261. paper.getById(element.id).attr({"stroke": HOVER_COLOR});
  262. });
  263. topBodyRect.mouseout(function () {
  264. paper.getById(element.id).attr({"stroke": _bpmnGetColor(element, defaultColor)});
  265. });
  266. if (isDebuggerEnabled) {
  267. if (element.current || element.brokenExecutions) {
  268. topBodyRect.click(function () {
  269. if (selectedElement != element.id) {
  270. paper.getById(element.id).attr({"stroke": "green"});
  271. selectedElement = element.id;
  272. paper.getById(element.id).attr({"stroke": "red"});
  273. _executionClicked(element.id);
  274. } else {
  275. selectedElement = undefined;
  276. paper.getById(element.id).attr({"stroke": "green"});
  277. var scope = angular.element(document.querySelector('#bpmnModel')).scope();
  278. modelDiv.attr("selected-execution", scope.model.processInstance.id);
  279. scope.model.selectedExecution = scope.model.processInstance.id;
  280. angular.element(document.querySelector('#variablesUi')).scope().loadVariables();
  281. }
  282. });
  283. }
  284. }
  285. }
  286. function _executionClicked(activityId) {
  287. var executions = angular.element(document.querySelector('#bpmnModel')).scope().model.executions;
  288. for (var i in executions) {
  289. if (executions[i]["activityId"] == activityId) {
  290. var activityToUnselect = modelDiv.attr("selected-activity");
  291. if (activityToUnselect) {
  292. var rectangleToUnselect = paper.getById(activityToUnselect);
  293. if (rectangleToUnselect) {
  294. rectangleToUnselect.attr({"stroke": "green"});
  295. }
  296. }
  297. modelDiv.attr("selected-execution", executions[i].id);
  298. modelDiv.attr("selected-activity", activityId);
  299. if (activityId) {
  300. paper.getById(activityId).attr({"stroke": "red"});
  301. }
  302. var scope = angular.element(document.querySelector('#bpmnModel')).scope();
  303. if (scope.gridExecutions.data) {
  304. for (var j = 0; j < scope.gridExecutions.data.length; j++) {
  305. if (executions[i].id == scope.gridExecutions.data[j].id) {
  306. scope.gridExecutionsApi.selection.selectRow(scope.gridExecutions.data[j]);
  307. j = scope.gridExecutions.data.length;
  308. }
  309. }
  310. }
  311. scope.loadVariables();
  312. return;
  313. }
  314. }
  315. }
  316. function _breakpointRestCall(actionType, activityId) {
  317. $.ajax({
  318. type: actionType,
  319. url: '../app/rest/debugger/breakpoints',
  320. contentType: 'application/json; charset=utf-8',
  321. data: JSON.stringify({
  322. activityId: activityId
  323. }),
  324. success: function () {
  325. paper.clear();
  326. angular.element(document.querySelector('#bpmnModel')).scope().getEventLog();
  327. _showProcessDiagram();
  328. }
  329. })
  330. }
  331. function _drawBreakpoint(element, breakpoints) {
  332. var circle = paper.circle(element.x + 10, element.y - 10, 7);
  333. var breakpointFillColor = "white";
  334. var breakpointStrokeColor = "gray";
  335. var breakpointTipText = "Inactive element";
  336. if (element.current) {
  337. breakpointFillColor = "red";
  338. breakpointTipText = "Active execution"
  339. }
  340. if (element.breakpoint) {
  341. breakpointTipText = breakpointTipText + "<br/> Click to remove breakpoint";
  342. breakpointStrokeColor = "red";
  343. circle.click(function () {
  344. _breakpointRestCall("DELETE", element.id);
  345. });
  346. } else {
  347. breakpointTipText = breakpointTipText + "<br/> Click to add breakpoint";
  348. circle.click(function () {
  349. _breakpointRestCall("POST", element.id);
  350. });
  351. }
  352. circle.attr("stroke", breakpointStrokeColor);
  353. circle.attr("stroke-width", "3");
  354. circle.attr("fill", breakpointFillColor);
  355. var circleHtmlNode = jQuery(circle.node);
  356. circleHtmlNode.qtip({
  357. content: {
  358. text: breakpointTipText,
  359. button: false
  360. },
  361. position: {
  362. my: 'top left',
  363. at: 'bottom center',
  364. viewport: jQuery('#bpmnModel')
  365. },
  366. hide: {
  367. fixed: true, delay: 500,
  368. event: 'click mouseleave'
  369. },
  370. style: {
  371. classes: 'ui-tooltip-kisbpm-bpmn'
  372. }
  373. });
  374. }
  375. function _zoom(zoomIn) {
  376. var tmpCanvasWidth, tmpCanvasHeight;
  377. if (zoomIn) {
  378. tmpCanvasWidth = canvasWidth * (1.0 / 0.90);
  379. tmpCanvasHeight = canvasHeight * (1.0 / 0.90);
  380. }
  381. else {
  382. tmpCanvasWidth = canvasWidth * (1.0 / 1.10);
  383. tmpCanvasHeight = canvasHeight * (1.0 / 1.10);
  384. }
  385. if (tmpCanvasWidth != canvasWidth || tmpCanvasHeight != canvasHeight) {
  386. canvasWidth = tmpCanvasWidth;
  387. canvasHeight = tmpCanvasHeight;
  388. paper.setSize(canvasWidth, canvasHeight);
  389. }
  390. }
  391. var modelUrl;
  392. if (modelType == 'runtime') {
  393. if (historyModelId) {
  394. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/history/' + historyModelId + '/model-json';
  395. } else if (isDebuggerEnabled) {
  396. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/debugger/' + modelId + '/model-json';
  397. } else {
  398. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances/' + modelId + '/model-json';
  399. }
  400. } else if (modelType == 'design') {
  401. if (historyModelId) {
  402. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/history/' + historyModelId + '/model-json';
  403. } else {
  404. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/models/' + modelId + '/model-json';
  405. }
  406. } else if (modelType == 'process-definition') {
  407. modelUrl = FLOWABLE.CONFIG.contextRoot + '/app/rest/process-definitions/' + processDefinitionId + '/model-json';
  408. }
  409. function _drawContinueExecution(x, y , executionId, activityId) {
  410. var arrow = paper.path("M "+ x +" "+ y + " L "+ (x+8) +" "+ (y+4) +" "+ x +" "+ (y+8) +" z");
  411. arrow.click(function () {
  412. $.ajax({
  413. type: 'PUT',
  414. url: '../app/rest/debugger/breakpoints/' + executionId + '/continue',
  415. contentType: 'application/json; charset=utf-8',
  416. success: function () {
  417. paper.clear();
  418. var processInstanceId = angular.element(document.querySelector('#bpmnModel')).scope().model.processInstance.id;
  419. modelDiv.attr("selected-execution", processInstanceId);
  420. angular.element(document.querySelector('#bpmnModel')).scope().model.selectedExecution = processInstanceId;
  421. angular.element(document.querySelector('#bpmnModel')).scope().getExecutions();
  422. angular.element(document.querySelector('#bpmnModel')).scope().model.variables = undefined;
  423. angular.element(document.querySelector('#bpmnModel')).scope().loadVariables();
  424. angular.element(document.querySelector('#bpmnModel')).scope().getEventLog();
  425. _showProcessDiagram();
  426. },
  427. error: function () {
  428. alert("error");
  429. }
  430. })
  431. }
  432. );
  433. arrow.attr("stroke", "green");
  434. arrow.attr("stroke-width", "3");
  435. arrow.attr("fill", "green");
  436. var arrowHtmlNode = jQuery(arrow.node);
  437. arrowHtmlNode.qtip({
  438. content: {
  439. text: "Fire execution "+ executionId+", activity " + activityId,
  440. button: false
  441. },
  442. position: {
  443. my: 'top left',
  444. at: 'bottom center',
  445. viewport: jQuery('#bpmnModel')
  446. },
  447. hide: {
  448. fixed: true, delay: 500,
  449. event: 'click mouseleave'
  450. },
  451. style: {
  452. classes: 'ui-tooltip-kisbpm-bpmn'
  453. }
  454. });
  455. }
  456. function _showProcessDiagram() {
  457. var request = jQuery.ajax({
  458. type: 'get',
  459. url: modelUrl + '?nocaching=' + new Date().getTime()
  460. });
  461. request.success(function (data, textStatus, jqXHR) {
  462. if ((!data.elements || data.elements.length == 0) && (!data.pools || data.pools.length == 0)) return;
  463. INITIAL_CANVAS_WIDTH = data.diagramWidth;
  464. if (modelType == 'design') {
  465. INITIAL_CANVAS_WIDTH += 20;
  466. } else {
  467. INITIAL_CANVAS_WIDTH += 30;
  468. }
  469. INITIAL_CANVAS_HEIGHT = data.diagramHeight + 50;
  470. canvasWidth = INITIAL_CANVAS_WIDTH;
  471. canvasHeight = INITIAL_CANVAS_HEIGHT;
  472. viewBoxWidth = INITIAL_CANVAS_WIDTH;
  473. viewBoxHeight = INITIAL_CANVAS_HEIGHT;
  474. if (modelType == 'design') {
  475. var headerBarHeight = 170;
  476. var offsetY = 0;
  477. if (jQuery(window).height() > (canvasHeight + headerBarHeight)) {
  478. offsetY = (jQuery(window).height() - headerBarHeight - canvasHeight) / 2;
  479. }
  480. if (offsetY > 50) {
  481. offsetY = 50;
  482. }
  483. jQuery('#bpmnModel').css('marginTop', offsetY);
  484. }
  485. jQuery('#bpmnModel').width(INITIAL_CANVAS_WIDTH);
  486. jQuery('#bpmnModel').height(INITIAL_CANVAS_HEIGHT);
  487. paper = Raphael(document.getElementById('bpmnModel'), canvasWidth, canvasHeight);
  488. paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);
  489. paper.renderfix();
  490. if (data.pools) {
  491. for (var i = 0; i < data.pools.length; i++) {
  492. var pool = data.pools[i];
  493. _drawPool(pool);
  494. }
  495. }
  496. var modelElements = data.elements;
  497. for (var i = 0; i < modelElements.length; i++) {
  498. var element = modelElements[i];
  499. // try {
  500. var drawFunction = eval("_draw" + element.type);
  501. drawFunction(element);
  502. if (isDebuggerEnabled) {
  503. _drawBreakpoint(element);
  504. if (element.brokenExecutions) {
  505. for (var j = 0; j < element.brokenExecutions.length; j++) {
  506. _drawContinueExecution(element.x + 25 + j * 10, element.y - 15, element.brokenExecutions[j], element.id);
  507. }
  508. }
  509. }
  510. // } catch(err) {console.log(err);}
  511. }
  512. if (data.flows) {
  513. for (var i = 0; i < data.flows.length; i++) {
  514. var flow = data.flows[i];
  515. if (flow.type === 'sequenceFlow') {
  516. _drawFlow(flow);
  517. } else if (flow.type === 'association') {
  518. _drawAssociation(flow);
  519. }
  520. }
  521. }
  522. bpmnData = data;
  523. });
  524. request.error(function (jqXHR, textStatus, errorThrown) {
  525. alert("error");
  526. });
  527. }
  528. _showProcessDiagram();