Browse Source

add flowable

main
wangshaoping 1 year ago
parent
commit
cbef3c5e59
  1. 4
      gradle.properties
  2. 2
      gradle/wrapper/gradle-wrapper.properties
  3. 3
      io.sc.platform.app/build.gradle
  4. 1
      io.sc.platform.core.frontend/.eslintrc.cjs
  5. 2
      io.sc.platform.core.frontend/package.json
  6. 10
      io.sc.platform.core.frontend/src/platform/components/form/PlatformForm.vue
  7. 164
      io.sc.platform.core.frontend/src/platform/components/grid/PlatformGrid.vue
  8. 20
      io.sc.platform.core.frontend/src/platform/components/index.ts
  9. 25
      io.sc.platform.core.frontend/src/platform/index.ts
  10. 1
      io.sc.platform.core.frontend/template-project/.eslintrc.cjs
  11. 7
      io.sc.platform.core.frontend/template-project/package.json
  12. 4
      io.sc.platform.core.frontend/template-project/src/App.vue
  13. 2
      io.sc.platform.core/src/main/java/io/sc/platform/core/bean/RestControllerReturnValueAdviceBean.java
  14. 3
      io.sc.platform.core/src/main/java/io/sc/platform/core/initializer/ApplicationInitializerExecuteException.java
  15. 3
      io.sc.platform.core/src/main/resources/META-INF/platform/plugins/security.json
  16. 4
      io.sc.platform.developer.frontend/package.json
  17. 50
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/AgentWebController.java
  18. 26
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/FlowableModelerEditorWebController.java
  19. 26
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/ProcessEntityWebController.java
  20. 23
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/ProcessQueryWebController.java
  21. 44
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/DatabaseSchemaUpdateInitializer.java
  22. 29
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/SampleWorkFlowSystemDictionaryInitializer.java
  23. 4
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/AgentService.java
  24. 3
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/ProcessQueryService.java
  25. 68
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/AgentServiceImpl.java
  26. 70
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/AssigneeQueryServiceImpl.java
  27. 4
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/FlowableModelerServiceImpl.java
  28. 4
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessEntityServiceImpl.java
  29. 2
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessOperationServiceImpl.java
  30. 6
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessQueryServiceImpl.java
  31. 6
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableGroupList.java
  32. 6
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableUser.java
  33. 10
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableUserList.java
  34. 2
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/util/BpmnConverterUtil.java
  35. 44
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/application-properties.json
  36. 10
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/components.json
  37. 3
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/liquibase.json
  38. 6
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/repositories.json
  39. 6
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/repository.json
  40. 3
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/resources.json
  41. 2
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/security.json
  42. 3
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/web-resource-handlers.json
  43. 1
      io.sc.platform.flowable/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer
  44. 157
      io.sc.platform.flowable/src/main/resources/flowable-modeler/404.html
  45. 9
      io.sc.platform.flowable/src/main/resources/flowable-modeler/browserconfig.xml
  46. 512
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/cmmn-draw.js
  47. 216
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/cmmn-icons.js
  48. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.css
  49. 15
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.html
  50. 272
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.js
  51. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.css
  52. 15
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.html
  53. 270
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.js
  54. 206
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/dmn-draw.js
  55. 182
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/dmn-icons.js
  56. 3
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/.gitignore
  57. 153
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/Gruntfile.js
  58. 387
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/Polyline.js
  59. 880
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/bpmn-draw.js
  60. 395
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/bpmn-icons.js
  61. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.css
  62. 19
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.html
  63. 316
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.js
  64. 2
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/jquery.qtip.min.css
  65. 5
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/jquery.qtip.min.js
  66. 37
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/package.json
  67. 1
      io.sc.platform.flowable/src/main/resources/flowable-modeler/display/raphael.min.js
  68. 19
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/flowable-header-custom.js
  69. 50
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/flowable-toolbar-custom-actions.js
  70. 507
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-assignment-controller.js
  71. 28
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-calledelementtype-controller.js
  72. 86
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-case-reference-controller.js
  73. 59
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-condition-expression-controller.js
  74. 12
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-custom-controllers.js
  75. 330
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-data-properties-controller.js
  76. 288
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-decisionservice-reference-controller.js
  77. 288
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-decisiontable-reference-controller.js
  78. 118
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-default-controllers.js
  79. 126
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-duedate-controller.js
  80. 145
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-escalation-definitions-controller.js
  81. 42
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-escalation-scope-controller.js
  82. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-channel-type-controller.js
  83. 141
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-correlation-parameters-controller.js
  84. 141
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-in-parameters-controller.js
  85. 263
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-listeners-controller.js
  86. 141
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-out-parameters-controller.js
  87. 184
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-exceptions-controller.js
  88. 358
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-execution-listeners-controller.js
  89. 206
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-fields-controller.js
  90. 327
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-form-properties-controller.js
  91. 261
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-form-reference-controller.js
  92. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-httprequest-controller.js
  93. 184
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-in-parameters-controller.js
  94. 145
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-message-definitions-controller.js
  95. 41
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-message-scope-controller.js
  96. 24
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-multiinstance-controller.js
  97. 28
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-ordering-controller.js
  98. 180
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-out-parameters-controller.js
  99. 357
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-plan-item-lifecycle-listeners-controller.js
  100. 82
      io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-planitem-dropdown-controller.js

4
gradle.properties

@ -36,9 +36,9 @@ application_version=1.0.0
# platform # platform
########################################################### ###########################################################
platform_group=io.sc platform_group=io.sc
platform_version=8.1.8 platform_version=8.1.9
platform_plugin_version=8.1.8 platform_plugin_version=8.1.8
platform_core_frontend_version=8.1.14 platform_core_frontend_version=8.1.16
########################################################### ###########################################################
# dependencies version # dependencies version

2
gradle/wrapper/gradle-wrapper.properties

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=http\://nexus.sc.io\:8000/repository/maven-releases/gradle/gradle/8.4/gradle-8.4.zip distributionUrl=http\://nexus.sc.io\:8000/repository/maven-releases/gradle/gradle/8.4/gradle-8.5.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

3
io.sc.platform.app/build.gradle

@ -2,7 +2,7 @@ dependencies {
api( api(
project(":io.sc.platform.csv"), project(":io.sc.platform.csv"),
project(":io.sc.platform.communication"), project(":io.sc.platform.communication"),
//project(":io.sc.platform.flowable"), project(":io.sc.platform.flowable"),
project(":io.sc.platform.groovy"), project(":io.sc.platform.groovy"),
project(":io.sc.platform.jdbc.liquibase"), project(":io.sc.platform.jdbc.liquibase"),
project(":io.sc.platform.jdbc.schemacrawler"), project(":io.sc.platform.jdbc.schemacrawler"),
@ -13,6 +13,7 @@ dependencies {
project(":io.sc.platform.system"), project(":io.sc.platform.system"),
project(":io.sc.platform.ws.cxf"), project(":io.sc.platform.ws.cxf"),
project(":org.webjars.flowable-6.8.0"),
project(":org.webjars.luckysheet-2.1.13"), project(":org.webjars.luckysheet-2.1.13"),
project(":org.webjars.tailwindcss-3.3.5"), project(":org.webjars.tailwindcss-3.3.5"),
) )

1
io.sc.platform.core.frontend/.eslintrc.cjs

@ -32,5 +32,6 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
"@typescript-eslint/no-unused-vars": 'off', "@typescript-eslint/no-unused-vars": 'off',
'vue/multi-word-component-names': 'off', /* 禁用 vue 组件名称检查规则 */ 'vue/multi-word-component-names': 'off', /* 禁用 vue 组件名称检查规则 */
'no-prototype-builtins': 'off',
}, },
}; };

2
io.sc.platform.core.frontend/package.json

@ -1,6 +1,6 @@
{ {
"name": "platform-core", "name": "platform-core",
"version": "8.1.15", "version": "8.1.17",
"description": "前端核心包,用于快速构建前端的脚手架", "description": "前端核心包,用于快速构建前端的脚手架",
"//main": "库的主文件", "//main": "库的主文件",
"main": "dist/platform-core.js", "main": "dist/platform-core.js",

10
io.sc.platform.core.frontend/src/platform/components/form/PlatformForm.vue

@ -210,7 +210,7 @@ const formLayoutComputed = computed(() => {
}); });
const selectDefaultValue = (field) => { const selectDefaultValue = (field) => {
if (field.hasOwnProperty.call('defaultValue') && field.defaultValue !== null) { if (field.hasOwnProperty('defaultValue') && field.defaultValue !== null) {
if (typeof field.defaultValue === 'string' || typeof field.defaultValue === 'boolean' || typeof field.defaultValue === 'number') { if (typeof field.defaultValue === 'string' || typeof field.defaultValue === 'boolean' || typeof field.defaultValue === 'number') {
const dftValue = field.options.filter((item) => { const dftValue = field.options.filter((item) => {
return item.value === field.defaultValue; return item.value === field.defaultValue;
@ -234,7 +234,7 @@ const selectDefaultValue = (field) => {
}; };
const numberDefaultValue = (field) => { const numberDefaultValue = (field) => {
if (field.hasOwnProperty.call('defaultValue') && typeof field.defaultValue === 'number') { if (field.hasOwnProperty('defaultValue') && typeof field.defaultValue === 'number') {
return field.defaultValue; return field.defaultValue;
} else { } else {
return ''; return '';
@ -242,7 +242,7 @@ const numberDefaultValue = (field) => {
}; };
const checkboxDefaultValue = (field) => { const checkboxDefaultValue = (field) => {
if (field.hasOwnProperty.call('defaultValue')) { if (field.hasOwnProperty('defaultValue')) {
return field.defaultValue; return field.defaultValue;
} else { } else {
return false; return false;
@ -250,7 +250,7 @@ const checkboxDefaultValue = (field) => {
}; };
const optionGroupDefaultValue = (field) => { const optionGroupDefaultValue = (field) => {
if (field.hasOwnProperty.call('defaultValue')) { if (field.hasOwnProperty('defaultValue')) {
return field.defaultValue; return field.defaultValue;
} else if (field.optionGroupType && field.optionGroupType === 'checkbox') { } else if (field.optionGroupType && field.optionGroupType === 'checkbox') {
return []; return [];
@ -260,7 +260,7 @@ const optionGroupDefaultValue = (field) => {
}; };
const textDefaultValue = (field) => { const textDefaultValue = (field) => {
if (field.hasOwnProperty.call('defaultValue')) { if (field.hasOwnProperty('defaultValue')) {
return field.defaultValue; return field.defaultValue;
} else { } else {
return ''; return '';

164
io.sc.platform.core.frontend/src/platform/components/grid/PlatformGrid.vue

@ -243,17 +243,22 @@
</template> </template>
</template> </template>
<template v-if="tableRowDrag" #body-cell="scope"> <template v-if="tableRowDrag" #body-cell="scope">
<q-td :props="scope"> <q-td
<PlatformGridTdDrag :props="scope"
v-if="scope.col.field === '_sortNo_'" draggable="true"
:td-value="[scope.rowIndex + 1]" @dragenter="onDragEnter($event, scope)"
:row-index="scope.rowIndex" @dragleave="onDragLeave"
@table-sort-fun="tableSortFun" @dragover="onDragOver($event, scope)"
></PlatformGridTdDrag> @drop="onDrop($event, scope)"
<PlatformGridTdDrag v-else :td-value="[scope.value]" :row-index="scope.rowIndex" @table-sort-fun="tableSortFun"></PlatformGridTdDrag> @dragstart="onDragStart($event, scope)"
<q-tooltip v-if="scope.col.classes?.indexOf('truncate') > -1 && scope.value && typeof scope.value === 'string'"> >
<template v-if="scope.col.field === '_sortNo_'">{{ scope.rowIndex + 1 }}</template>
<template v-else>
{{ scope.value }}
<q-tooltip v-if="scope.col.classes?.indexOf('truncate') > -1">
{{ scope.value }} {{ scope.value }}
</q-tooltip> </q-tooltip>
</template>
</q-td> </q-td>
</template> </template>
<template v-else #body-cell="scope"> <template v-else #body-cell="scope">
@ -349,13 +354,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick, toRaw } from 'vue'; import { ref, reactive, computed, onMounted, nextTick, toRaw } from 'vue';
import { axios, Environment, i18n } from '@/platform'; import { axios, Environment } from '@/platform';
import { useQuasar, getCssVar } from 'quasar'; import { useQuasar, getCssVar } from 'quasar';
import PlatformDialog from '@/platform/components/dialog/PlatformDialog.vue'; import PlatformDialog from '@/platform/components/dialog/PlatformDialog.vue';
import PlatformDrawer from '@/platform/components/drawer/PlatformDrawer.vue'; import PlatformDrawer from '@/platform/components/drawer/PlatformDrawer.vue';
import PlatformInfo from '@/platform/components/panel/PlatformInfo.vue'; import PlatformInfo from '@/platform/components/panel/PlatformInfo.vue';
import PlatformForm from '@/platform/components/form/PlatformForm.vue'; import PlatformForm from '@/platform/components/form/PlatformForm.vue';
import PlatformGridTdDrag from './PlatformGridTdDrag.vue';
import { import {
extractTableProps, extractTableProps,
extractTableColumnsProps, extractTableColumnsProps,
@ -367,7 +371,6 @@ import {
isEmpty, isEmpty,
PageStatusEnum, PageStatusEnum,
PlatformNotifyTypeEnum, PlatformNotifyTypeEnum,
CriteriaType,
} from '@/platform/components/utils'; } from '@/platform/components/utils';
import '@/css/tailwind.css'; import '@/css/tailwind.css';
@ -921,6 +924,12 @@ const onResize = () => {
} }
}; };
type CriteriaType = {
fieldName: string;
operator: OperatorTypeEnum;
value: any;
};
// criteria // criteria
const buildQueryCriterias = (reqParams) => { const buildQueryCriterias = (reqParams) => {
const urlSearchParams = new URLSearchParams(reqParams); const urlSearchParams = new URLSearchParams(reqParams);
@ -1344,34 +1353,6 @@ const stickyHeaderColumn = () => {
} }
}; };
onMounted(() => {
if (extractTableColumns && extractTableColumns.length > props.tableColumns.length) {
handlerMoreRowColumnTitle();
}
if (props.tableInitLoadData) {
onRequest({
pagination: table.pagination,
});
} else {
stickyHeaderColumn();
}
});
defineExpose({
onView,
onDelete,
getSelectedRows,
refreshTable,
replaceRowsFun,
replaceRowFun,
rowClickFun,
getRowsFun,
deleteRowsFun,
addRowFun,
getQueryFormRefFun,
getAddEditFormRefFun,
});
const excludeColumnNum = computed(() => { const excludeColumnNum = computed(() => {
let num = 0; let num = 0;
if (props.tableSelection !== 'none') { if (props.tableSelection !== 'none') {
@ -1578,9 +1559,110 @@ const tableTitleClassComputed = computed(() => {
} }
return classArr; return classArr;
}); });
//
let dragRowIndex;
const onDragStart = (e, scope) => {
dragRowIndex = scope.rowIndex;
e.dataTransfer.dropEffect = 'move';
};
const addDragTopStyle = (e) => {
e.target.parentNode.style.borderTopWidth = '2px';
e.target.parentNode.style.borderTopStyle = 'dashed';
e.target.parentNode.style.borderTopColor = 'orange';
};
const removeDragTopStyle = (e) => {
e.target.parentNode.style.borderTopWidth = '';
e.target.parentNode.style.borderTopStyle = '';
e.target.parentNode.style.borderTopColor = '';
};
const addDragBottomStyle = (e) => {
e.target.parentNode.style.borderBottomWidth = '2px';
e.target.parentNode.style.borderBottomStyle = 'dashed';
e.target.parentNode.style.borderBottomColor = 'orange';
};
const removeDragBottomStyle = (e) => {
e.target.parentNode.style.borderBottomWidth = '';
e.target.parentNode.style.borderBottomStyle = '';
e.target.parentNode.style.borderBottomColor = '';
};
//
const onDragEnter = (e, scope) => {
if (dragRowIndex !== scope.rowIndex && e.target.parentNode.parentNode.children.length === scope.rowIndex + 1) {
//
addDragBottomStyle(e);
} else if (dragRowIndex !== scope.rowIndex) {
addDragTopStyle(e);
}
};
//
const onDragLeave = (e) => {
removeDragTopStyle(e);
removeDragBottomStyle(e);
};
//
const onDragOver = (e, scope) => {
if (e.offsetY >= 24 && dragRowIndex !== scope.rowIndex && e.target.parentNode.parentNode.children.length === scope.rowIndex + 1) {
removeDragTopStyle(e);
addDragBottomStyle(e);
} else if (e.offsetY < 24 && dragRowIndex !== scope.rowIndex && e.target.parentNode.parentNode.children.length === scope.rowIndex + 1) {
removeDragBottomStyle(e);
addDragTopStyle(e);
}
e.preventDefault();
};
//
const onDrop = (e, scope) => {
e.preventDefault();
if (dragRowIndex === scope.rowIndex) {
return;
}
const dragRow = table.rows[dragRowIndex];
if (e.offsetY < 24 && dragRowIndex !== scope.rowIndex && e.target.parentNode.parentNode.children.length === scope.rowIndex + 1) {
table.rows.splice(dragRowIndex, 1);
table.rows.splice(scope.rowIndex - 1, 0, dragRow);
} else {
table.rows.splice(dragRowIndex, 1);
table.rows.splice(scope.rowIndex, 0, dragRow);
}
removeDragTopStyle(e);
removeDragBottomStyle(e);
};
onMounted(() => {
if (extractTableColumns && extractTableColumns.length > props.tableColumns.length) {
handlerMoreRowColumnTitle();
}
if (props.tableInitLoadData) {
onRequest({
pagination: table.pagination,
});
} else {
stickyHeaderColumn();
}
});
defineExpose({
onView,
onDelete,
getSelectedRows,
refreshTable,
replaceRowsFun,
replaceRowFun,
rowClickFun,
getRowsFun,
deleteRowsFun,
addRowFun,
getQueryFormRefFun,
getAddEditFormRefFun,
});
</script> </script>
<style scope lang="css"> <style scoped lang="css">
:deep(.q-table) {
border-collapse: collapse;
}
/** 表格最后一行数据底部边框没有,通过强制覆盖组件样式增加底部边框 */ /** 表格最后一行数据底部边框没有,通过强制覆盖组件样式增加底部边框 */
.q-table--vertical-separator td, .q-table--vertical-separator td,
.q-table--vertical-separator th, .q-table--vertical-separator th,

20
io.sc.platform.core.frontend/src/platform/components/index.ts

@ -44,3 +44,23 @@ export {
PlatformGrid, PlatformGrid,
PlatformGridTdDrag, PlatformGridTdDrag,
}; };
export { PlatformIconEnum } from './utils';
export { PageStatusEnum } from './utils';
export { FormTypeEnum } from './utils';
export { DataTypeEnum } from './utils';
export { OptionComeFromEnum } from './utils';
export { FormComponentValidateEnum } from './utils';
export { OperatorTypeEnum } from './utils';
export type { CriteriaType } from './utils';
export { PlatformNotifyTypeEnum } from './utils';
export { platformNotify } from './utils';
export { isEmpty } from './utils';
export { extractDialogProps } from './utils';
export { extractFormProps } from './utils';
export { extractFormItemComponentProps } from './utils';
export { extractTableProps } from './utils';
export { extractTableColumnsProps } from './utils';
export { getQueryFormColsNumberByScreen } from './utils';
export { arrayToMap } from './utils';

25
io.sc.platform.core.frontend/src/platform/index.ts

@ -57,11 +57,6 @@ export type {
*/ */
export { PConst } from './PConst'; export { PConst } from './PConst';
/**
*
*/
export { IconEnum } from './enums';
/** /**
* *
*/ */
@ -110,3 +105,23 @@ export {
PlatformGrid, PlatformGrid,
PlatformGridTdDrag, PlatformGridTdDrag,
} from './components'; } from './components';
export { PlatformIconEnum } from './components';
export { PageStatusEnum } from './components';
export { FormTypeEnum } from './components';
export { DataTypeEnum } from './components';
export { OptionComeFromEnum } from './components';
export { FormComponentValidateEnum } from './components';
export { OperatorTypeEnum } from './components';
export type { CriteriaType } from './components';
export { PlatformNotifyTypeEnum } from './components';
export { platformNotify } from './components';
export { isEmpty } from './components';
export { extractDialogProps } from './components';
export { extractFormProps } from './components';
export { extractFormItemComponentProps } from './components';
export { extractTableProps } from './components';
export { extractTableColumnsProps } from './components';
export { getQueryFormColsNumberByScreen } from './components';
export { arrayToMap } from './components';

1
io.sc.platform.core.frontend/template-project/.eslintrc.cjs

@ -32,5 +32,6 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
"@typescript-eslint/no-unused-vars": 'off', "@typescript-eslint/no-unused-vars": 'off',
'vue/multi-word-component-names': 'off', /* 禁用 vue 组件名称检查规则 */ 'vue/multi-word-component-names': 'off', /* 禁用 vue 组件名称检查规则 */
'no-prototype-builtins': 'off',
}, },
}; };

7
io.sc.platform.core.frontend/template-project/package.json

@ -1,6 +1,6 @@
{ {
"name": "platform-core", "name": "platform-core",
"version": "8.1.15", "version": "8.1.17",
"description": "前端核心包,用于快速构建前端的脚手架", "description": "前端核心包,用于快速构建前端的脚手架",
"private": false, "private": false,
"keywords": [], "keywords": [],
@ -20,7 +20,8 @@
}, },
"publishConfig": { "publishConfig": {
"registry": "http://nexus.sc.io:8000/repository/npm-releases/", "registry": "http://nexus.sc.io:8000/repository/npm-releases/",
"access": "public" "access": "public",
"no-git-checks": true
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.23.2", "@babel/core": "7.23.2",
@ -77,7 +78,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.15", "platform-core": "8.1.17",
"quasar": "2.13.0", "quasar": "2.13.0",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"vue": "3.3.7", "vue": "3.3.7",

4
io.sc.platform.core.frontend/template-project/src/App.vue

@ -2,6 +2,4 @@
<w-platform-page></w-platform-page> <w-platform-page></w-platform-page>
</template> </template>
<script setup lang="ts"> <script setup lang="ts"></script>
</script>

2
io.sc.platform.core/src/main/java/io/sc/platform/core/bean/RestControllerReturnValueAdviceBean.java

@ -41,7 +41,7 @@ public class RestControllerReturnValueAdviceBean implements ResponseBodyAdvice<O
* 2. 控制器类不能存在 @IgnoreResponseBodyAdvice 注解 * 2. 控制器类不能存在 @IgnoreResponseBodyAdvice 注解
* 3. 控制器类的方法上不能存在 @IgnoreResponseBodyAdvice 注解 * 3. 控制器类的方法上不能存在 @IgnoreResponseBodyAdvice 注解
* @param methodParameter the return type * @param methodParameter the return type
* @param converterType the selected converter type * @param converterType the selected convertor type
* @return 是否支持 * @return 是否支持
*/ */
@Override @Override

3
io.sc.platform.core/src/main/java/io/sc/platform/core/initializer/ApplicationInitializerExecuteException.java

@ -1,4 +1,7 @@
package io.sc.platform.core.initializer; package io.sc.platform.core.initializer;
public class ApplicationInitializerExecuteException extends RuntimeException { public class ApplicationInitializerExecuteException extends RuntimeException {
public ApplicationInitializerExecuteException(Throwable cause) {
super(cause);
}
} }

3
io.sc.platform.core/src/main/resources/META-INF/platform/plugins/security.json

@ -13,6 +13,7 @@
"/**/*.eot", "/**/*.eot",
"/**/*.ttf", "/**/*.ttf",
"/**/*.otf", "/**/*.otf",
"/**/*.map" "/**/*.map",
"/**/*.json"
] ]
} }

4
io.sc.platform.developer.frontend/package.json

@ -1,6 +1,6 @@
{ {
"name": "io.sc.platform.developer.frontend", "name": "io.sc.platform.developer.frontend",
"version": "8.1.8", "version": "8.1.9",
"description": "", "description": "",
"private": false, "private": false,
"keywords": [ "keywords": [
@ -79,7 +79,7 @@
"luckyexcel": "1.0.1", "luckyexcel": "1.0.1",
"mockjs": "1.1.0", "mockjs": "1.1.0",
"pinia": "2.1.7", "pinia": "2.1.7",
"platform-core": "8.1.14", "platform-core": "8.1.16",
"quasar": "2.13.0", "quasar": "2.13.0",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"vue": "3.3.7", "vue": "3.3.7",

50
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/AgentWebController.java

@ -5,62 +5,32 @@ import io.sc.platform.flowable.jpa.repository.AgentRepository;
import io.sc.platform.flowable.service.AgentService; import io.sc.platform.flowable.service.AgentService;
import io.sc.platform.mvc.controller.support.RestCrudController; import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.security.util.SecurityUtil; import io.sc.platform.security.util.SecurityUtil;
import io.sc.platform.system.api.user.User; import io.sc.platform.system.api.user.UserVo;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.jpa.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Controller @RestController
@RequestMapping("/api/system/agent") @RequestMapping("/api/system/agent")
public class AgentWebController extends RestCrudController<Agent,String, AgentRepository, AgentService> { public class AgentWebController extends RestCrudController<Agent,String, AgentRepository, AgentService> {
@Autowired private UserRepository userRepository; @GetMapping("getAvailableAgent")
public List<UserVo> getAvailableAgent() throws Exception{
@RequestMapping(value="getAvailableAgent",method=RequestMethod.GET)
@ResponseBody
public List<User> getAvailableAgent() throws Exception{
return service.listAvailableAgentByUserId(SecurityUtil.getUserId()); return service.listAvailableAgentByUserId(SecurityUtil.getUserId());
} }
@Override @PostMapping("isc/agree/{id}")
protected ResponseWrapper<Agent> iscAdd(HttpServletRequest request, HttpServletResponse response,@Valid IscRequest<Agent> iscRequest, BindingResult bindingResult) throws Exception { public Agent agree(@PathVariable(name="id")String id){
if(iscRequest!=null) { return service.agree(id);
Agent agent =iscRequest.getData();
if(agent!=null) {
String agentLoginName =agent.getAgentLoginName();
User user =userRepository.findByLoginName(agentLoginName);
if(user!=null) {
agent.setLoginName(SecurityUtil.getLoginName());
agent.setUserName(SecurityUtil.getNickName());
agent.setAgentUserName(user.getNickName());
}
}
}
return super.iscAdd(request, response, iscRequest, bindingResult);
}
@RequestMapping(value="isc/agree/{id}",method=RequestMethod.GET)
@ResponseBody
public ResponseWrapper<Agent> agree(@PathVariable(name="id")String id){
return ResponseWrapperBuilder.crud(service.agree(id));
} }
@RequestMapping(value="isc/reject/{id}",method=RequestMethod.POST) @PostMapping("isc/reject/{id}")
@ResponseBody public Agent reject(@PathVariable(name="id")String id,@RequestBody Map<String,String> data){
public ResponseWrapper<Agent> reject(@PathVariable(name="id")String id,@RequestBody Map<String,String> data){
String comments =null; String comments =null;
if(data!=null) { if(data!=null) {
comments =data.get("comments"); comments =data.get("comments");
} }
return ResponseWrapperBuilder.crud(service.reject(id,comments)); return service.reject(id,comments);
} }
} }

26
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/FlowableModelerEditorWebController.java

@ -12,7 +12,11 @@ import io.sc.platform.flowable.support.FlowableGroupList;
import io.sc.platform.flowable.support.FlowableUser; import io.sc.platform.flowable.support.FlowableUser;
import io.sc.platform.flowable.support.FlowableUserList; import io.sc.platform.flowable.support.FlowableUserList;
import io.sc.platform.orm.service.support.QueryParameter; import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.system.role.convertor.RoleEntityVoConverter;
import io.sc.platform.system.role.jpa.entity.RoleEntity;
import io.sc.platform.system.role.service.RoleService; import io.sc.platform.system.role.service.RoleService;
import io.sc.platform.system.user.convertor.UserEntityVoConverter;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.service.UserService; import io.sc.platform.system.user.service.UserService;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.BpmnModel;
@ -23,6 +27,8 @@ import org.flowable.validation.ValidationError;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -34,6 +40,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import javax.persistence.criteria.Join;
/** /**
* 流程设计器控制器 * 流程设计器控制器
* @author wangshaoping * @author wangshaoping
@ -125,18 +133,19 @@ public class FlowableModelerEditorWebController {
} }
/** /**
* 获取用户列表用于流程设计器在选择任务分配策略时选择人物执行人 * 获取用户列表用于流程设计器在选择任务分配策略时选择执行人
* @param filter 过滤用户条件 * @param filter 过滤用户条件
* @return 符合 filter 条件的用户列表 * @return 符合 filter 条件的用户列表
* @throws Exception 违例 * @throws Exception 违例
*/ */
@RequestMapping(value = "app/rest/editor-users",method=RequestMethod.GET) @RequestMapping(value = "app/rest/editor-users",method=RequestMethod.GET)
@ResponseBody @ResponseBody
public FlowableUserList editorUsers(@RequestParam(name="filter",required=false) String filter) throws Exception{ public FlowableUserList editorUsers(@RequestParam(name="filter",required=false) String filter,QueryParameter queryParameter) throws Exception{
User queryExampleEntity =new User(); Specification<UserEntity> specification = (root, query, criteriaBuilder) -> {
queryExampleEntity.setLoginName(filter); return criteriaBuilder.like(root.get("loginName"),filter);
QueryParameter queryParameter =new QueryParameter(); };
return FlowableUserList.fromUsers(userService.query(queryExampleEntity, queryParameter)); Page<UserEntity> userEntities =userService.query(specification,queryParameter);
return FlowableUserList.fromUsers(new UserEntityVoConverter().toVo(userEntities));
} }
/** /**
@ -147,7 +156,8 @@ public class FlowableModelerEditorWebController {
*/ */
@RequestMapping(value = "app/rest/editor-groups",method=RequestMethod.GET) @RequestMapping(value = "app/rest/editor-groups",method=RequestMethod.GET)
@ResponseBody @ResponseBody
public FlowableGroupList editorGroups(@RequestParam(name="filter",required=false) String filter) throws Exception{ public FlowableGroupList editorGroups(@RequestParam(name="filter",required=false) String filter,QueryParameter queryParameter) throws Exception{
return FlowableGroupList.fromGroups(roleService.listRolesByCodeOrName(filter)); Page<RoleEntity> roleEntities =roleService.queryRolesByCodeOrName(filter,queryParameter);
return FlowableGroupList.fromGroups(new RoleEntityVoConverter().toVo(roleEntities));
} }
} }

26
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/ProcessEntityWebController.java

@ -4,33 +4,15 @@ import io.sc.platform.flowable.jpa.entity.ProcessEntity;
import io.sc.platform.flowable.jpa.repository.ProcessEntityRepository; import io.sc.platform.flowable.jpa.repository.ProcessEntityRepository;
import io.sc.platform.flowable.service.ProcessEntityService; import io.sc.platform.flowable.service.ProcessEntityService;
import io.sc.platform.mvc.controller.support.RestCrudController; import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.security.util.SecurityUtil;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller @RestController
@RequestMapping("/api/system/process") @RequestMapping("/api/system/process")
public class ProcessEntityWebController extends RestCrudController<ProcessEntity,String, ProcessEntityRepository, ProcessEntityService> { public class ProcessEntityWebController extends RestCrudController<ProcessEntity,String, ProcessEntityRepository, ProcessEntityService> {
//========================================================================================================= @PostMapping("deploy/{id}")
// 菜单入口
//=========================================================================================================
/**
* 流程管理页面
* @param model 模型
* @return 流程管理页面
*/
@RequestMapping("process.html")
public String process(Model model){
model.addAttribute("loginName", SecurityUtil.getLoginName());
return "org/wsp/framework/flowable/view/process.html";
}
@RequestMapping(value="deploy/{id}",method=RequestMethod.POST)
@ResponseBody
public void deploy(@PathVariable(name="id") String id) throws Exception{ public void deploy(@PathVariable(name="id") String id) throws Exception{
service.deploy(id); service.deploy(id);
} }

23
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/controller/ProcessQueryWebController.java

@ -3,12 +3,15 @@ package io.sc.platform.flowable.controller;
import io.sc.platform.flowable.service.ProcessQueryService; import io.sc.platform.flowable.service.ProcessQueryService;
import io.sc.platform.flowable.support.*; import io.sc.platform.flowable.support.*;
import io.sc.platform.mvc.support.FileDownloader; import io.sc.platform.mvc.support.FileDownloader;
import io.sc.platform.orm.service.support.QueryParameter;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
@RestController @RestController
@RequestMapping("/api/system/process/query") @RequestMapping("/api/system/process/query")
@ -37,34 +40,34 @@ public class ProcessQueryWebController {
@RequestMapping(value="instance/isc/fetch", method=RequestMethod.GET) @RequestMapping(value="instance/isc/fetch", method=RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseWrapper<ProcessInstanceWrapper> processInstanceQuery(@RequestParam(name="businessKey",required=false)String businessKey, ProcessEntity queryExampleEntity, QueryParameter queryParameter) throws Exception{ public Page<ProcessInstanceWrapper> processInstanceQuery(@RequestParam(name="businessKey",required=false)String businessKey, QueryParameter queryParameter) throws Exception{
return ResponseWrapperBuilder.query(service.queryProcessInstances(businessKey,queryExampleEntity,queryParameter)); return service.queryProcessInstances(businessKey,queryParameter);
} }
@RequestMapping(value="task/isc/fetch", method=RequestMethod.GET) @RequestMapping(value="task/isc/fetch", method=RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseWrapper<ProcessTaskWrapper> taskQuery(@RequestParam(name="processInstanceId",required=false) String processInstanceId, QueryParameter queryParameter) throws Exception{ public List<ProcessTaskWrapper> taskQuery(@RequestParam(name="processInstanceId",required=false) String processInstanceId, QueryParameter queryParameter) throws Exception{
return ResponseWrapperBuilder.query(service.queryProcessTasks(processInstanceId,queryParameter)); return service.queryProcessTasks(processInstanceId,queryParameter);
} }
@RequestMapping(value="variable/isc/fetch", method=RequestMethod.GET) @RequestMapping(value="variable/isc/fetch", method=RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseWrapper<VariableWrapper> variableQuery(@RequestParam(name="procInstId",required=false) String procInstId) throws Exception{ public List<VariableWrapper> variableQuery(@RequestParam(name="procInstId",required=false) String procInstId) throws Exception{
return ResponseWrapperBuilder.query(service.queryVariables(procInstId)); return service.queryVariables(procInstId);
} }
@RequestMapping(value="activity/isc/fetch", method=RequestMethod.GET) @RequestMapping(value="activity/isc/fetch", method=RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseWrapper<UserTaskDefinitionWrapper> activityQuery(@RequestParam(name="taskId",required=false) String taskId) throws Exception{ public List<UserTaskDefinitionWrapper> activityQuery(@RequestParam(name="taskId",required=false) String taskId) throws Exception{
return ResponseWrapperBuilder.query(service.queryUserTaskDefinition(taskId)); return service.queryUserTaskDefinition(taskId);
} }
@RequestMapping(value="candidate/isc/fetch", method=RequestMethod.GET) @RequestMapping(value="candidate/isc/fetch", method=RequestMethod.GET)
@ResponseBody @ResponseBody
public ResponseWrapper<Assignee> candidateQuery( public List<Assignee> candidateQuery(
@RequestParam(name="taskId",required=false) String taskId, @RequestParam(name="taskId",required=false) String taskId,
@RequestParam(name="activityId",required=false) String activityId @RequestParam(name="activityId",required=false) String activityId
) throws Exception{ ) throws Exception{
return ResponseWrapperBuilder.query(service.queryCandidate(taskId,activityId)); return service.queryCandidate(taskId,activityId);
} }
} }

44
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/DatabaseSchemaUpdateInitializer.java

@ -1,44 +0,0 @@
package io.sc.platform.flowable.initializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.wsp.framework.core.service.ApplicationPropertiesService;
import org.wsp.framework.core.service.support.ApplicationInitializer;
@Component
public class DatabaseSchemaUpdateInitializer implements ApplicationInitializer{
@Autowired private ApplicationPropertiesService applicationPropertiesService;
@Autowired private Environment environment;
@Override
public String getId() {
return this.getClass().getName();
}
@Override
public String getName() {
return "Flowable Database Schema Update Initializer";
}
@Override
public String getDescription() {
return "Flowable Database Schema Update Initializer";
}
@Override
public int getOrder() {
return 11000;
}
@Override
public boolean isInitialized() {
return !environment.getProperty("flowable.databaseSchemaUpdate", Boolean.class, true);
}
@Override
public void execute() throws Exception {
applicationPropertiesService.setProperty("flowable.databaseSchemaUpdate", "false");
applicationPropertiesService.persist();
}
}

29
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/SampleWorkFlowSystemDictionaryInitializer.java

@ -1,14 +1,19 @@
package io.sc.platform.flowable.initializer; package io.sc.platform.flowable.initializer;
import org.springframework.beans.factory.annotation.Autowired; import io.sc.platform.core.initializer.ApplicationInitializer;
import org.springframework.stereotype.Component; import io.sc.platform.core.initializer.ApplicationInitializerExecuteException;
import org.wsp.framework.core.service.support.ApplicationInitializer; import io.sc.platform.core.util.BeanUtil;
import org.wsp.framework.system.dictionary.entity.SystemDictionary; import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import org.wsp.framework.system.dictionary.service.SystemDictionaryService; import io.sc.platform.system.dictionary.service.DictionaryService;
import org.springframework.context.ApplicationContext;
@Component
public class SampleWorkFlowSystemDictionaryInitializer implements ApplicationInitializer { public class SampleWorkFlowSystemDictionaryInitializer implements ApplicationInitializer {
@Autowired private SystemDictionaryService systemDictionaryService; private DictionaryService dictionaryService;
@Override
public void init(ApplicationContext applicationContext) {
this.dictionaryService = BeanUtil.getBean(applicationContext,DictionaryService.class);
}
@Override @Override
public String getId() { public String getId() {
@ -32,15 +37,15 @@ public class SampleWorkFlowSystemDictionaryInitializer implements ApplicationIni
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return systemDictionaryService.getRepository().count()>0; return dictionaryService.getRepository().count()>0;
} }
@Override @Override
public void execute() throws Exception { public void execute() throws ApplicationInitializerExecuteException {
SystemDictionary item =new SystemDictionary(); DictionaryEntity item =new DictionaryEntity();
item.setCode("WORK_FLOW"); item.setCode("WORK_FLOW");
item.setKey("SAMPLE"); item.setValue("SAMPLE");
item.setOrder(0); item.setOrder(0);
systemDictionaryService.getRepository().save(item); dictionaryService.getRepository().save(item);
} }
} }

4
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/AgentService.java

@ -3,7 +3,7 @@ package io.sc.platform.flowable.service;
import io.sc.platform.flowable.jpa.entity.Agent; import io.sc.platform.flowable.jpa.entity.Agent;
import io.sc.platform.flowable.jpa.repository.AgentRepository; import io.sc.platform.flowable.jpa.repository.AgentRepository;
import io.sc.platform.orm.service.DaoService; import io.sc.platform.orm.service.DaoService;
import io.sc.platform.system.api.user.User; import io.sc.platform.system.api.user.UserVo;
import java.util.List; import java.util.List;
@ -20,7 +20,7 @@ public interface AgentService extends DaoService<Agent, String, AgentRepository>
* @param userId 用户ID * @param userId 用户ID
* @return 该用户可选的代理人列表 * @return 该用户可选的代理人列表
*/ */
public List<User> listAvailableAgentByUserId(String userId); public List<UserVo> listAvailableAgentByUserId(String userId) throws Exception;
/** /**
* 同意成为对方的代理人 * 同意成为对方的代理人

3
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/ProcessQueryService.java

@ -36,12 +36,11 @@ public interface ProcessQueryService {
/** /**
* 查询流程实例 * 查询流程实例
* @param businessKey 业务主键 * @param businessKey 业务主键
* @param queryExampleEntity 流程定义实体实例查询对象
* @param queryParameter 查询参数 * @param queryParameter 查询参数
* @return 流程实例 * @return 流程实例
* @throws Exception 违例 * @throws Exception 违例
*/ */
public Page<ProcessInstanceWrapper> queryProcessInstances(String businessKey, ProcessEntity queryExampleEntity, QueryParameter queryParameter) throws Exception; public Page<ProcessInstanceWrapper> queryProcessInstances(String businessKey, QueryParameter queryParameter) throws Exception;
/** /**
* 查询任务 * 查询任务

68
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/AgentServiceImpl.java

@ -1,25 +1,30 @@
package io.sc.platform.flowable.service.impl; package io.sc.platform.flowable.service.impl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import io.sc.platform.flowable.jpa.entity.Agent; import io.sc.platform.flowable.jpa.entity.Agent;
import io.sc.platform.flowable.jpa.repository.AgentRepository; import io.sc.platform.flowable.jpa.repository.AgentRepository;
import io.sc.platform.flowable.service.AgentService; import io.sc.platform.flowable.service.AgentService;
import io.sc.platform.orm.service.impl.DaoServiceImpl; import io.sc.platform.orm.service.impl.DaoServiceImpl;
import io.sc.platform.system.api.role.Role; import io.sc.platform.system.api.role.RoleVo;
import io.sc.platform.system.api.user.User; import io.sc.platform.system.api.user.UserVo;
import io.sc.platform.system.role.jpa.repository.RoleRepository; import io.sc.platform.system.role.jpa.entity.RoleEntity;
import io.sc.platform.system.user.jpa.repository.UserRepository; import io.sc.platform.system.role.service.RoleService;
import io.sc.platform.system.user.convertor.UserEntityVoConverter;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service("frAgentService") import javax.persistence.criteria.Join;
@Service
public class AgentServiceImpl extends DaoServiceImpl<Agent, String, AgentRepository> implements AgentService { public class AgentServiceImpl extends DaoServiceImpl<Agent, String, AgentRepository> implements AgentService {
@Autowired @Autowired private UserService userService;
RoleRepository roleRepository; @Autowired private RoleService roleService;
@Autowired
UserRepository userRepository;
@Override @Override
public List<Agent> getAgents(String loginName) { public List<Agent> getAgents(String loginName) {
@ -27,33 +32,35 @@ public class AgentServiceImpl extends DaoServiceImpl<Agent, String, AgentReposit
} }
@Override @Override
public List<User> listAvailableAgentByUserId(String userId){ public List<UserVo> listAvailableAgentByUserId(String userId) throws Exception{
List<Role> roles =listRolesByUser(userId); List<RoleEntity> roleEntities =roleService.listRolesByUser(userId);
List<String> roleIds =new ArrayList<String>(); List<String> roleIds =new ArrayList<String>();
if(roles!=null && roles.size()>0){ if(roleEntities!=null && !roleEntities.isEmpty()){
for(Role role : roles){ for(RoleEntity roleEntity : roleEntities){
roleIds.add(role.getId()); roleIds.add(roleEntity.getId());
} }
} }
BooleanBuilder builder =new BooleanBuilder();
QUser q =QUser.user; Specification<UserEntity> specification = (root, query, criteriaBuilder) -> {
builder.and(q.roles.any().id.in(roleIds)); Join<RoleEntity,UserEntity> join = root.join("roles");
List<User> users =IterableUtil.toList(userRepository.findAll(builder.getValue())); return join.get("id").in(roleIds);
if(users!=null && users.size()>0){ };
List<User> result =new ArrayList<User>(); List<UserEntity> userEntities =userService.list(specification);
for(User user : users){ if(userEntities!=null && !userEntities.isEmpty()){
if(!userId.equals(user.getId())){ List<UserEntity> result =new ArrayList<>();
result.add(user); for(UserEntity userEntity : userEntities){
if(!userId.equals(userEntity.getId())){
result.add(userEntity);
} }
} }
return result; return new UserEntityVoConverter().toVo(result);
} }
return null; return Collections.emptyList();
} }
@Override @Override
public Agent agree(String agentId) { public Agent agree(String agentId) {
Agent agent =repository.findOne(agentId); Agent agent =repository.getOne(agentId);
if(agent!=null) { if(agent!=null) {
agent.setEffective(true); agent.setEffective(true);
return repository.save(agent); return repository.save(agent);
@ -63,7 +70,7 @@ public class AgentServiceImpl extends DaoServiceImpl<Agent, String, AgentReposit
@Override @Override
public Agent reject(String agentId, String comments) { public Agent reject(String agentId, String comments) {
Agent agent =repository.findOne(agentId); Agent agent =repository.getOne(agentId);
if(agent!=null) { if(agent!=null) {
agent.setEffective(false); agent.setEffective(false);
agent.setComments(comments); agent.setComments(comments);
@ -71,11 +78,4 @@ public class AgentServiceImpl extends DaoServiceImpl<Agent, String, AgentReposit
} }
return null; return null;
} }
private List<Role> listRolesByUser(String userId) {
BooleanBuilder builder =new BooleanBuilder();
QRole q =QRole.role;
builder.and(q.users.any().id.eq(userId));
return IterableUtil.toList(roleRepository.findAll(builder.getValue()));
}
} }

70
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/AssigneeQueryServiceImpl.java

@ -2,7 +2,11 @@ package io.sc.platform.flowable.service.impl;
import io.sc.platform.flowable.service.AssigneeQueryService; import io.sc.platform.flowable.service.AssigneeQueryService;
import io.sc.platform.flowable.support.Assignee; import io.sc.platform.flowable.support.Assignee;
import io.sc.platform.security.util.SecurityUtil;
import io.sc.platform.system.org.jpa.entity.OrgEntity;
import io.sc.platform.system.role.jpa.entity.RoleEntity;
import io.sc.platform.system.role.service.RoleService; import io.sc.platform.system.role.service.RoleService;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.service.UserService; import io.sc.platform.system.user.service.UserService;
import org.flowable.bpmn.model.UserTask; import org.flowable.bpmn.model.UserTask;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
@ -12,7 +16,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service("frAssigneeQueryService") @Service("platformAssigneeQueryService")
public class AssigneeQueryServiceImpl implements AssigneeQueryService { public class AssigneeQueryServiceImpl implements AssigneeQueryService {
@Autowired private UserService userService; @Autowired private UserService userService;
@Autowired private RoleService roleService; @Autowired private RoleService roleService;
@ -23,14 +27,14 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
List<String> candidateGroups =newUserTaskDefinition.getCandidateGroups(); List<String> candidateGroups =newUserTaskDefinition.getCandidateGroups();
if(candidateUsers!=null && candidateUsers.size()>0){ if(candidateUsers!=null && candidateUsers.size()>0){
List<User> users =userService.getRepository().findByLoginNameIn(candidateUsers); List<UserEntity> users =userService.getRepository().findByLoginNameIn(candidateUsers);
if(users!=null && users.size()>0){ if(users!=null && !users.isEmpty()){
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<>();
for(User user : users){ for(UserEntity user : users){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(user.getId()); assignee.setId(user.getId());
assignee.setLoginName(user.getLoginName()); assignee.setLoginName(user.getLoginName());
assignee.setUserName(user.getNickName()); assignee.setUserName(user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;
@ -39,31 +43,31 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
if(candidateGroups!=null && candidateGroups.size()>0){ if(candidateGroups!=null && candidateGroups.size()>0){
//通过定义的组(角色)获取所包含的所有用户 //通过定义的组(角色)获取所包含的所有用户
List<User> roleUsers =null; List<UserEntity> roleUsers =null;
List<Role> roles =roleService.getRepository().findByCodeIn(candidateGroups); List<RoleEntity> roles =roleService.getRepository().findByCodeIn(candidateGroups);
if(roles!=null && roles.size()>0){ if(roles!=null && !roles.isEmpty()){
List<String> roleIds =new ArrayList<String>(); List<String> roleIds =new ArrayList<String>();
for(Role role : roles){ for(RoleEntity role : roles){
roleIds.add(role.getId()); roleIds.add(role.getId());
} }
roleUsers =userService.listUsersByRoles(roleIds); roleUsers =userService.listUsersByRoles(roleIds);
} }
if(roleUsers==null || roleUsers.size()==0){ if(roleUsers==null || roleUsers.isEmpty()){
return null; return null;
} }
String preAssignee =(task==null? SecurityUtil.getLoginName():task.getAssignee()); String preAssignee =(task==null? SecurityUtil.getLoginName():task.getAssignee());
User user =userService.getRepository().findByLoginName(preAssignee); UserEntity user =userService.getRepository().findByLoginName(preAssignee);
//如果未找到前一处理人,直接返回角色下面的用户 //如果未找到前一处理人,直接返回角色下面的用户
if(user==null) { if(user==null) {
if(roleUsers!=null && roleUsers.size()>0){ if(roleUsers!=null && roleUsers.size()>0){
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<>();
for(User _user : roleUsers){ for(UserEntity _user : roleUsers){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(_user.getId()); assignee.setId(_user.getId());
assignee.setLoginName(_user.getLoginName()); assignee.setLoginName(_user.getLoginName());
assignee.setUserName(_user.getNickName()); assignee.setUserName(_user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;
@ -73,12 +77,12 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
} }
//所有机构及其父机构 //所有机构及其父机构
List<Org> orgAndParentOrgs =new ArrayList<Org>(); List<OrgEntity> orgAndParentOrgs =new ArrayList<OrgEntity>();
List<Org> orgs =user.getOrgs(); List<OrgEntity> orgs =user.getOrgs();
if(orgs!=null && orgs.size()>0){ if(orgs!=null && orgs.size()>0){
for(Org org : orgs){ for(OrgEntity org : orgs){
orgAndParentOrgs.add(org); orgAndParentOrgs.add(org);
Org parentOrg =org.getParent(); OrgEntity parentOrg =org.getParent();
while(parentOrg!=null){ while(parentOrg!=null){
orgAndParentOrgs.add(parentOrg); orgAndParentOrgs.add(parentOrg);
parentOrg =parentOrg.getParent(); parentOrg =parentOrg.getParent();
@ -87,19 +91,19 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
} }
List<String> orgIds =new ArrayList<String>(); List<String> orgIds =new ArrayList<String>();
for(Org org : orgAndParentOrgs){ for(OrgEntity org : orgAndParentOrgs){
orgIds.add(org.getId()); orgIds.add(org.getId());
} }
List<User> orgUsers =userService.listUsersByOrgs(orgIds); List<UserEntity> orgUsers =userService.listUsersByOrgs(orgIds);
if(orgUsers==null || orgUsers.size()==0){ if(orgUsers==null || orgUsers.size()==0){
//目前对于没有机构配置的情况,直接返回角色的人 //目前对于没有机构配置的情况,直接返回角色的人
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<Assignee>();
for(User _user : roleUsers){ for(UserEntity _user : roleUsers){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(_user.getId()); assignee.setId(_user.getId());
assignee.setLoginName(_user.getLoginName()); assignee.setLoginName(_user.getLoginName());
assignee.setUserName(_user.getNickName()); assignee.setUserName(_user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;
@ -109,11 +113,11 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
orgUsers.retainAll(roleUsers); orgUsers.retainAll(roleUsers);
if(orgUsers!=null && orgUsers.size()>0){ if(orgUsers!=null && orgUsers.size()>0){
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<Assignee>();
for(User _user : orgUsers){ for(UserEntity _user : orgUsers){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(_user.getId()); assignee.setId(_user.getId());
assignee.setLoginName(_user.getLoginName()); assignee.setLoginName(_user.getLoginName());
assignee.setUserName(_user.getNickName()); assignee.setUserName(_user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;
@ -128,14 +132,14 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
List<String> candidateGroups =newUserTaskDefinition.getCandidateGroups(); List<String> candidateGroups =newUserTaskDefinition.getCandidateGroups();
if(candidateUsers!=null && candidateUsers.size()>0){ if(candidateUsers!=null && candidateUsers.size()>0){
List<User> users =userService.getRepository().findByLoginNameIn(candidateUsers); List<UserEntity> users =userService.getRepository().findByLoginNameIn(candidateUsers);
if(users!=null && users.size()>0){ if(users!=null && users.size()>0){
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<Assignee>();
for(User user : users){ for(UserEntity user : users){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(user.getId()); assignee.setId(user.getId());
assignee.setLoginName(user.getLoginName()); assignee.setLoginName(user.getLoginName());
assignee.setUserName(user.getNickName()); assignee.setUserName(user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;
@ -144,21 +148,21 @@ public class AssigneeQueryServiceImpl implements AssigneeQueryService {
if(candidateGroups!=null && candidateGroups.size()>0){ if(candidateGroups!=null && candidateGroups.size()>0){
//通过定义的组(角色)获取所包含的所有用户 //通过定义的组(角色)获取所包含的所有用户
List<User> roleUsers =null; List<UserEntity> roleUsers =null;
List<Role> roles =roleService.getRepository().findByCodeIn(candidateGroups); List<RoleEntity> roles =roleService.getRepository().findByCodeIn(candidateGroups);
if(roles!=null && roles.size()>0){ if(roles!=null && roles.size()>0){
List<String> roleIds =new ArrayList<String>(); List<String> roleIds =new ArrayList<String>();
for(Role role : roles){ for(RoleEntity role : roles){
roleIds.add(role.getId()); roleIds.add(role.getId());
} }
roleUsers =userService.listUsersByRoles(roleIds); roleUsers =userService.listUsersByRoles(roleIds);
if(roleUsers!=null && roleUsers.size()>0) { if(roleUsers!=null && roleUsers.size()>0) {
List<Assignee> candidateUserAssignees =new ArrayList<Assignee>(); List<Assignee> candidateUserAssignees =new ArrayList<Assignee>();
for(User user : roleUsers){ for(UserEntity user : roleUsers){
Assignee assignee =new Assignee(); Assignee assignee =new Assignee();
assignee.setId(user.getId()); assignee.setId(user.getId());
assignee.setLoginName(user.getLoginName()); assignee.setLoginName(user.getLoginName());
assignee.setUserName(user.getNickName()); assignee.setUserName(user.getUserName());
candidateUserAssignees.add(assignee); candidateUserAssignees.add(assignee);
} }
return candidateUserAssignees; return candidateUserAssignees;

4
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/FlowableModelerServiceImpl.java

@ -31,7 +31,7 @@ public class FlowableModelerServiceImpl implements FlowableModelerService {
@Override @Override
public BpmnModelWrapper getModelJson(String id) throws Exception { public BpmnModelWrapper getModelJson(String id) throws Exception {
if(StringUtils.hasText(id)){ if(StringUtils.hasText(id)){
ProcessEntity entity =repository.findOne(id); ProcessEntity entity =repository.getOne(id);
if(entity!=null){ if(entity!=null){
BpmnModel model = BpmnConverterUtil.xml2BpmnModel(entity.getXml()); BpmnModel model = BpmnConverterUtil.xml2BpmnModel(entity.getXml());
@ -57,7 +57,7 @@ public class FlowableModelerServiceImpl implements FlowableModelerService {
String jsonXml =values.get("json_xml"); String jsonXml =values.get("json_xml");
if(StringUtils.hasText(id)){ if(StringUtils.hasText(id)){
ProcessEntity entity =repository.findOne(id); ProcessEntity entity =repository.getOne(id);
if(entity!=null){ if(entity!=null){
//将修改后的流程定义转成 xml 进行存储 //将修改后的流程定义转成 xml 进行存储
entity.setXml(getModifiedBpmnModelXml(entity,jsonXml)); entity.setXml(getModifiedBpmnModelXml(entity,jsonXml));

4
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessEntityServiceImpl.java

@ -74,12 +74,12 @@ public class ProcessEntityServiceImpl extends DaoServiceImpl<ProcessEntity, Stri
public Resource getSampleResource(String category){ public Resource getSampleResource(String category){
ResourceLoader resourceLoader =new DefaultResourceLoader(); ResourceLoader resourceLoader =new DefaultResourceLoader();
if(StringUtils.hasText(category)){ if(StringUtils.hasText(category)){
Resource rs =resourceLoader.getResource("classpath:/org/wsp/framework/flowable/sample/" + category + ".bpmn"); Resource rs =resourceLoader.getResource("classpath:/io/sc/platform/flowable/sample/" + category + ".bpmn");
if(rs.exists()){ if(rs.exists()){
return rs; return rs;
} }
} }
return resourceLoader.getResource("classpath:/org/wsp/framework/flowable/sample/Sample.bpmn"); return resourceLoader.getResource("classpath:/io/sc/platform/flowable/sample/Sample.bpmn");
} }
@Override @Override

2
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessOperationServiceImpl.java

@ -53,7 +53,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
public class ProcessOperationServiceImpl implements ProcessOperationService { public class ProcessOperationServiceImpl implements ProcessOperationService {
private static final Logger log =LoggerFactory.getLogger(ProcessOperationServiceImpl.class); private static final Logger log =LoggerFactory.getLogger(ProcessOperationServiceImpl.class);
private static final Pattern GO_BACK_VARIABLE_PATTERN = Pattern.compile(FrameworkVariableNames.GO_BACK + "\\s*==\\s*([-]?\\d*)"); private static final Pattern GO_BACK_VARIABLE_PATTERN = Pattern.compile(FrameworkVariableNames.GO_BACK + "\\s*==\\s*([-]?\\d*)");
private static final String DEFAULT_ASSIGNMENT_STRATEGY_SPRING_BEAN_NAME ="frAssigneeQueryService"; private static final String DEFAULT_ASSIGNMENT_STRATEGY_SPRING_BEAN_NAME ="platformAssigneeQueryService";
private static final String ASSIGNMENT_STRATEGY_DATA_OBJECT_ID ="assignment-strategy"; private static final String ASSIGNMENT_STRATEGY_DATA_OBJECT_ID ="assignment-strategy";
@Autowired private RuntimeService runtimeService; @Autowired private RuntimeService runtimeService;
@Autowired private HistoryService historyService; @Autowired private HistoryService historyService;

6
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessQueryServiceImpl.java

@ -42,7 +42,7 @@ public class ProcessQueryServiceImpl implements ProcessQueryService {
@Autowired private ProcessEntityService processEntityService; @Autowired private ProcessEntityService processEntityService;
@Autowired @Autowired
@Qualifier("frAssigneeQueryService") @Qualifier("platformAssigneeQueryService")
private AssigneeQueryService assigneeQueryService; private AssigneeQueryService assigneeQueryService;
@Autowired private Dialect dialect; @Autowired private Dialect dialect;
@ -114,8 +114,8 @@ public class ProcessQueryServiceImpl implements ProcessQueryService {
} }
@Override @Override
public Page<ProcessInstanceWrapper> queryProcessInstances(String businessKey, ProcessEntity queryExampleEntity, QueryParameter queryParameter) throws Exception { public Page<ProcessInstanceWrapper> queryProcessInstances(String businessKey, QueryParameter queryParameter) throws Exception {
List<ProcessEntity> entities =processEntityService.fetchByExample(queryExampleEntity,null,null); List<ProcessEntity> entities =processEntityService.list(queryParameter);
if(entities!=null && entities.size()>0){ if(entities!=null && entities.size()>0){
Set<String> deployedIds =new HashSet<String>(); Set<String> deployedIds =new HashSet<String>();
for(ProcessEntity entity : entities){ for(ProcessEntity entity : entities){

6
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableGroupList.java

@ -3,7 +3,7 @@ package io.sc.platform.flowable.support;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import io.sc.platform.system.api.role.Role; import io.sc.platform.system.api.role.RoleVo;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
public class FlowableGroupList { public class FlowableGroupList {
@ -12,14 +12,14 @@ public class FlowableGroupList {
private int start; private int start;
private List<FlowableGroup> data =new ArrayList<FlowableGroup>(); private List<FlowableGroup> data =new ArrayList<FlowableGroup>();
public static FlowableGroupList fromGroups(Page<Role> page){ public static FlowableGroupList fromGroups(Page<RoleVo> page){
FlowableGroupList result =new FlowableGroupList(); FlowableGroupList result =new FlowableGroupList();
if(page!=null){ if(page!=null){
result.setSize(page.getSize()); result.setSize(page.getSize());
result.setTotal(page.getTotalElements()); result.setTotal(page.getTotalElements());
result.setStart(0); result.setStart(0);
if(page.getContent()!=null && page.getContent().size()>0){ if(page.getContent()!=null && page.getContent().size()>0){
for(Role role : page.getContent()){ for(RoleVo role : page.getContent()){
FlowableGroup group =new FlowableGroup(); FlowableGroup group =new FlowableGroup();
group.setId(role.getCode()); group.setId(role.getCode());
group.setName(role.getName()); group.setName(role.getName());

6
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableUser.java

@ -17,10 +17,10 @@ public class FlowableUser {
public static FlowableUser currentLoginUser(){ public static FlowableUser currentLoginUser(){
FlowableUser user =new FlowableUser(); FlowableUser user =new FlowableUser();
user.setId(SecurityUtil.getUserId()); user.setId(SecurityUtil.getUserId());
user.setFirstName(SecurityUtil.getNickName()); user.setFirstName(SecurityUtil.getUserName());
user.setLastName(SecurityUtil.getNickName()); user.setLastName(SecurityUtil.getUserName());
user.setEmail(null); user.setEmail(null);
user.setFullName(SecurityUtil.getNickName()); user.setFullName(SecurityUtil.getUserName());
return user; return user;
} }

10
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/support/FlowableUserList.java

@ -1,6 +1,6 @@
package io.sc.platform.flowable.support; package io.sc.platform.flowable.support;
import io.sc.platform.system.api.user.User; import io.sc.platform.system.api.user.UserVo;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import java.util.ArrayList; import java.util.ArrayList;
@ -12,19 +12,19 @@ public class FlowableUserList {
private int start; private int start;
private List<FlowableUser> data =new ArrayList<FlowableUser>(); private List<FlowableUser> data =new ArrayList<FlowableUser>();
public static FlowableUserList fromUsers(Page<User> page){ public static FlowableUserList fromUsers(Page<UserVo> page){
FlowableUserList result =new FlowableUserList(); FlowableUserList result =new FlowableUserList();
if(page!=null){ if(page!=null){
result.setSize(page.getSize()); result.setSize(page.getSize());
result.setTotal(page.getTotalElements()); result.setTotal(page.getTotalElements());
result.setStart(0); result.setStart(0);
if(page.getContent()!=null && page.getContent().size()>0){ if(page.getContent()!=null && page.getContent().size()>0){
for(User user : page.getContent()){ for(UserVo user : page.getContent()){
FlowableUser fuser =new FlowableUser(); FlowableUser fuser =new FlowableUser();
fuser.setId(user.getLoginName()); fuser.setId(user.getLoginName());
fuser.setFirstName(user.getLoginName()); fuser.setFirstName(user.getLoginName());
fuser.setLastName(user.getNickName()); fuser.setLastName(user.getUserName());
fuser.setFullName(user.getNickName()); fuser.setFullName(user.getUserName());
result.getData().add(fuser); result.getData().add(fuser);
} }
} }

2
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/util/BpmnConverterUtil.java

@ -14,11 +14,11 @@ import io.sc.platform.core.Environment;
import io.sc.platform.core.util.ObjectMapper4Json; import io.sc.platform.core.util.ObjectMapper4Json;
import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.BpmnModel;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
/** /**
* Flowable 工作流模型转化工具类 * Flowable 工作流模型转化工具类

44
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/application-properties.json

@ -0,0 +1,44 @@
[
{
"module" : "io.sc.platform.flowable",
"order" : 5000,
"description": "flowable bpm configuration",
"properties": [
"# core",
"flowable.asyncExecutorActivate =false",
"flowable.asyncHistoryExecutorActivate = false",
"flowable.check-process-definitions=false",
"flowable.custom-mybatis-mappers=",
"flowable.custom-mybatis-x-m-l-mappers=",
"flowable.database-schema=",
"flowable.database-schema-update=true",
"flowable.db-history-used=true",
"flowable.deployment-name=SpringBootAutoDeployment",
"flowable.history-level=",
"flowable.process-definition-location-prefix=classpath*:/processes/",
"flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn",
"# process",
"flowable.process.definition-cache-limit=-1",
"flowable.process.enable-safe-xml=true",
"flowable.process.servlet.load-on-startup=-1",
"flowable.process.servlet.name=Flowable BPMN Rest API",
"flowable.process.servlet.path=/process-api",
"# cmmn",
"flowable.cmmn.enabled=false",
"# content",
"flowable.content.enabled=false",
"# dmn",
"flowable.dmn.enabled=false",
"# form",
"flowable.form.enabled=false",
"# idm",
"flowable.idm.enabled=false"
]
}
]

10
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/components.json

@ -1,9 +1,9 @@
{ {
"includes":[ "includes":[
"org.wsp.framework.flowable.controller", "io.sc.platform.flowable.controller",
"org.wsp.framework.flowable.service.impl", "io.sc.platform.flowable.service.impl",
"org.wsp.framework.flowable.extension.listener.task", "io.sc.platform.flowable.extension.listener.task",
"org.wsp.framework.flowable.initializer", "io.sc.platform.flowable.initializer",
"org.wsp.framework.flowable.installer" "io.sc.platform.flowable.installer"
] ]
} }

3
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -4,7 +4,8 @@
"order" : 600, "order" : 600,
"description":"工作流流程定义表结构", "description":"工作流流程定义表结构",
"locations":[ "locations":[
"classpath:/liquibase/FR_1.0.0_20171228__Process Manager Database Schema DDL.xml" "classpath:/liquibase/FLOWABLE_6.8.0_20220528__Flowable Database Schema DDL.xml",
"classpath:/liquibase/PF_1.0.0_20221228__Process Manager Database Schema DDL.xml"
] ]
} }
] ]

6
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/repositories.json

@ -0,0 +1,6 @@
{
"includes":[
"io.sc.platform.flowable.jpa.entity",
"io.sc.platform.flowable.jpa.repository"
]
}

6
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/repository.json

@ -1,6 +0,0 @@
{
"includes":[
"org.wsp.framework.flowable.entity",
"org.wsp.framework.flowable.repository"
]
}

3
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/resources.json

@ -0,0 +1,3 @@
[
{"handler":"/flowable-modeler/**" ,"location":"classpath:/flowable-modeler/"}
]

2
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/security.json

@ -1,5 +1,5 @@
{ {
"ignoredSecurityControllerUrlMatchers":[ "permitPatterns":[
"/flowable-modeler/editor.html", /**/ "/flowable-modeler/editor.html", /**/
"/flowable-modeler/editor-app/**", /**/ "/flowable-modeler/editor-app/**", /**/
] ]

3
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/web-resource-handlers.json

@ -1,3 +0,0 @@
[
{"handler":"/flowable-modeler/**" ,"location":"classpath:/flowable-modeler/"}
]

1
io.sc.platform.flowable/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer

@ -0,0 +1 @@
io.sc.platform.flowable.initializer.SampleWorkFlowSystemDictionaryInitializer

157
io.sc.platform.flowable/src/main/resources/flowable-modeler/404.html

@ -0,0 +1,157 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page Not Found :(</title>
<style>
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
html {
padding: 30px 10px;
font-size: 20px;
line-height: 1.4;
color: #737373;
background: #f0f0f0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
html,
input {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body {
max-width: 500px;
_width: 500px;
padding: 30px 20px 50px;
border: 1px solid #b3b3b3;
border-radius: 4px;
margin: 0 auto;
box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
background: #fcfcfc;
}
h1 {
margin: 0 10px;
font-size: 50px;
text-align: center;
}
h1 span {
color: #bbb;
}
h3 {
margin: 1.5em 0 0.5em;
}
p {
margin: 1em 0;
}
ul {
padding: 0 0 0 40px;
margin: 1em 0;
}
.container {
max-width: 380px;
_width: 380px;
margin: 0 auto;
}
/* google search */
#goog-fixurl ul {
list-style: none;
padding: 0;
margin: 0;
}
#goog-fixurl form {
margin: 0;
}
#goog-wm-qt,
#goog-wm-sb {
border: 1px solid #bbb;
font-size: 16px;
line-height: normal;
vertical-align: top;
color: #444;
border-radius: 2px;
}
#goog-wm-qt {
width: 220px;
height: 20px;
padding: 5px;
margin: 5px 10px 0 0;
box-shadow: inset 0 1px 1px #ccc;
}
#goog-wm-sb {
display: inline-block;
height: 32px;
padding: 0 10px;
margin: 5px 0 0;
white-space: nowrap;
cursor: pointer;
background-color: #f5f5f5;
background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
*overflow: visible;
*display: inline;
*zoom: 1;
}
#goog-wm-sb:hover,
#goog-wm-sb:focus {
border-color: #aaa;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
background-color: #f8f8f8;
}
#goog-wm-qt:hover,
#goog-wm-qt:focus {
border-color: #105cb6;
outline: 0;
color: #222;
}
input::-moz-focus-inner {
padding: 0;
border: 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Not found <span>:(</span></h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
<p>It looks like this was the result of either:</p>
<ul>
<li>a mistyped address</li>
<li>an out-of-date link</li>
</ul>
<script>
var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;
</script>
<script src="//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
</div>
</body>
</html>

9
io.sc.platform.flowable/src/main/resources/flowable-modeler/browserconfig.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="images/mstile-150x150.png?v=Om5N75Y123"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

512
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/cmmn-draw.js

@ -0,0 +1,512 @@
/* 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.
*/
function _cmmnGetColor(element, defaultColor)
{
var strokeColor;
if(element.current) {
strokeColor = CURRENT_COLOR;
} else if(element.completed) {
strokeColor = COMPLETED_COLOR;
} else {
strokeColor = defaultColor;
}
return strokeColor;
}
function _drawPlanModel(planModel)
{
var rect = paper.rect(planModel.x, planModel.y, planModel.width, planModel.height);
rect.attr({"stroke-width": 1,
"stroke": "#000000",
"fill": "white"
});
if (planModel.name)
{
var planModelName = paper.text(planModel.x + 14, planModel.y + (planModel.height / 2), planModel.name).attr({
"text-anchor" : "middle",
"font-family" : "Arial",
"font-size" : "12",
"fill" : "#000000"
});
planModelName.transform("r270");
}
}
function _drawSubProcess(element)
{
var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);
rect.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
}
function _drawServiceTaskTypeIcon(element)
{
_drawTask(element);
if (element.taskType === "mail")
{
_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "camel")
{
_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "mule")
{
_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "http")
{
_drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.stencilIconId)
{
paper.image("../service/stencilitem/" + element.stencilIconId + "/icon", element.x + 4, element.y + 4, 16, 16);
}
else
{
_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);
}
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawHttpServiceTask(element)
{
_drawTask(element);
_drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawHumanTask(element)
{
_drawTask(element);
_drawHumanTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawCaseTask(element)
{
_drawTask(element);
_drawCaseTaskIcon(paper, element.x + 1, element.y + 1);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawProcessTask(element)
{
_drawTask(element);
_drawProcessTaskIcon(paper, element.x + 1, element.y + 1);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawScriptTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 5,2 0,0.094 c 0.23706,0.064 0.53189,0.1645 0.8125,0.375 0.5582,0.4186 1.05109,1.228 1.15625,2.5312 l 8.03125,0 1,0 1,0 c 0,-3 -2,-3 -2,-3 l -10,0 z M 4,3 4,13 2,13 c 0,3 2,3 2,3 l 9,0 c 0,0 2,0 2,-3 L 15,6 6,6 6,5.5 C 6,4.1111 5.5595,3.529 5.1875,3.25 4.8155,2.971 4.5,3 4.5,3 L 4,3 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var scriptTaskIcon = paper.set();
scriptTaskIcon.push(path1);
scriptTaskIcon.transform("T" + startX + "," + startY);
}
function _drawScriptServiceTask(element)
{
_drawTask(element);
_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawSendEventServiceTask(element)
{
_drawTask(element);
_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawExternalWorkerServiceTask(element)
{
_drawTask(element);
_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawDecisionTask(element)
{
_drawTask(element);
_drawDecisionTaskIcon(paper, element.x + 1, element.y + 1);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawServiceTask(element)
{
_drawTask(element);
_drawServiceTaskTypeIcon(element);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawTask(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 4);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = ACTIVITY_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
}
}
function _drawTimerEventListener(element)
{
_drawEventListener(element);
_drawTimerEventListenerIcon(paper, element);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawUserEventListener(element)
{
_drawEventListener(element);
_drawUserEventListenerIcon(paper, element);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawVariableEventListener(element)
{
_drawEventListener(element);
_drawVariableEventListenerIcon(paper, element);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawGenericEventListener(element)
{
_drawEventListener(element);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawEventListener(element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 15);
circle.attr({"stroke-width": 1,
"stroke": "black",
"fill": "white"
});
circle.id = element.id;
}
function _drawMilestone(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 24);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = WHITE_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
}
}
function _drawStage(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 16);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = WHITE_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x + 10, element.y + 5, element.width, element.height, "start", "top", 11);
}
}
function _drawPlanModel(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _cmmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 4);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = WHITE_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
var path1 = paper.path("M20 55 L37 34 L275 34 L291 55");
path1.attr({
"opacity": 1,
"stroke": strokeColor,
"fill": "#ffffff"
});
var planModelHeader = paper.set();
planModelHeader.push(path1);
planModelHeader.translate(element.x, element.y - 55);
if (element.name) {
this._drawMultilineText(element.name, element.x + 10, element.y - 16, 275, element.height, "middle", "top", 11);
}
}
function _drawEntryCriterion(element)
{
var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);
var rhombus = 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"
);
// Fill
var gatewayFillColor = WHITE_FILL_COLOR;
// Opacity
var gatewayOpacity = 1.0;
rhombus.attr("stroke-width", 1);
rhombus.attr("stroke", strokeColor);
rhombus.attr("fill", gatewayFillColor);
rhombus.attr("fill-opacity", gatewayOpacity);
rhombus.id = element.id;
}
function _drawExitCriterion(element)
{
var strokeColor = _cmmnGetColor(element, MAIN_STROKE_COLOR);
var rhombus = 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"
);
// Fill
var gatewayFillColor = '#000000';
// Opacity
var gatewayOpacity = 1.0;
rhombus.attr("stroke-width", 1);
rhombus.attr("stroke", strokeColor);
rhombus.attr("fill", gatewayFillColor);
rhombus.attr("fill-opacity", gatewayOpacity);
rhombus.id = element.id;
}
function _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)
{
if (!text || text == "")
{
return;
}
var textBoxX, textBoxY;
var width = boxWidth - (2 * TEXT_PADDING);
if (horizontalAnchor === "middle")
{
textBoxX = x + (boxWidth / 2);
}
else if (horizontalAnchor === "start")
{
textBoxX = x;
}
textBoxY = y + (boxHeight / 2);
var t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({
"text-anchor" : horizontalAnchor,
"font-family" : "Arial",
"font-size" : fontSize,
"fill" : "#373e48"
});
var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
t.attr({
"text" : abc
});
var letterWidth = t.getBBox().width / abc.length;
t.attr({
"text" : text
});
var removedLineBreaks = text.split("\n");
var x = 0, s = [];
for (var r = 0; r < removedLineBreaks.length; r++)
{
var words = removedLineBreaks[r].split(" ");
for ( var i = 0; i < words.length; i++) {
var l = words[i].length;
if (x + (l * letterWidth) > width) {
s.push("\n");
x = 0;
}
x += l * letterWidth;
s.push(words[i] + " ");
}
s.push("\n");
x = 0;
}
t.attr({
"text" : s.join("")
});
if (verticalAnchor && verticalAnchor === "top")
{
t.attr({"y": y + (t.getBBox().height / 2)});
}
}
function _drawAssociation(flow){
var polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
polyline.element = paper.path(polyline.path);
polyline.element.attr({"stroke-width": ASSOCIATION_STROKE});
polyline.element.attr({"stroke-dasharray": ". "});
polyline.element.attr({"stroke":"#585858"});
polyline.element.id = flow.id;
var polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
polylineInvisible.element = paper.path(polyline.path);
polylineInvisible.element.attr({
"opacity": 0,
"stroke-width": 8,
"stroke" : "#000000"
});
_showTip(jQuery(polylineInvisible.element.node), flow);
polylineInvisible.element.mouseover(function() {
paper.getById(polyline.element.id).attr({"stroke":"blue"});
});
polylineInvisible.element.mouseout(function() {
paper.getById(polyline.element.id).attr({"stroke":"#585858"});
});
}
function _drawArrowHead(line, connectionType)
{
var doubleArrowWidth = 2 * ARROW_WIDTH;
var arrowHead = paper.path("M0 0L-" + (ARROW_WIDTH / 2 + .5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2 + .5) + " -" + doubleArrowWidth + "z");
// anti smoothing
if (this.strokeWidth%2 == 1)
line.x2 += .5, line.y2 += .5;
arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
arrowHead.attr("fill", "#585858");
arrowHead.attr("stroke-width", SEQUENCEFLOW_STROKE);
arrowHead.attr("stroke", "#585858");
return arrowHead;
}

216
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/cmmn-icons.js

@ -0,0 +1,216 @@
/* 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.
*/
function _drawHumanTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#d1b575"
});
var userTaskIcon = paper.set();
userTaskIcon.push(path1);
userTaskIcon.transform("T" + startX + "," + startY);
}
function _drawServiceTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375 6.6676654,3.4929791 6.3336971,3.6092802 6.03125,3.78125 6.02349,3.78566 6.007733,3.77681 6,3.78125 5.8811373,3.761018 5.8125,3.71875 5.8125,3.71875 l -1.6875,-1 -1.40625,1.4375 0.96875,1.65625 c 0,0 0.065705,0.068637 0.09375,0.1875 0.002,0.00849 -0.00169,0.022138 0,0.03125 C 3.6092802,6.3336971 3.4929791,6.6676654 3.375,7 3.3629836,7.0338489 3.3239228,7.0596246 3.3125,7.09375 3.125763,7.4756184 2.875,7.5 2.875,7.5 L 1,8 l 0,2 1.875,0.5 c 0,0 0.250763,0.02438 0.4375,0.40625 0.017853,0.03651 0.046318,0.04988 0.0625,0.09375 0.1129372,0.318132 0.2124732,0.646641 0.375,0.9375 -0.00302,0.215512 -0.09375,0.34375 -0.09375,0.34375 L 2.6875,13.9375 4.09375,15.34375 5.78125,14.375 c 0,0 0.1229911,-0.09744 0.34375,-0.09375 0.2720511,0.147787 0.5795915,0.23888 0.875,0.34375 0.033849,0.01202 0.059625,0.05108 0.09375,0.0625 C 7.4756199,14.874237 7.5,15.125 7.5,15.125 L 8,17 l 2,0 0.5,-1.875 c 0,0 0.02438,-0.250763 0.40625,-0.4375 0.03651,-0.01785 0.04988,-0.04632 0.09375,-0.0625 0.332335,-0.117979 0.666303,-0.23428 0.96875,-0.40625 0.177303,0.0173 0.28125,0.09375 0.28125,0.09375 l 1.65625,0.96875 1.40625,-1.40625 -0.96875,-1.65625 c 0,0 -0.07645,-0.103947 -0.09375,-0.28125 0.162527,-0.290859 0.262063,-0.619368 0.375,-0.9375 0.01618,-0.04387 0.04465,-0.05724 0.0625,-0.09375 C 14.874237,10.52438 15.125,10.5 15.125,10.5 L 17,10 17,8 15.125,7.5 c 0,0 -0.250763,-0.024382 -0.4375,-0.40625 C 14.669647,7.0572406 14.641181,7.0438697 14.625,7 14.55912,6.8144282 14.520616,6.6141566 14.4375,6.4375 c -0.224363,-0.4866 0,-0.71875 0,-0.71875 L 15.40625,4.0625 14,2.625 l -1.65625,1 c 0,0 -0.253337,0.1695664 -0.71875,-0.03125 l -0.03125,0 C 11.405359,3.5035185 11.198648,3.4455201 11,3.375 10.95613,3.3588185 10.942759,3.3303534 10.90625,3.3125 10.524382,3.125763 10.5,2.875 10.5,2.875 L 10,1 8,1 z m 1,5 c 1.656854,0 3,1.3431458 3,3 0,1.656854 -1.343146,3 -3,3 C 7.3431458,12 6,10.656854 6,9 6,7.3431458 7.3431458,6 9,6 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var serviceTaskIcon = paper.set();
serviceTaskIcon.push(path1);
serviceTaskIcon.transform("T" + startX + "," + startY);
}
function _drawCaseTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M5 8 L9 4 L18 4 L 21 7");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#000000"
});
var path2 = paper.path("M1 23 L1 4 L30 4 L30 23z");
path2.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var caseTaskIcon = paper.set();
caseTaskIcon.push(path1);
caseTaskIcon.push(path2);
caseTaskIcon.translate(startX, startY);
caseTaskIcon.scale(0.7, 0.7);
}
function _drawProcessTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var processTaskIcon = paper.set();
processTaskIcon.push(path1);
processTaskIcon.translate(startX, startY);
processTaskIcon.scale(0.7, 0.7);
}
function _drawSendTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z");
path1.attr({
"stroke": "none",
"fill": "#16964d"
});
var sendTaskIcon = paper.set();
sendTaskIcon.push(path1);
sendTaskIcon.transform("T" + startX + "," + startY);
}
function _drawDecisionTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var decisionTaskIcon = paper.set();
decisionTaskIcon.push(path1);
decisionTaskIcon.translate(startX, startY);
decisionTaskIcon.scale(0.7, 0.7);
}
function _drawHttpTaskIcon(paper, startX, startY)
{
var path = paper.path("m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#16964d"
});
startX += -2;
startY += -2;
path.transform("T" + startX + "," + startY);
}
function _drawBusinessRuleTaskIcon(paper, startX, startY) {
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.7999224 -8.72718,0 z m -4.36364,4.1998844 2.90906,0 0,2.800116 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.800116 -8.72718,0 z");
path1.attr({
"stroke": "none",
"fill": "#72a7d0"
});
var businessRuleTaskIcon = paper.set();
businessRuleTaskIcon.push(path1);
businessRuleTaskIcon.transform("T" + startX + "," + startY);
}
function _drawTimerEventListenerIcon(paper, element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 10);
circle.attr({"stroke-width": 1,
"stroke": "black",
"fill": "none"
});
var path = paper.path("M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z");
path.attr({
"stroke": "none",
"fill": "#585858"
});
path.transform("T" + (element.x + 5) + "," + (element.y + 5));
return path;
}
function _drawUserEventListenerIcon(paper, element) {
var userTaskIcon = paper.set();
var path1 = paper.path("M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z");
path1.attr({"opacity": 1, "stroke": "none", "fill": "#F4F6F7"});
userTaskIcon.push(path1);
var path2 = paper.path("M6,20L6,24");
path2.attr({"opacity": 1, "stroke": "white", "fill": "none"});
userTaskIcon.push(path2);
var path3 = paper.path("M20,20L20,24");
path3.attr({"opacity": 1, "stroke": "white", "fill": "none"});
userTaskIcon.push(path3);
var circle = paper.circle(13.002, 5.916, 5.417);
circle.attr({"stroke-width": 1, "stroke": "black", "fill": "#000000"});
userTaskIcon.push(circle);
var path4 = paper.path("M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z");
path4.attr({"opacity": 1, "stroke": "none", "fill": "#F0EFF0"});
userTaskIcon.push(path4);
var x = (element.width / 2) - 2;
var y = (element.height / 2) - 2;
var circle2 = paper.circle(x, y, 17);
circle2.attr({"stroke-width": 1, "stroke": "#F0EFF0", "fill": "none"});
userTaskIcon.push(circle2);
userTaskIcon.transform("S0.7,0.7T" + (element.x + 2) + "," + (element.y + 2));
return userTaskIcon;
}
function _drawVariableEventListenerIcon(paper, element) {
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 10);
circle.attr({"stroke-width": 1,
"stroke": "black",
"fill": "none"
});
var path = paper.path("M 20.834856,22.874369 L 10.762008,22.873529 L 7.650126,13.293421 L 15.799725,7.3734296 L 23.948336,13.294781 L 20.834856,22.874369 z");
path.attr({
"stroke": "#585858",
"fill": "none"
});
path.transform("S0.8,0.8T" + (element.x - 1) + "," + (element.y - 1));
return path;
}

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.css

@ -0,0 +1,24 @@
div[class*='ui-tooltip-flowable-'] {
background-color: #ffffff;
border-color: #c5c5c5;
color: #4a4a4a;
font-family: Verdana;
font-size: 12px;
}
div[class*='ui-tooltip-flowable-'] .qtip-content {
color: #4a4a4a;
background-color: #ffffff;
font-family: Verdana;
font-size: 12px;
}
.ui-tooltip-flowable-cmmn .qtip-titlebar {
color: #FFFFFF;
font-size: 12px;
background: #2B414F;
}
.ui-tooltip-flowable-cmmn .qtip-tip {
background-color: #2B414F;
}

15
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.html

@ -0,0 +1,15 @@
<html>
<head>
<link type="text/css" rel="stylesheet" href="display/jquery.qtip.min.css" />
<link type="text/css" rel="stylesheet" href="display-cmmn/displaymodel.css" />
<script type="text/javascript" src="display/jquery.qtip.min.js"></script>
<script type="text/javascript" src="display/raphael.min.js"></script>
<script type="text/javascript" src="display-cmmn/cmmn-draw.js"></script>
<script type="text/javascript" src="display-cmmn/cmmn-icons.js"></script>
<script type="text/javascript" src="display/Polyline.js"></script>
<script type="text/javascript" src="display-cmmn/displaymodel.js"></script>
</head>
</html>

272
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-cmmn/displaymodel.js

@ -0,0 +1,272 @@
/* 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 = 1;
var ASSOCIATION_STROKE = 2;
var TASK_STROKE = 1;
var TASK_HIGHLIGHT_STROKE = 2;
var TEXT_COLOR= "#373e48";
var CURRENT_COLOR= "#017501";
var HOVER_COLOR= "#666666";
var ACTIVITY_STROKE_COLOR = "#bbbbbb";
var ACTIVITY_FILL_COLOR = "#f9f9f9";
var WHITE_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('#cmmnModel');
var modelId = modelDiv.attr('data-model-id');
var historyModelId = modelDiv.attr('data-history-id');
var caseDefinitionId = modelDiv.attr('data-case-definition-id');
var modelType = modelDiv.attr('data-model-type');
var elementsAdded = new Array();
var elementsRemoved = new Array();
function _showTip(htmlNode, element)
{
// Default tooltip, no custom tool tip set
if (documentation === undefined) {
var documentation = "";
if (element.name && element.name.length > 0) {
documentation += "<b>Name</b>: <i>" + element.name + "</i><br/><br/>";
}
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 += '<b>' + propName + '</b>:<br/>';
for (var j = 0; j < element.properties[i].value.length; j++) {
documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';
}
}
else {
documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';
}
}
}
}
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('#cmmnModel')
},
hide: {
fixed: true, delay: 500,
event: 'click mouseleave'
},
style: {
classes: 'ui-tooltip-flowable-cmmn'
}
});
}
function _addHoverLogic(element, type, defaultColor)
{
var strokeColor = _cmmnGetColor(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":strokeColor});
});
}
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.APP_URL.getCaseInstancesHistoryModelJsonUrl(historyModelId);
} else {
modelUrl = FLOWABLE.APP_URL.getCaseInstancesModelJsonUrl(modelId);
}
} else if (modelType == 'design') {
if (historyModelId) {
modelUrl = FLOWABLE.APP_URL.getModelHistoryModelJsonUrl(modelId, historyModelId);
} else {
modelUrl = FLOWABLE.APP_URL.getModelModelJsonUrl(modelId);
}
} else if (modelType == 'case-definition') {
modelUrl = FLOWABLE.APP_URL.getCaseDefinitionModelJsonUrl(caseDefinitionId);
}
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('#cmmnModel').css('marginTop', offsetY);
}
jQuery('#cmmnModel').width(INITIAL_CANVAS_WIDTH);
jQuery('#cmmnModel').height(INITIAL_CANVAS_HEIGHT);
paper = Raphael(document.getElementById('cmmnModel'), canvasWidth, canvasHeight);
paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);
paper.renderfix();
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);
//} catch(err) {console.log(err);}
}
if (data.flows)
{
for (var i = 0; i < data.flows.length; i++)
{
var flow = data.flows[i];
_drawAssociation(flow);
}
}
});
request.error(function(jqXHR, textStatus, errorThrown) {
alert("error");
});

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.css

@ -0,0 +1,24 @@
div[class*='ui-tooltip-flowable-'] {
background-color: #ffffff;
border-color: #c5c5c5;
color: #4a4a4a;
font-family: Verdana;
font-size: 12px;
}
div[class*='ui-tooltip-flowable-'] .qtip-content {
color: #4a4a4a;
background-color: #ffffff;
font-family: Verdana;
font-size: 12px;
}
.ui-tooltip-flowable-cmmn .qtip-titlebar {
color: #FFFFFF;
font-size: 12px;
background: #2B414F;
}
.ui-tooltip-flowable-cmmn .qtip-tip {
background-color: #2B414F;
}

15
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.html

@ -0,0 +1,15 @@
<html>
<head>
<link type="text/css" rel="stylesheet" href="display/jquery.qtip.min.css" />
<link type="text/css" rel="stylesheet" href="display-dmn/displaymodel.css" />
<script type="text/javascript" src="display/jquery.qtip.min.js"></script>
<script type="text/javascript" src="display/raphael.min.js"></script>
<script type="text/javascript" src="display-dmn/dmn-draw.js"></script>
<script type="text/javascript" src="display-dmn/dmn-icons.js"></script>
<script type="text/javascript" src="display/Polyline.js"></script>
<script type="text/javascript" src="display-dmn/displaymodel.js"></script>
</head>
</html>

270
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/displaymodel.js

@ -0,0 +1,270 @@
/* 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 = 1;
var ASSOCIATION_STROKE = 2;
var TASK_STROKE = 1;
var TASK_HIGHLIGHT_STROKE = 2;
var DECISION_SERVICE_STROKE = 3;
var COMPLETED_COLOR = "#2632aa";
var TEXT_COLOR= "#373e48";
var CURRENT_COLOR= "#017501";
var AVAILABLE_COLOR = "#e3da82";
var HOVER_COLOR= "#666666";
var ACTIVITY_STROKE_COLOR = "#bbbbbb";
var ACTIVITY_FILL_COLOR = "#f9f9f9";
var WHITE_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('#dmnModel');
var modelId = modelDiv.attr('data-model-id');
var historyModelId = modelDiv.attr('data-history-id');
var decisionDefinitionId = modelDiv.attr('data-decision-definition-id');
var modelType = modelDiv.attr('data-model-type');
var elementsAdded = new Array();
var elementsRemoved = new Array();
function _showTip(htmlNode, element)
{
// Default tooltip, no custom tool tip set
if (documentation === undefined) {
var documentation = "";
if (element.name && element.name.length > 0) {
documentation += "<b>Name</b>: <i>" + element.name + "</i><br/><br/>";
}
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 += '<b>' + propName + '</b>:<br/>';
for (var j = 0; j < element.properties[i].value.length; j++) {
documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';
}
}
else {
documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';
}
}
}
}
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('#dmnModel')
},
hide: {
fixed: true, delay: 500,
event: 'click mouseleave'
},
style: {
classes: 'ui-tooltip-flowable-cmmn'
}
});
}
function _addHoverLogic(element, type, defaultColor)
{
var strokeColor = _dmnGetColor(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});
paper.getById("divider_"+element.id) != undefined ? paper.getById("divider_"+element.id).attr({"stroke":HOVER_COLOR}) : '';
});
topBodyRect.mouseout(function() {
paper.getById(element.id).attr({"stroke":strokeColor});
paper.getById("divider_"+element.id) != undefined ? paper.getById("divider_"+element.id).attr({"stroke":strokeColor}) : '';
});
}
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 == 'decision-service') {
// modelUrl = FLOWABLE.APP_URL.getDgetCaseDefinitionModelJsonUrl(caseDefinitionId);
modelUrl = './app/rest/admin/decisions/decision-service/' + decisionDefinitionId + '/model-json';
} else if (modelType == 'design') {
if (historyModelId) {
modelUrl = FLOWABLE.APP_URL.getModelHistoryModelJsonUrl(modelId, historyModelId);
} else {
modelUrl = FLOWABLE.APP_URL.getModelModelJsonUrl(modelId);
}
}
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('#dmnModel').css('marginTop', offsetY);
}
jQuery('#dmnModel').width(INITIAL_CANVAS_WIDTH);
jQuery('#dmnModel').height('100%');
paper = Raphael(document.getElementById('dmnModel'), canvasWidth, canvasHeight);
paper.setViewBox(0, 0, viewBoxWidth, viewBoxHeight, false);
paper.renderfix();
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);
//} catch(err) {console.log(err);}
}
if (data.flows)
{
for (var i = 0; i < data.flows.length; i++)
{
var flow = data.flows[i];
_drawInformationRequirement(flow);
}
}
});
request.error(function(jqXHR, textStatus, errorThrown) {
alert("error");
});

206
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/dmn-draw.js

@ -0,0 +1,206 @@
function _dmnGetColor(element, defaultColor)
{
var strokeColor;
if (element.current) {
strokeColor = CURRENT_COLOR;
} else if (element.completed) {
strokeColor = COMPLETED_COLOR;
} else if (element.available) {
strokeColor = AVAILABLE_COLOR;
} else {
strokeColor = defaultColor;
}
return strokeColor;
}
function _drawDecisionService(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _dmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth = DECISION_SERVICE_STROKE;
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 16);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = WHITE_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
var dividerElement = element.divider;
var divider = new Polyline("divider_" + element.id, dividerElement.waypoints, ACTIVITY_STROKE_COLOR, paper);
divider.element = paper.path(divider.path);
divider.element.attr({"stroke-width": ASSOCIATION_STROKE});
divider.element.attr({"stroke":"#bbbbbb"});
divider.element.id = "divider_" + element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x + 10, element.y + 5, element.width, element.height, "start", "top", 11);
}
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawDecision(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _dmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 4);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
rectAttrs['fill'] = ACTIVITY_FILL_COLOR;
rect.attr(rectAttrs);
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
}
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawInformationRequirement(flow){
var polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
var strokeColor = _dmnGetColor(flow, MAIN_STROKE_COLOR);
polyline.element = paper.path(polyline.path);
polyline.element.attr({"stroke-width": ASSOCIATION_STROKE});
polyline.element.attr({"stroke":strokeColor});
polyline.element.id = flow.id;
var lastLineIndex = polyline.getLinesCount() - 1;
var line = polyline.getLine(lastLineIndex);
var polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
polylineInvisible.element = paper.path(polyline.path);
polylineInvisible.element.attr({
"opacity": 0,
"stroke-width": 8,
"stroke" : "#000000"
});
_showTip(jQuery(polylineInvisible.element.node), flow);
polylineInvisible.element.mouseover(function() {
paper.getById(polyline.element.id).attr({"stroke":HOVER_COLOR});
});
polylineInvisible.element.mouseout(function() {
paper.getById(polyline.element.id).attr({"stroke":strokeColor});
});
_drawArrowHead(line, strokeColor, paper);
}
function _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)
{
if (!text || text == "")
{
return;
}
var textBoxX, textBoxY;
var width = boxWidth - (2 * TEXT_PADDING);
if (horizontalAnchor === "middle")
{
textBoxX = x + (boxWidth / 2);
}
else if (horizontalAnchor === "start")
{
textBoxX = x;
}
textBoxY = y + (boxHeight / 2);
var t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({
"text-anchor" : horizontalAnchor,
"font-family" : "Arial",
"font-size" : fontSize,
"fill" : "#373e48"
});
var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
t.attr({
"text" : abc
});
var letterWidth = t.getBBox().width / abc.length;
t.attr({
"text" : text
});
var removedLineBreaks = text.split("\n");
var x = 0, s = [];
for (var r = 0; r < removedLineBreaks.length; r++)
{
var words = removedLineBreaks[r].split(" ");
for ( var i = 0; i < words.length; i++) {
var l = words[i].length;
if (x + (l * letterWidth) > width) {
s.push("\n");
x = 0;
}
x += l * letterWidth;
s.push(words[i] + " ");
}
s.push("\n");
x = 0;
}
t.attr({
"text" : s.join("")
});
if (verticalAnchor && verticalAnchor === "top")
{
t.attr({"y": y + (t.getBBox().height / 2)});
}
}
function _drawArrowHead(line, connectionType)
{
var doubleArrowWidth = 2 * ARROW_WIDTH;
var arrowHead = paper.path("M0 0L-" + (ARROW_WIDTH / 2 + .5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2 + .5) + " -" + doubleArrowWidth + "z");
// anti smoothing
if (this.strokeWidth%2 == 1)
line.x2 += .5, line.y2 += .5;
arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
arrowHead.attr("fill", "#585858");
arrowHead.attr("stroke-width", ASSOCIATION_STROKE);
arrowHead.attr("stroke", "#585858");
return arrowHead;
}

182
io.sc.platform.flowable/src/main/resources/flowable-modeler/display-dmn/dmn-icons.js

@ -0,0 +1,182 @@
function _drawHumanTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#d1b575"
});
var userTaskIcon = paper.set();
userTaskIcon.push(path1);
userTaskIcon.transform("T" + startX + "," + startY);
}
function _drawServiceTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375 6.6676654,3.4929791 6.3336971,3.6092802 6.03125,3.78125 6.02349,3.78566 6.007733,3.77681 6,3.78125 5.8811373,3.761018 5.8125,3.71875 5.8125,3.71875 l -1.6875,-1 -1.40625,1.4375 0.96875,1.65625 c 0,0 0.065705,0.068637 0.09375,0.1875 0.002,0.00849 -0.00169,0.022138 0,0.03125 C 3.6092802,6.3336971 3.4929791,6.6676654 3.375,7 3.3629836,7.0338489 3.3239228,7.0596246 3.3125,7.09375 3.125763,7.4756184 2.875,7.5 2.875,7.5 L 1,8 l 0,2 1.875,0.5 c 0,0 0.250763,0.02438 0.4375,0.40625 0.017853,0.03651 0.046318,0.04988 0.0625,0.09375 0.1129372,0.318132 0.2124732,0.646641 0.375,0.9375 -0.00302,0.215512 -0.09375,0.34375 -0.09375,0.34375 L 2.6875,13.9375 4.09375,15.34375 5.78125,14.375 c 0,0 0.1229911,-0.09744 0.34375,-0.09375 0.2720511,0.147787 0.5795915,0.23888 0.875,0.34375 0.033849,0.01202 0.059625,0.05108 0.09375,0.0625 C 7.4756199,14.874237 7.5,15.125 7.5,15.125 L 8,17 l 2,0 0.5,-1.875 c 0,0 0.02438,-0.250763 0.40625,-0.4375 0.03651,-0.01785 0.04988,-0.04632 0.09375,-0.0625 0.332335,-0.117979 0.666303,-0.23428 0.96875,-0.40625 0.177303,0.0173 0.28125,0.09375 0.28125,0.09375 l 1.65625,0.96875 1.40625,-1.40625 -0.96875,-1.65625 c 0,0 -0.07645,-0.103947 -0.09375,-0.28125 0.162527,-0.290859 0.262063,-0.619368 0.375,-0.9375 0.01618,-0.04387 0.04465,-0.05724 0.0625,-0.09375 C 14.874237,10.52438 15.125,10.5 15.125,10.5 L 17,10 17,8 15.125,7.5 c 0,0 -0.250763,-0.024382 -0.4375,-0.40625 C 14.669647,7.0572406 14.641181,7.0438697 14.625,7 14.55912,6.8144282 14.520616,6.6141566 14.4375,6.4375 c -0.224363,-0.4866 0,-0.71875 0,-0.71875 L 15.40625,4.0625 14,2.625 l -1.65625,1 c 0,0 -0.253337,0.1695664 -0.71875,-0.03125 l -0.03125,0 C 11.405359,3.5035185 11.198648,3.4455201 11,3.375 10.95613,3.3588185 10.942759,3.3303534 10.90625,3.3125 10.524382,3.125763 10.5,2.875 10.5,2.875 L 10,1 8,1 z m 1,5 c 1.656854,0 3,1.3431458 3,3 0,1.656854 -1.343146,3 -3,3 C 7.3431458,12 6,10.656854 6,9 6,7.3431458 7.3431458,6 9,6 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var serviceTaskIcon = paper.set();
serviceTaskIcon.push(path1);
serviceTaskIcon.transform("T" + startX + "," + startY);
}
function _drawCaseTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M5 8 L9 4 L18 4 L 21 7");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#000000"
});
var path2 = paper.path("M1 23 L1 4 L30 4 L30 23z");
path2.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var caseTaskIcon = paper.set();
caseTaskIcon.push(path1);
caseTaskIcon.push(path2);
caseTaskIcon.translate(startX, startY);
caseTaskIcon.scale(0.7, 0.7);
}
function _drawProcessTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M1 23 L7 11 L1 0 L30 0 L 35 11 L 30 23z");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var processTaskIcon = paper.set();
processTaskIcon.push(path1);
processTaskIcon.translate(startX, startY);
processTaskIcon.scale(0.7, 0.7);
}
function _drawDecisionTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var decisionTaskIcon = paper.set();
decisionTaskIcon.push(path1);
decisionTaskIcon.translate(startX, startY);
decisionTaskIcon.scale(0.7, 0.7);
}
function _drawHttpTaskIcon(paper, startX, startY)
{
var path = paper.path("m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#16964d"
});
startX += -2;
startY += -2;
path.transform("T" + startX + "," + startY);
}
function _drawSendEventTaskIcon(paper, startX, startY)
{
var path = paper.path("m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z M 7.5,9.5 9,11 10.5,9.5 15,14 3,14 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var sendEventTaskIcon = paper.set();
sendEventTaskIcon.push(path);
sendEventTaskIcon.transform("T" + startX + "," + startY);
}
function _drawBusinessRuleTaskIcon(paper, startX, startY) {
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.7999224 -8.72718,0 z m -4.36364,4.1998844 2.90906,0 0,2.800116 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.800116 -8.72718,0 z");
path1.attr({
"stroke": "none",
"fill": "#72a7d0"
});
var businessRuleTaskIcon = paper.set();
businessRuleTaskIcon.push(path1);
businessRuleTaskIcon.transform("T" + startX + "," + startY);
}
function _drawTimerEventListenerIcon(paper, element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 10);
circle.attr({"stroke-width": 1,
"stroke": "black",
"fill": "none"
});
var path = paper.path("M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z");
path.attr({
"stroke": "none",
"fill": "#585858"
});
path.transform("T" + (element.x + 5) + "," + (element.y + 5));
return path;
}
function _drawUserEventListenerIcon(paper, element) {
var userTaskIcon = paper.set();
var path1 = paper.path("M0.585,24.167h24.083v-7.833c0,0-2.333-3.917-7.083-5.167h-9.25 c-4.417,1.333-7.833,5.75-7.833,5.75L0.585,24.167z");
path1.attr({"opacity": 1, "stroke": "none", "fill": "#F4F6F7"});
userTaskIcon.push(path1);
var path2 = paper.path("M6,20L6,24");
path2.attr({"opacity": 1, "stroke": "white", "fill": "none"});
userTaskIcon.push(path2);
var path3 = paper.path("M20,20L20,24");
path3.attr({"opacity": 1, "stroke": "white", "fill": "none"});
userTaskIcon.push(path3);
var circle = paper.circle(13.002, 5.916, 5.417);
circle.attr({"stroke-width": 1, "stroke": "black", "fill": "#000000"});
userTaskIcon.push(circle);
var path4 = paper.path("M8.043,7.083c0,0,2.814-2.426,5.376-1.807s4.624-0.693,4.624-0.693 c0.25,1.688,0.042,3.75-1.458,5.584c0,0,1.083,0.75,1.083,1.5s0.125,1.875-1,3s-5.5,1.25-6.75,0S8.668,12.834,8.668,12 s0.583-1.25,1.25-1.917C8.835,9.5,7.419,7.708,8.043,7.083z");
path4.attr({"opacity": 1, "stroke": "none", "fill": "#F0EFF0"});
userTaskIcon.push(path4);
var x = (element.width / 2) - 2;
var y = (element.height / 2) - 2;
var circle2 = paper.circle(x, y, 17);
circle2.attr({"stroke-width": 1, "stroke": "#F0EFF0", "fill": "none"});
userTaskIcon.push(circle2);
userTaskIcon.transform("S0.7,0.7" + "T" + (element.x + 2) + "," + (element.y + 2));
return userTaskIcon;
}

3
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/.gitignore

@ -0,0 +1,3 @@
/dist
/node_modules
/displaymodel_temp.html

153
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/Gruntfile.js

@ -0,0 +1,153 @@
/* 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.
*/
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
grunt.initConfig({
yeoman: {
app: require('./package.json').appPath || 'app',
dist: 'dist'
},
clean: {
dist: {
files: [
{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}
]
},
server: '.tmp'
},
useminPrepare: {
html: 'displaymodel.html',
options: {
dest: '<%= yeoman.dist %>/'
}
},
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/display/styles/{,*/}*.css'],
options: {
dirs: ['<%= yeoman.dist %>']
}
},
// Put files not handled in other tasks here
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '.',
dest: '<%= yeoman.dist %>',
src: [
'fonts/*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: [
'generated/*'
]
}]
},
styles: {
expand: true,
cwd: 'styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
},
index: {
expand: true,
cwd: './',
src: ['*.html', 'views/**/**.html'],
dest: '<%= yeoman.dist %>'
},
copyCss : {
files: [
{expand: true, cwd:'.tmp/concat/display/styles/', src:'*.css', dest:'<%= yeoman.dist %>/display/styles/', filter: 'isFile'}
]
},
copyJs : {
files: [
{expand: true, cwd:'.tmp/concat/display/scripts', src:'*.js', dest:'<%= yeoman.dist %>/display/scripts/', filter: 'isFile'}
]
},
},
ngAnnotate: {
dist: {
files: [
{
expand: true,
cwd: '.tmp/concat/display/scripts',
src: '*.js',
dest: '.tmp/concat/display/scripts'
}
]
}
},
uglify: {
dist: {
options: {
mangle: true
},
files: {
'<%= yeoman.dist %>/display/scripts/displaymodel-logic.js': [
'<%= yeoman.dist %>/display/scripts/displaymodel-logic.js'
]
}
}
},
rev: {
dist: {
files: {
src: [
'<%= yeoman.dist %>/display/{,*/}*.js',
'<%= yeoman.dist %>/display/{,*/}*.css',
'<%= yeoman.dist %>/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
}
}
});
grunt.registerTask('buildApp', [
'clean:dist',
'useminPrepare',
'copy:styles',
'concat',
'copy:dist',
'ngAnnotate',
'copy:copyCss',
'copy:copyJs',
'copy:index',
'uglify',
'rev',
'usemin'
]);
grunt.registerTask('default', [
'buildApp'
]);
};

387
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/Polyline.js

@ -0,0 +1,387 @@
/* Copyright 2005-2015 Alfresco Software, Ltd.
*
* 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.
*/
/**
* Class to generate polyline
*
* @author Dmitry Farafonov
*/
var ANCHOR_TYPE= {
main: "main",
middle: "middle",
first: "first",
last: "last"
};
function Anchor(uuid, type, x, y) {
this.uuid = uuid;
this.x = x;
this.y = y;
this.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;
};
Anchor.prototype = {
uuid: null,
x: 0,
y: 0,
type: ANCHOR_TYPE.main,
isFirst: false,
isLast: false,
ndex: 0,
typeIndex: 0
};
function Polyline(uuid, points, strokeWidth, paper) {
/* Array on coordinates:
* points: [{x: 410, y: 110}, 1
* {x: 570, y: 110}, 1 2
* {x: 620, y: 240}, 2 3
* {x: 750, y: 270}, 3 4
* {x: 650, y: 370}]; 4
*/
this.points = points;
/*
* path for graph
* [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
*/
this.path = [];
this.anchors = [];
if (strokeWidth) this.strokeWidth = strokeWidth;
this.paper = paper;
this.closePath = false;
this.init();
};
Polyline.prototype = {
id: null,
points: [],
path: [],
anchors: [],
strokeWidth: 1,
radius: 1,
showDetails: false,
paper: null,
element: null,
isDefaultConditionAvailable: false,
closePath: false,
init: function(points){
var linesCount = this.getLinesCount();
if (linesCount < 1)
return;
this.normalizeCoordinates();
// create anchors
this.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);
for (var i = 1; i < linesCount; i++)
{
var line1 = this.getLine(i-1);
this.pushAnchor(ANCHOR_TYPE.main, line1.x2, line1.y2);
}
this.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);
this.rebuildPath();
},
normalizeCoordinates: function(){
for(var i=0; i < this.points.length; i++){
this.points[i].x = parseFloat(this.points[i].x);
this.points[i].y = parseFloat(this.points[i].y);
}
},
getLinesCount: function(){
return this.points.length-1;
},
_getLine: function(i){
if (this.points.length > i && this.points[i]) {
return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};
} else {
return undefined;
}
},
getLine: function(i){
var line = this._getLine(i);
if (line != undefined) {
line.angle = this.getLineAngle(i);
}
return line;
},
getLineAngle: function(i){
var line = this._getLine(i);
return Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
},
getLineLengthX: function(i){
var line = this.getLine(i);
return (line.x2 - line.x1);
},
getLineLengthY: function(i){
var line = this.getLine(i);
return (line.y2 - line.y1);
},
getLineLength: function(i){
return Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));
},
getAnchors: function(){
return this.anchors;
},
getAnchorsCount: function(type){
if (!type)
return this.anchors.length;
else {
var count = 0;
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.getType() == type) {
count++;
}
}
return count;
}
},
pushAnchor: function(type, x, y, index){
if (type == ANCHOR_TYPE.first) {
index = 0;
typeIndex = 0;
} else if (type == ANCHOR_TYPE.last) {
index = this.getAnchorsCount();
typeIndex = 0;
} else if (!index) {
index = this.anchors.length;
} else {
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.index > index) {
anchor.index++;
anchor.typeIndex++;
}
}
}
var anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);
this.anchors.push(anchor);
},
getAnchor: function(position){
return this.anchors[position];
},
getAnchorByType: function(type, position){
if (type == ANCHOR_TYPE.first)
return this.anchors[0];
if (type == ANCHOR_TYPE.last)
return this.anchors[this.getAnchorsCount()-1];
for(var i=0; i < this.getAnchorsCount(); i++){
var anchor = this.anchors[i];
if (anchor.type == type) {
if( position == anchor.position)
return anchor;
}
}
return null;
},
addNewPoint: function(position, x, y){
//
for(var i = 0; i < this.getLinesCount(); i++){
var line = this.getLine(i);
if (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) {
this.points.splice(i+1,0,{x: x, y: y});
break;
}
}
this.rebuildPath();
},
rebuildPath: function(){
var path = [];
for(var i = 0; i < this.getAnchorsCount(); i++){
var anchor = this.getAnchor(i);
var pathType = "";
if (i == 0)
pathType = "M";
else
pathType = "L";
// TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous
var targetX = anchor.x, targetY = anchor.y;
if (i>0 && i < this.getAnchorsCount()-1) {
// get new x,y
var cx = anchor.x, cy = anchor.y;
// pivot point of prev line
var AO = this.getLineLength(i-1);
if (AO < this.radius) {
AO = this.radius;
}
this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
var ED = this.getLineLengthY(i-1) * this.radius / AO;
var OD = this.getLineLengthX(i-1) * this.radius / AO;
targetX = anchor.x - OD;
targetY = anchor.y - ED;
if (AO < 2*this.radius && i>1) {
targetX = anchor.x - this.getLineLengthX(i-1)/2;
targetY = anchor.y - this.getLineLengthY(i-1)/2;;
}
// pivot point of next line
var AO = this.getLineLength(i);
if (AO < this.radius) {
AO = this.radius;
}
var ED = this.getLineLengthY(i) * this.radius / AO;
var OD = this.getLineLengthX(i) * this.radius / AO;
var nextSrcX = anchor.x + OD;
var nextSrcY = anchor.y + ED;
if (AO < 2*this.radius && i<this.getAnchorsCount()-2) {
nextSrcX = anchor.x + this.getLineLengthX(i)/2;
nextSrcY = anchor.y + this.getLineLengthY(i)/2;;
}
var dx0 = (cx - targetX) / 3,
dy0 = (cy - targetY) / 3,
ax = cx - dx0,
ay = cy - dy0,
dx1 = (cx - nextSrcX) / 3,
dy1 = (cy - nextSrcY) / 3,
bx = cx - dx1,
by = cy - dy1,
zx=nextSrcX, zy=nextSrcY;
} else if (i==1 && this.getAnchorsCount() == 2){
var AO = this.getLineLength(i-1);
if (AO < this.radius) {
AO = this.radius;
}
this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
}
// anti smoothing
if (this.strokeWidth%2 == 1) {
targetX += 0.5;
targetY += 0.5;
}
path.push([pathType, targetX, targetY]);
if (i>0 && i < this.getAnchorsCount()-1) {
path.push(["C", ax, ay, bx, by, zx, zy]);
}
}
if (this.closePath)
{
path.push(["Z"]);
}
this.path = path;
},
transform: function(transformation)
{
this.element.transform(transformation);
},
attr: function(attrs)
{
// TODO: foreach and set each
this.element.attr(attrs);
}
};
function Polygone(points, strokeWidth) {
/* Array on coordinates:
* points: [{x: 410, y: 110}, 1
* {x: 570, y: 110}, 1 2
* {x: 620, y: 240}, 2 3
* {x: 750, y: 270}, 3 4
* {x: 650, y: 370}]; 4
*/
this.points = points;
/*
* path for graph
* [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
*/
this.path = [];
this.anchors = [];
if (strokeWidth) this.strokeWidth = strokeWidth;
this.closePath = true;
this.init();
};
/*
* Poligone is inherited from Poliline: draws closedPath of polyline
*/
var Foo = function () { };
Foo.prototype = Polyline.prototype;
Polygone.prototype = new Foo();
Polygone.prototype.rebuildPath = function(){
var path = [];
for(var i = 0; i < this.getAnchorsCount(); i++){
var anchor = this.getAnchor(i);
var pathType = "";
if (i == 0)
pathType = "M";
else
pathType = "L";
var targetX = anchor.x, targetY = anchor.y;
// anti smoothing
if (this.strokeWidth%2 == 1) {
targetX += 0.5;
targetY += 0.5;
}
path.push([pathType, targetX, targetY]);
}
if (this.closePath)
path.push(["Z"]);
this.path = path;
};

880
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/bpmn-draw.js

@ -0,0 +1,880 @@
/* Copyright 2005-2015 Alfresco Software, Ltd.
*
* 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.
*/
function _bpmnGetColor(element, defaultColor)
{
var strokeColor;
if(element.current) {
strokeColor = CURRENT_COLOR;
} else if(element.completed) {
strokeColor = COMPLETED_COLOR;
} else {
strokeColor = defaultColor;
}
return strokeColor;
}
function _drawPool(pool)
{
var rect = paper.rect(pool.x, pool.y, pool.width, pool.height);
rect.attr({"stroke-width": 1,
"stroke": "#000000",
"fill": "white"
});
if (pool.name)
{
var poolName = paper.text(pool.x + 14, pool.y + (pool.height / 2), pool.name).attr({
"text-anchor" : "middle",
"font-family" : "Arial",
"font-size" : "12",
"fill" : "#000000"
});
poolName.transform("r270");
}
if (pool.lanes)
{
for (var i = 0; i < pool.lanes.length; i++)
{
var lane = pool.lanes[i];
_drawLane(lane);
}
}
}
function _drawLane(lane)
{
var rect = paper.rect(lane.x, lane.y, lane.width, lane.height);
rect.attr({"stroke-width": 1,
"stroke": "#000000",
"fill": "white"
});
if (lane.name)
{
var laneName = paper.text(lane.x + 10, lane.y + (lane.height / 2), lane.name).attr({
"text-anchor" : "middle",
"font-family" : "Arial",
"font-size" : "12",
"fill" : "#000000"
});
laneName.transform("r270");
}
}
function _drawSubProcess(element)
{
var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
rect.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
}
function _drawTransaction(element)
{
var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
rect.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
var borderRect = paper.rect(element.x + 2, element.y + 2, element.width - 4, element.height -4, 4);
borderRect.attr({"stroke-width": 1,
"stroke": "black",
"fill": "none"
});
}
function _drawEventSubProcess(element)
{
var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
rect.attr({"stroke-width": 1,
"stroke": strokeColor,
"stroke-dasharray": ".",
"fill": "white"
});
}
function _drawAdhocSubProcess(element)
{
var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
rect.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
paper.text(element.x + (element.width / 2), element.y + element.height - 8).attr({
"text-anchor" : "middle",
"font-family" : "Arial",
"font-size" : 20,
"text" : "~",
"fill" : "#373e48"
});
}
function _drawStartEvent(element)
{
var startEvent = _drawEvent(element, NORMAL_STROKE, 15);
startEvent.click(function() {
_zoom(true);
});
_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
}
function _drawEndEvent(element)
{
var endEvent = _drawEvent(element, ENDEVENT_STROKE, 14);
endEvent.click(function() {
_zoom(false);
});
_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
}
function _drawEvent(element, strokeWidth, radius)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, radius);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
// Fill
var eventFillColor = _determineCustomFillColor(element, "#ffffff");
// Opacity
var eventOpacity = 1.0;
if (customActivityBackgroundOpacity) {
eventOpacity = customActivityBackgroundOpacity;
}
if (element.interrupting === undefined || element.interrupting) {
circle.attr({
"stroke-width": strokeWidth,
"stroke": strokeColor,
"fill": eventFillColor,
"fill-opacity": eventOpacity
});
} else {
circle.attr({
"stroke-width": strokeWidth,
"stroke": strokeColor,
"stroke-dasharray": ".",
"fill": eventFillColor,
"fill-opacity": eventOpacity
});
}
circle.id = element.id;
_drawEventIcon(paper, element);
return circle;
}
function _drawServiceTask(element)
{
_drawTask(element);
if (element.taskType === "mail")
{
_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "camel")
{
_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "mule")
{
_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "http")
{
_drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "shell")
{
_drawShellTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.taskType === "dmn") {
_drawDecisionTaskIcon(paper, element.x + 4, element.y + 4);
}
else if (element.stencilIconId)
{
paper.image("../service/stencilitem/" + element.stencilIconId + "/icon", element.x + 4, element.y + 4, 16, 16);
}
else
{
_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);
}
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawSendEventServiceTask(element)
{
_drawTask(element);
_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawExternalWorkerServiceTask(element)
{
_drawTask(element);
_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawHttpServiceTask(element)
{
_drawTask(element);
_drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawCallActivity(element)
{
var width = element.width - (CALL_ACTIVITY_STROKE / 2);
var height = element.height - (CALL_ACTIVITY_STROKE / 2);
var rect = paper.rect(element.x, element.y, width, height, 4);
var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);
// Fill
var callActivityFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var callActivityOpacity = 1.0;
if (customActivityBackgroundOpacity) {
callActivityOpacity = customActivityBackgroundOpacity;
}
rect.attr({"stroke-width": CALL_ACTIVITY_STROKE,
"stroke": strokeColor,
"fill": callActivityFillColor,
"fill-opacity": callActivityOpacity
});
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
}
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawScriptTask(element)
{
_drawTask(element);
_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawUserTask(element)
{
_drawTask(element);
_drawUserTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawBusinessRuleTask(element)
{
_drawTask(element);
_drawBusinessRuleTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawManualTask(element)
{
_drawTask(element);
_drawManualTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawSendTask(element)
{
_drawTask(element);
_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawReceiveTask(element)
{
_drawTask(element);
_drawReceiveTaskIcon(paper, element.x, element.y);
_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
}
function _drawTask(element)
{
var rectAttrs = {};
// Stroke
var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);
rectAttrs['stroke'] = strokeColor;
var strokeWidth;
if (strokeColor === ACTIVITY_STROKE_COLOR) {
strokeWidth = TASK_STROKE;
} else {
strokeWidth = TASK_HIGHLIGHT_STROKE;
}
var width = element.width - (strokeWidth / 2);
var height = element.height - (strokeWidth / 2);
var rect = paper.rect(element.x, element.y, width, height, 4);
rectAttrs['stroke-width'] = strokeWidth;
// Fill
var fillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
rectAttrs['fill'] = fillColor;
// Opacity
if (customActivityBackgroundOpacity) {
rectAttrs['fill-opacity'] = customActivityBackgroundOpacity;
}
rect.attr(rectAttrs);
rect.id = element.id;
if (element.name) {
this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
}
}
function _drawExclusiveGateway(element)
{
_drawGateway(element);
var quarterWidth = element.width / 4;
var quarterHeight = element.height / 4;
var iks = paper.path(
"M" + (element.x + quarterWidth + 3) + " " + (element.y + quarterHeight + 3) +
"L" + (element.x + 3 * quarterWidth - 3) + " " + (element.y + 3 * quarterHeight - 3) +
"M" + (element.x + quarterWidth + 3) + " " + (element.y + 3 * quarterHeight - 3) +
"L" + (element.x + 3 * quarterWidth - 3) + " " + (element.y + quarterHeight + 3)
);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
// Fill
var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var gatewayOpacity = 1.0;
if (customActivityBackgroundOpacity) {
gatewayOpacity = customActivityBackgroundOpacity;
}
iks.attr({"stroke-width": 3, "stroke": strokeColor, "fill": gatewayFillColor, "fill-opacity": gatewayOpacity});
_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
}
function _drawParallelGateway(element)
{
_drawGateway(element);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
var path1 = paper.path("M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75");
// Fill
var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var gatewayOpacity = 1.0;
if (customActivityBackgroundOpacity) {
gatewayOpacity = customActivityBackgroundOpacity;
}
path1.attr({
"stroke-width": 3,
"stroke": strokeColor,
"fill": gatewayFillColor,
"fill-opacity": gatewayOpacity
});
path1.transform("T" + (element.x + 4) + "," + (element.y + 4));
_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
}
function _drawInclusiveGateway(element)
{
_drawGateway(element);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
var circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 9.75);
// Fill
var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var gatewayOpacity = 1.0;
if (customActivityBackgroundOpacity) {
gatewayOpacity = customActivityBackgroundOpacity;
}
circle1.attr({
"stroke-width": 2.5,
"stroke": strokeColor,
"fill": gatewayFillColor,
"fill-opacity": gatewayOpacity
});
_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
}
function _drawEventGateway(element)
{
_drawGateway(element);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
var circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 10.4);
// Fill
var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var gatewayOpacity = 1.0;
if (customActivityBackgroundOpacity) {
gatewayOpacity = customActivityBackgroundOpacity;
}
circle1.attr({
"stroke-width": 0.5,
"stroke": strokeColor,
"fill": gatewayFillColor,
"fill-opacity": gatewayOpacity
});
var circle2 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 11.7);
circle2.attr({
"stroke-width": 0.5,
"stroke": strokeColor,
"fill": gatewayFillColor,
"fill-opacity": gatewayOpacity
});
var path1 = paper.path("M 20.327514,22.344972 L 11.259248,22.344216 L 8.4577203,13.719549 L 15.794545,8.389969 L 23.130481,13.720774 L 20.327514,22.344972 z");
path1.attr({
"stroke-width": 1.39999998,
"stroke": strokeColor,
"fill": gatewayFillColor,
"fill-opacity": gatewayOpacity,
"stroke-linejoin": "bevel"
});
path1.transform("T" + (element.x + 4) + "," + (element.y + 4));
_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
}
function _drawGateway(element)
{
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
var rhombus = 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"
);
// Fill
var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
// Opacity
var gatewayOpacity = 1.0;
if (customActivityBackgroundOpacity) {
gatewayOpacity = customActivityBackgroundOpacity;
}
rhombus.attr("stroke-width", 2);
rhombus.attr("stroke", strokeColor);
rhombus.attr("fill", gatewayFillColor);
rhombus.attr("fill-opacity", gatewayOpacity);
rhombus.id = element.id;
return rhombus;
}
function _drawBoundaryEvent(element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 15);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
if (element.cancelActivity) {
circle.attr({
"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
} else {
circle.attr({
"stroke-width": 1,
"stroke-dasharray": ".",
"stroke": strokeColor,
"fill": "white"
});
}
var innerCircle = paper.circle(x, y, 12);
if (element.cancelActivity) {
innerCircle.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "none"
});
} else {
innerCircle.attr({
"stroke-width": 1,
"stroke-dasharray": ".",
"stroke": strokeColor,
"fill": "none"
});
}
_drawEventIcon(paper, element);
_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
circle.id = element.id;
innerCircle.id = element.id + "_inner";
}
function _drawIntermediateCatchEvent(element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 15);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
circle.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
var innerCircle = paper.circle(x, y, 12);
innerCircle.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "none"
});
_drawEventIcon(paper, element);
_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
circle.id = element.id;
innerCircle.id = element.id + "_inner";
}
function _drawThrowEvent(element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 15);
var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
circle.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "white"
});
var innerCircle = paper.circle(x, y, 12);
innerCircle.attr({"stroke-width": 1,
"stroke": strokeColor,
"fill": "none"
});
_drawEventIcon(paper, element);
_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
circle.id = element.id;
innerCircle.id = element.id + "_inner";
}
function _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)
{
if (!text || text == "")
{
return;
}
var textBoxX, textBoxY;
var width = boxWidth - (2 * TEXT_PADDING);
if (horizontalAnchor === "middle")
{
textBoxX = x + (boxWidth / 2);
}
else if (horizontalAnchor === "start")
{
textBoxX = x;
}
textBoxY = y + (boxHeight / 2);
var t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({
"text-anchor" : horizontalAnchor,
"font-family" : "Arial",
"font-size" : fontSize,
"fill" : "#373e48"
});
var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
t.attr({
"text" : abc
});
var letterWidth = t.getBBox().width / abc.length;
t.attr({
"text" : text
});
var removedLineBreaks = text.split("\n");
var x = 0, s = [];
for (var r = 0; r < removedLineBreaks.length; r++)
{
var words = removedLineBreaks[r].split(" ");
for ( var i = 0; i < words.length; i++) {
var l = words[i].length;
if (x + (l * letterWidth) > width) {
s.push("\n");
x = 0;
}
x += l * letterWidth;
s.push(words[i] + " ");
}
s.push("\n");
x = 0;
}
t.attr({
"text" : s.join("")
});
if (verticalAnchor && verticalAnchor === "top")
{
t.attr({"y": y + (t.getBBox().height / 2)});
}
}
function _drawTextAnnotation(element)
{
var path1 = paper.path("M20,1 L1,1 L1,50 L20,50");
path1.attr({
"stroke": "#585858",
"fill": "none"
});
var annotation = paper.set();
annotation.push(path1);
annotation.transform("T" + element.x + "," + element.y);
if (element.text) {
this._drawMultilineText(element.text, element.x + 2, element.y, element.width, element.height, "start", "middle", 11);
}
}
function _drawFlow(flow){
var polyline = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);
var strokeColor = _bpmnGetColor(flow, MAIN_STROKE_COLOR);
polyline.element = paper.path(polyline.path);
polyline.element.attr({"stroke-width":SEQUENCEFLOW_STROKE});
polyline.element.attr({"stroke":strokeColor});
polyline.element.id = flow.id;
var lastLineIndex = polyline.getLinesCount() - 1;
var line = polyline.getLine(lastLineIndex);
if (line == undefined) return;
if (flow.type == "connection" && flow.conditions)
{
var middleX = (line.x1 + line.x2) / 2;
var middleY = (line.y1 + line.y2) / 2;
var image = paper.image("../editor/images/condition-flow.png", middleX - 8, middleY - 8, 16, 16);
}
var polylineInvisible = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);
polylineInvisible.element = paper.path(polyline.path);
polylineInvisible.element.attr({
"opacity": 0,
"stroke-width": 8,
"stroke" : "#000000"
});
if (flow.name) {
var firstLine = polyline.getLine(0);
var angle;
if (firstLine.x1 !== firstLine.x2) {
angle = Math.atan((firstLine.y2 - firstLine.y1) / (firstLine.x2 - firstLine.x1));
} else if (firstLine.y1 < firstLine.y2) {
angle = Math.PI / 2;
} else {
angle = -Math.PI / 2;
}
var flowName = paper.text(firstLine.x1, firstLine.y1, flow.name).attr({
"text-anchor": "middle",
"font-family" : "Arial",
"font-size" : "12",
"fill" : "#000000"
});
var offsetX = (flowName.getBBox().width / 2 + 5);
var offsetY = -(flowName.getBBox().height / 2 + 5);
if (firstLine.x1 > firstLine.x2) {
offsetX = -offsetX;
}
var rotatedOffsetX = offsetX * Math.cos(angle) - offsetY * Math.sin(angle);
var rotatedOffsetY = offsetX * Math.sin(angle) + offsetY * Math.cos(angle);
flowName.attr({
x: firstLine.x1 + rotatedOffsetX,
y: firstLine.y1 + rotatedOffsetY
});
flowName.transform("r" + ((angle) * 180) / Math.PI);
}
_showTip(jQuery(polylineInvisible.element.node), flow);
polylineInvisible.element.mouseover(function() {
paper.getById(polyline.element.id).attr({"stroke":"blue"});
});
polylineInvisible.element.mouseout(function() {
paper.getById(polyline.element.id).attr({"stroke":"#585858"});
});
_drawArrowHead(line);
}
function _drawAssociation(flow){
var polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
polyline.element = paper.path(polyline.path);
polyline.element.attr({"stroke-width": ASSOCIATION_STROKE});
polyline.element.attr({"stroke-dasharray": ". "});
polyline.element.attr({"stroke":"#585858"});
polyline.element.id = flow.id;
var polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
polylineInvisible.element = paper.path(polyline.path);
polylineInvisible.element.attr({
"opacity": 0,
"stroke-width": 8,
"stroke" : "#000000"
});
_showTip(jQuery(polylineInvisible.element.node), flow);
polylineInvisible.element.mouseover(function() {
paper.getById(polyline.element.id).attr({"stroke":"blue"});
});
polylineInvisible.element.mouseout(function() {
paper.getById(polyline.element.id).attr({"stroke":"#585858"});
});
}
function _drawArrowHead(line, connectionType)
{
var doubleArrowWidth = 2 * ARROW_WIDTH;
var arrowHead = paper.path("M0 0L-" + (ARROW_WIDTH / 2 + .5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2 + .5) + " -" + doubleArrowWidth + "z");
// anti smoothing
if (this.strokeWidth%2 == 1)
line.x2 += .5, line.y2 += .5;
arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
arrowHead.attr("fill", "#585858");
arrowHead.attr("stroke-width", SEQUENCEFLOW_STROKE);
arrowHead.attr("stroke", "#585858");
return arrowHead;
}
function _determineCustomFillColor(element, defaultColor) {
var color;
// By name
if (customActivityColors && customActivityColors[element.name]) {
color = customActivityColors[element.name];
}
if (color !== null && color !== undefined) {
return color;
}
// By id
if (customActivityColors && customActivityColors[element.id]) {
color = customActivityColors[element.id];
}
if (color !== null && color !== undefined) {
return color;
}
return defaultColor;
}

395
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/bpmn-icons.js

@ -0,0 +1,395 @@
/* 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.
*/
function _drawUserTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#d1b575"
});
var userTaskIcon = paper.set();
userTaskIcon.push(path1);
userTaskIcon.transform("T" + startX + "," + startY);
}
function _drawServiceTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375 6.6676654,3.4929791 6.3336971,3.6092802 6.03125,3.78125 6.02349,3.78566 6.007733,3.77681 6,3.78125 5.8811373,3.761018 5.8125,3.71875 5.8125,3.71875 l -1.6875,-1 -1.40625,1.4375 0.96875,1.65625 c 0,0 0.065705,0.068637 0.09375,0.1875 0.002,0.00849 -0.00169,0.022138 0,0.03125 C 3.6092802,6.3336971 3.4929791,6.6676654 3.375,7 3.3629836,7.0338489 3.3239228,7.0596246 3.3125,7.09375 3.125763,7.4756184 2.875,7.5 2.875,7.5 L 1,8 l 0,2 1.875,0.5 c 0,0 0.250763,0.02438 0.4375,0.40625 0.017853,0.03651 0.046318,0.04988 0.0625,0.09375 0.1129372,0.318132 0.2124732,0.646641 0.375,0.9375 -0.00302,0.215512 -0.09375,0.34375 -0.09375,0.34375 L 2.6875,13.9375 4.09375,15.34375 5.78125,14.375 c 0,0 0.1229911,-0.09744 0.34375,-0.09375 0.2720511,0.147787 0.5795915,0.23888 0.875,0.34375 0.033849,0.01202 0.059625,0.05108 0.09375,0.0625 C 7.4756199,14.874237 7.5,15.125 7.5,15.125 L 8,17 l 2,0 0.5,-1.875 c 0,0 0.02438,-0.250763 0.40625,-0.4375 0.03651,-0.01785 0.04988,-0.04632 0.09375,-0.0625 0.332335,-0.117979 0.666303,-0.23428 0.96875,-0.40625 0.177303,0.0173 0.28125,0.09375 0.28125,0.09375 l 1.65625,0.96875 1.40625,-1.40625 -0.96875,-1.65625 c 0,0 -0.07645,-0.103947 -0.09375,-0.28125 0.162527,-0.290859 0.262063,-0.619368 0.375,-0.9375 0.01618,-0.04387 0.04465,-0.05724 0.0625,-0.09375 C 14.874237,10.52438 15.125,10.5 15.125,10.5 L 17,10 17,8 15.125,7.5 c 0,0 -0.250763,-0.024382 -0.4375,-0.40625 C 14.669647,7.0572406 14.641181,7.0438697 14.625,7 14.55912,6.8144282 14.520616,6.6141566 14.4375,6.4375 c -0.224363,-0.4866 0,-0.71875 0,-0.71875 L 15.40625,4.0625 14,2.625 l -1.65625,1 c 0,0 -0.253337,0.1695664 -0.71875,-0.03125 l -0.03125,0 C 11.405359,3.5035185 11.198648,3.4455201 11,3.375 10.95613,3.3588185 10.942759,3.3303534 10.90625,3.3125 10.524382,3.125763 10.5,2.875 10.5,2.875 L 10,1 8,1 z m 1,5 c 1.656854,0 3,1.3431458 3,3 0,1.656854 -1.343146,3 -3,3 C 7.3431458,12 6,10.656854 6,9 6,7.3431458 7.3431458,6 9,6 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var serviceTaskIcon = paper.set();
serviceTaskIcon.push(path1);
serviceTaskIcon.transform("T" + startX + "," + startY);
}
function _drawScriptTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 5,2 0,0.094 c 0.23706,0.064 0.53189,0.1645 0.8125,0.375 0.5582,0.4186 1.05109,1.228 1.15625,2.5312 l 8.03125,0 1,0 1,0 c 0,-3 -2,-3 -2,-3 l -10,0 z M 4,3 4,13 2,13 c 0,3 2,3 2,3 l 9,0 c 0,0 2,0 2,-3 L 15,6 6,6 6,5.5 C 6,4.1111 5.5595,3.529 5.1875,3.25 4.8155,2.971 4.5,3 4.5,3 L 4,3 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#72a7d0"
});
var scriptTaskIcon = paper.set();
scriptTaskIcon.push(path1);
scriptTaskIcon.transform("T" + startX + "," + startY);
}
function _drawBusinessRuleTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.7999224 -8.72718,0 z m -4.36364,4.1998844 2.90906,0 0,2.800116 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.800116 -8.72718,0 z");
path1.attr({
"stroke": "none",
"fill": "#72a7d0"
});
var businessRuleTaskIcon = paper.set();
businessRuleTaskIcon.push(path1);
businessRuleTaskIcon.transform("T" + startX + "," + startY);
}
function _drawSendTaskIcon(paper, startX, startY)
{
var path1 = paper.path("M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z");
path1.attr({
"stroke": "none",
"fill": "#16964d"
});
var sendTaskIcon = paper.set();
sendTaskIcon.push(path1);
sendTaskIcon.transform("T" + startX + "," + startY);
}
function _drawManualTaskIcon(paper, startX, startY)
{
var path1 = paper.path("m 17,9.3290326 c -0.0069,0.5512461 -0.455166,1.0455894 -0.940778,1.0376604 l -5.792746,0 c 0.0053,0.119381 0.0026,0.237107 0.0061,0.355965 l 5.154918,0 c 0.482032,-0.0096 0.925529,0.49051 0.919525,1.037574 -0.0078,0.537128 -0.446283,1.017531 -0.919521,1.007683 l -5.245273,0 c -0.01507,0.104484 -0.03389,0.204081 -0.05316,0.301591 l 2.630175,0 c 0.454137,-0.0096 0.872112,0.461754 0.866386,0.977186 C 13.619526,14.554106 13.206293,15.009498 12.75924,15 L 3.7753054,15 C 3.6045812,15 3.433552,14.94423 3.2916363,14.837136 c -0.00174,0 -0.00436,0 -0.00609,0 C 1.7212035,14.367801 0.99998255,11.458641 1,11.458641 L 1,7.4588393 c 0,0 0.6623144,-1.316333 1.8390583,-2.0872584 1.1767614,-0.7711868 6.8053358,-2.40497 7.2587847,-2.8052901 0.453484,-0.40032 1.660213,1.4859942 0.04775,2.4010487 C 8.5332315,5.882394 8.507351,5.7996113 8.4370292,5.7936859 l 6.3569748,-0.00871 c 0.497046,-0.00958 0.952273,0.5097676 0.94612,1.0738232 -0.0053,0.556126 -0.456176,1.0566566 -0.94612,1.0496854 l -4.72435,0 c 0.01307,0.1149374 0.0244,0.2281319 0.03721,0.3498661 l 5.952195,0 c 0.494517,-0.00871 0.947906,0.5066305 0.940795,1.0679848 z");
path1.attr({
"opacity": 1,
"stroke": "none",
"fill": "#d1b575"
});
var manualTaskIcon = paper.set();
manualTaskIcon.push(path1);
manualTaskIcon.transform("T" + startX + "," + startY);
}
function _drawReceiveTaskIcon(paper, startX, startY)
{
var path = paper.path("m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z M 7.5,9.5 9,11 10.5,9.5 15,14 3,14 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#16964d"
});
startX += 4;
startY += 2;
path.transform("T" + startX + "," + startY);
}
function _drawCamelTaskIcon(paper, startX, startY)
{
var path = paper.path("m 8.1878027,15.383782 c -0.824818,-0.3427 0.375093,-1.1925 0.404055,-1.7743 0.230509,-0.8159 -0.217173,-1.5329 -0.550642,-2.2283 -0.106244,-0.5273 -0.03299,-1.8886005 -0.747194,-1.7818005 -0.712355,0.3776 -0.9225,1.2309005 -1.253911,1.9055005 -0.175574,1.0874 -0.630353,2.114 -0.775834,3.2123 -0.244009,0.4224 -1.741203,0.3888 -1.554386,-0.1397 0.651324,-0.3302 1.13227,-0.9222 1.180246,-1.6705 0.0082,-0.7042 -0.133578,-1.3681 0.302178,-2.0083 0.08617,-0.3202 0.356348,-1.0224005 -0.218996,-0.8051 -0.694517,0.2372 -1.651062,0.6128 -2.057645,-0.2959005 -0.696769,0.3057005 -1.102947,-0.611 -1.393127,-1.0565 -0.231079,-0.6218 -0.437041,-1.3041 -0.202103,-1.9476 -0.185217,-0.7514 -0.39751099,-1.5209 -0.35214999,-2.301 -0.243425,-0.7796 0.86000899,-1.2456 0.08581,-1.8855 -0.76078999,0.1964 -1.41630099,-0.7569 -0.79351899,-1.2877 0.58743,-0.52829998 1.49031699,-0.242 2.09856399,-0.77049998 0.816875,-0.3212 1.256619,0.65019998 1.923119,0.71939998 0.01194,0.7333 -0.0031,1.5042 -0.18417,2.2232 -0.194069,0.564 -0.811196,1.6968 0.06669,1.9398 0.738382,-0.173 1.095723,-0.9364 1.659041,-1.3729 0.727298,-0.3962 1.093982,-1.117 1.344137,-1.8675 0.400558,-0.8287 1.697676,-0.6854 1.955367,0.1758 0.103564,0.5511 0.9073983,1.7538 1.2472763,0.6846 0.121868,-0.6687 0.785541,-1.4454 1.518183,-1.0431 0.813587,0.4875 0.658233,1.6033 1.285504,2.2454 0.768715,0.8117 1.745394,1.4801 2.196633,2.5469 0.313781,0.8074 0.568552,1.707 0.496624,2.5733 -0.35485,0.8576005 -1.224508,-0.216 -0.64725,-0.7284 0.01868,-0.3794 -0.01834,-1.3264 -0.370249,-1.3272 -0.123187,0.7586 -0.152778,1.547 -0.10869,2.3154 0.270285,0.6662005 1.310741,0.7653005 1.060553,1.6763005 -0.03493,0.9801 0.294343,1.9505 0.148048,2.9272 -0.320479,0.2406 -0.79575,0.097 -1.185062,0.1512 -0.165725,0.3657 -0.40138,0.921 -1.020848,0.6744 -0.564671,0.1141 -1.246404,-0.266 -0.578559,-0.7715 0.679736,-0.5602 0.898618,-1.5362 0.687058,-2.3673 -0.529674,-1.108 -1.275984,-2.0954005 -1.839206,-3.1831005 -0.634619,-0.1004 -1.251945,0.6779 -1.956789,0.7408 -0.6065893,-0.038 -1.0354363,-0.06 -0.8495673,0.6969005 0.01681,0.711 0.152396,1.3997 0.157345,2.1104 0.07947,0.7464 0.171287,1.4944 0.238271,2.2351 0.237411,1.0076 -0.687542,1.1488 -1.414811,0.8598 z m 6.8675483,-1.8379 c 0.114364,-0.3658 0.206751,-1.2704 -0.114466,-1.3553 -0.152626,0.5835 -0.225018,1.1888 -0.227537,1.7919 0.147087,-0.1166 0.265559,-0.2643 0.342003,-0.4366 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#bd4848"
});
startX += 4;
startY += 2;
path.transform("T" + startX + "," + startY);
}
function _drawMuleTaskIcon(paper, startX, startY)
{
var path = paper.path("M 8,0 C 3.581722,0 0,3.5817 0,8 c 0,4.4183 3.581722,8 8,8 4.418278,0 8,-3.5817 8,-8 L 16,7.6562 C 15.813571,3.3775 12.282847,0 8,0 z M 5.1875,2.7812 8,7.3437 10.8125,2.7812 c 1.323522,0.4299 2.329453,1.5645 2.8125,2.8438 1.136151,2.8609 -0.380702,6.4569 -3.25,7.5937 -0.217837,-0.6102 -0.438416,-1.2022 -0.65625,-1.8125 0.701032,-0.2274 1.313373,-0.6949 1.71875,-1.3125 0.73624,-1.2317 0.939877,-2.6305 -0.03125,-4.3125 l -2.75,4.0625 -0.65625,0 -0.65625,0 -2.75,-4 C 3.5268433,7.6916 3.82626,8.862 4.5625,10.0937 4.967877,10.7113 5.580218,11.1788 6.28125,11.4062 6.063416,12.0165 5.842837,12.6085 5.625,13.2187 2.755702,12.0819 1.238849,8.4858 2.375,5.625 2.858047,4.3457 3.863978,3.2112 5.1875,2.7812 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#bd4848"
});
startX += 4;
startY += 2;
path.transform("T" + startX + "," + startY);
}
function _drawAlfrescoPublishTaskIcon(paper, startX, startY)
{
startX += 2;
startY += 2;
var path = paper.path("M4.11870968,2.12890323 L6.12954839,0.117935484 L3.10993548,0.118064516 L3.10270968,0.118064516 C1.42941935,0.118064516 0.0729032258,1.47458065 0.0729032258,3.14774194 C0.0729032258,4.82116129 1.42929032,6.17754839 3.10258065,6.17754839 C3.22967742,6.17754839 3.35470968,6.16877419 3.47767742,6.15354839 C2.8163871,4.85083871 3.02954839,3.21793548 4.11870968,2.12890323M6.57032258,3.144 L6.57032258,0.300258065 L4.43522581,2.4356129 L4.43006452,2.44064516 C3.24683871,3.62387097 3.24683871,5.54219355 4.43006452,6.72541935 C5.61329032,7.90864516 7.5316129,7.90864516 8.71483871,6.72541935 C8.80464516,6.6356129 8.88529032,6.54025806 8.96154839,6.44270968 C7.57341935,5.98864516 6.57045161,4.68387097 6.57032258,3.144");
path.attr({"fill": "#87C040"});
var startX1 = startX + 1.419355;
var startY1 = startY + 8.387097;
path.transform("T" + startX1 + "," + startY1);
path = paper.path("M10.4411613,10.5153548 L8.43032258,8.50451613 L8.43032258,11.5313548 C8.43032258,13.2047742 9.78683871,14.5611613 11.460129,14.5611613 C13.1334194,14.5611613 14.4899355,13.2047742 14.4899355,11.5314839 C14.4899355,11.4043871 14.4811613,11.2793548 14.4659355,11.1563871 C13.1632258,11.8178065 11.5303226,11.6045161 10.4411613,10.5153548M15.0376774,5.91935484 C14.947871,5.82954839 14.8526452,5.74890323 14.7550968,5.67264516 C14.3010323,7.06064516 12.996129,8.06374194 11.4563871,8.06374194 L8.61277419,8.06374194 L10.7529032,10.204 C11.936129,11.3872258 13.8545806,11.3872258 15.0376774,10.204 C16.2209032,9.02077419 16.2209032,7.10245161 15.0376774,5.91935484");
path.attr({"fill": "#87C040"});
path.transform("T" + startX + "," + startY);
path = paper.path("M5.9083871,1.5636129 C5.78129032,1.5636129 5.65625806,1.57225806 5.53329032,1.58748387 C6.19458065,2.89032258 5.98141935,4.52309677 4.89225806,5.61225806 L2.88154839,7.62309677 L5.9083871,7.62309677 C7.58154839,7.62309677 8.93806452,6.26658065 8.93806452,4.59329032 C8.93819355,2.92 7.58167742,1.5636129 5.9083871,1.5636129");
path.attr({"fill": "#ED9A2D"});
var startX2 = startX + 5.548387;
path.transform("T" + startX2 + "," + startY);
path = paper.path("M4.58090323,1.0156129 C3.39767742,-0.167483871 1.47935484,-0.167483871 0.296129032,1.01574194 C0.206451613,1.10554839 0.125806452,1.20077419 0.0495483871,1.29845161 C1.43754839,1.75251613 2.44064516,3.05729032 2.44064516,4.59703226 L2.44064516,7.44077419 L4.57574194,5.30554839 L4.58090323,5.30051613 C5.76412903,4.11729032 5.76412903,2.19896774 4.58090323,1.0156129");
path.attr({"fill": "#5698C6"});
path.transform("T" + startX2 + "," + startY);
path = paper.path("M5.54051613,5.61432258 L5.62670968,5.70425806 L7.54632258,7.62387097 L7.5483871,7.62387097 L7.5483871,4.604 L7.5483871,4.59677419 C7.5483871,2.92348387 6.19187097,1.56696774 4.51858065,1.56696774 C2.84529032,1.56696774 1.48877419,2.92335484 1.48890323,4.59664516 C1.48890323,4.72348387 1.49754839,4.84812903 1.51264516,4.97083871 C2.81625806,4.30993548 4.45122581,4.52503226 5.54051613,5.61432258M1.23251613,10.4292903 C1.25625806,10.3588387 1.28180645,10.2894194 1.30980645,10.2210323 C1.31329032,10.2123871 1.3163871,10.2036129 1.32,10.1952258 C1.35070968,10.1216774 1.38451613,10.0500645 1.42,9.97935484 C1.42774194,9.96374194 1.43574194,9.9483871 1.44387097,9.93277419 C1.4803871,9.86258065 1.51883871,9.79354839 1.55987097,9.72632258 C1.56425806,9.71909677 1.56903226,9.71225806 1.57341935,9.70529032 C1.6123871,9.64245161 1.65354839,9.58141935 1.6963871,9.52141935 C1.70516129,9.50903226 1.71380645,9.49651613 1.72283871,9.48425806 C1.76890323,9.42154839 1.81690323,9.36064516 1.86683871,9.30129032 C1.87703226,9.28916129 1.88735484,9.27741935 1.89780645,9.26567742 C1.94658065,9.20916129 1.99690323,9.15406452 2.04916129,9.10090323 C2.05380645,9.09625806 2.05806452,9.09135484 2.06270968,9.08670968 C2.11832258,9.03083871 2.17625806,8.97741935 2.23548387,8.92554839 C2.2483871,8.91419355 2.26129032,8.90296774 2.27432258,8.89187097 C2.33393548,8.84103226 2.39496774,8.79212903 2.45780645,8.74529032 C2.46606452,8.73922581 2.47470968,8.73354839 2.48296774,8.7276129 C2.54167742,8.68490323 2.60180645,8.64412903 2.66322581,8.60503226 C2.67535484,8.59729032 2.68735484,8.58929032 2.6996129,8.58167742 C2.76593548,8.54064516 2.83380645,8.50206452 2.90296774,8.46541935 C2.91754839,8.45780645 2.93225806,8.45045161 2.94696774,8.44296774 C3.016,8.40774194 3.08593548,8.37406452 3.15741935,8.34348387 C3.16090323,8.34206452 3.16425806,8.3403871 3.16774194,8.33883871 C3.24167742,8.30748387 3.31729032,8.27948387 3.39380645,8.25316129 C3.41032258,8.24748387 3.42670968,8.24180645 3.44335484,8.2363871 C3.51909677,8.21174194 3.59587097,8.18903226 3.67380645,8.16929032 C3.68567742,8.16645161 3.69793548,8.16387097 3.70980645,8.16116129 C3.78206452,8.14374194 3.85509677,8.12877419 3.92890323,8.116 C3.94270968,8.11367742 3.9563871,8.11083871 3.97019355,8.10877419 C4.05032258,8.09587097 4.13148387,8.08619355 4.21329032,8.07896774 C4.23096774,8.07741935 4.24877419,8.07625806 4.26645161,8.07483871 C4.35109677,8.06877419 4.43612903,8.06451613 4.52232258,8.06451613 L7.36606452,8.0643871 L5.22580645,5.92412903 C4.04258065,4.74103226 2.12412903,4.74090323 0.941032258,5.92412903 C-0.242193548,7.10735484 -0.242193548,9.02567742 0.941032258,10.2089032 C1.03070968,10.2985806 1.12464516,10.3814194 1.22206452,10.4575484 C1.22529032,10.448 1.22929032,10.4388387 1.23251613,10.4292903");
path.attr({"fill": "#5698C6"});
path.transform("T" + startX + "," + startY);
path = paper.path("M5.23290323,5.92412903 L6.92748387,7.61870968 L4.64980645,7.61870968 L4.52064516,7.62141935 C3.13354839,7.62141935 1.96425806,6.68929032 1.60477419,5.41729032 C2.75870968,4.77019355 4.24619355,4.93754839 5.22787097,5.91909677 L5.23290323,5.92412903M7.54722581,4.59612903 L7.54722581,6.99264516 L5.93664516,5.38206452 L5.84348387,5.29264516 C4.86258065,4.31187097 4.69483871,2.82580645 5.34012903,1.67225806 C6.61367742,2.03070968 7.54722581,3.20090323 7.54722581,4.58890323 L7.54722581,4.59612903M10.1385806,5.29819355 L8.444,6.99290323 L8.444,4.71522581 L8.44129032,4.58606452 C8.44129032,3.19896774 9.37341935,2.02954839 10.6454194,1.67019355 C11.2925161,2.82412903 11.1251613,4.3116129 10.1436129,5.29316129 L10.1385806,5.29819355");
path.attr({"fill": "#446BA5"});
path.transform("T" + startX + "," + startY);
path = paper.path("M11.4548387,7.61677419 L9.05832258,7.61677419 L10.6689032,6.00619355 L10.7583226,5.91303226 C11.7390968,4.93212903 13.2251613,4.7643871 14.3787097,5.40967742 C14.0202581,6.68322581 12.8500645,7.61677419 11.4620645,7.61677419 L11.4548387,7.61677419");
path.attr({"fill": "#FFF101"});
path.transform("T" + startX + "," + startY);
path = paper.path("M10.7470968,10.192 L9.05251613,8.49741935 L11.3301935,8.49741935 L11.4593548,8.49470968 C12.8464516,8.49483871 14.0157419,9.42696774 14.3752258,10.6989677 C13.2211613,11.3459355 11.7338065,11.1787097 10.752129,10.1970323 L10.7470968,10.192M8.43729032,11.5174194 L8.43729032,9.12090323 L10.047871,10.7314839 L10.1411613,10.8209032 C11.1219355,11.8018065 11.2896774,13.2876129 10.6443871,14.4412903 C9.37083871,14.0828387 8.43729032,12.9127742 8.43729032,11.5245161 L8.43729032,11.5174194M5.86193548,10.8296774 L7.55651613,9.13496774 L7.55651613,11.4126452 L7.55922581,11.5418065 C7.55922581,12.9289032 6.62709677,14.0983226 5.35509677,14.4578065 C4.708,13.3036129 4.87535484,11.8162581 5.85690323,10.8347097 L5.86193548,10.8296774M4.53251613,8.50993548 L6.92903226,8.50993548 L5.31845161,10.1205161 L5.22903226,10.2136774 C4.24812903,11.1945806 2.76219355,11.3623226 1.60851613,10.7170323 C1.96709677,9.44335484 3.13716129,8.50993548 4.52529032,8.50993548 L4.53251613,8.50993548");
path.attr({"fill": "#45AB47"});
path.transform("T" + startX + "," + startY);
}
function _drawHttpTaskIcon(paper, startX, startY)
{
var path = paper.path("m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L 7.2329969,8.7876913 Q 7.0897576,8.8055849 7.000233,8.9309334 L 4.9948821,12.368677 q -0.035811,0.06267 -0.035811,0.143242 0,0.107426 0.080572,0.205905 l 0.5729577,0.572957 q 0.125334,0.116384 0.2864786,0.07162 l 2.4708789,-0.760963 2.5156417,2.515645 -0.76096,2.470876 q -0.009,0.02687 -0.009,0.08057 0,0.125338 0.08058,0.205905 l 0.572957,0.572958 q 0.170096,0.152194 0.349146,0.04476 l 3.437744,-2.005351 q 0.125335,-0.08953 0.143239,-0.232763 l 0.17905,-3.392986 q 1.02058,-0.859435 1.745729,-1.575629 1.67411,-1.6830612 2.309735,-3.2049805 0.635625,-1.5219191 0.635625,-3.8585111 0,-0.1253369 -0.08505,-0.2148575 -0.08505,-0.089526 -0.201431,-0.089526 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#16964d"
});
startX += -2;
startY += -2;
path.transform("T" + startX + "," + startY);
}
function _drawShellTaskIcon(paper, startX, startY) {
var path = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.4,3 12.7,0 0,10 -12.7,0 z");
path.attr({
"opacity": 1,
"stroke": "none",
"fill": "#16964d"
});
var text = paper.text(3, 9, ">_").attr({
"font-size": "5px",
"fill": "#16964d"
});
startY += -2;
text.transform("T" + startX + "," + startY);
startX += -2;
path.transform("T" + startX + "," + startY);
}
function _drawDecisionTaskIcon(paper, startX, startY) {
var path1 = paper.path("m 1,2 0,14 16,0 0,-14 z m 1.9,2.4000386 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m -8.67364,3.9 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z m 4.36364,0 3.7,0 0,2.7999224 -3.7,0 z");
path1.attr({
"opacity": 1,
"stroke": "#000000",
"fill": "#F4F6F7"
});
var decisionTaskIcon = paper.set();
decisionTaskIcon.push(path1);
decisionTaskIcon.translate(startX, startY);
decisionTaskIcon.scale(0.7, 0.7);
}
function _drawEventIcon(paper, element)
{
if (element.eventDefinition && element.eventDefinition.type) {
if ("timer" === element.eventDefinition.type) {
_drawTimerIcon(paper, element);
} else if ("conditional" === element.eventDefinition.type) {
_drawConditionalIcon(paper, element);
} else if ("error" === element.eventDefinition.type) {
_drawErrorIcon(paper, element);
} else if ("escalation" === element.eventDefinition.type) {
_drawEscalationIcon(paper, element);
} else if ("signal" === element.eventDefinition.type) {
_drawSignalIcon(paper, element);
} else if ("message" === element.eventDefinition.type) {
_drawMessageIcon(paper, element);
} else if ("eventRegistry" === element.eventDefinition.type) {
_drawMessageIcon(paper, element);
} else if ("variable" === element.eventDefinition.type) {
_drawVariableListenerIcon(paper, element);
}
}
}
function _drawConditionalIcon(paper, element)
{
var fill = "none";
var path = paper.path("M 10 10 L 22 10 M 10 14 L 22 14 M 10 18 L 22 18 M 10 22 L 22 22");
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + (element.x - 1) + "," + (element.y - 1));
return path;
}
function _drawVariableListenerIcon(paper, element)
{
var fill = "none";
var path = paper.path("M 20.834856,22.874369 L 10.762008,22.873529 L 7.650126,13.293421 L 15.799725,7.3734296 L 23.948336,13.294781 L 20.834856,22.874369 z");
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + (element.x - 1) + "," + (element.y - 1));
return path;
}
function _drawTimerIcon(paper, element)
{
var x = element.x + (element.width / 2);
var y = element.y + (element.height / 2);
var circle = paper.circle(x, y, 10);
circle.attr({"stroke-width": 1,
"stroke": "black",
"fill": "none"
});
var path = paper.path("M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z");
path.attr({
"stroke": "none",
"fill": "#585858"
});
path.transform("T" + (element.x + 5) + "," + (element.y + 5));
return path;
}
function _drawErrorIcon(paper, element)
{
var path = paper.path("M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 L 13.048949,6.8323057 L 18.996148,16.132659 L 22.820839,11.171502 z");
var fill = "none";
var x = element.x - 1;
var y = element.y - 1;
if (element.type === "EndEvent")
{
fill = "black";
x -= 1;
y -= 1;
}
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + x + "," + y);
return path;
}
function _drawEscalationIcon(paper, element)
{
var fill = "none";
if (element.type === "ThrowEvent")
{
fill = "black";
}
var path = paper.path("M 16,8.75 L22,23.75 L16,17 L10,23.75z");
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + (element.x - 1) + "," + (element.y - 1));
return path;
}
function _drawSignalIcon(paper, element)
{
var fill = "none";
if (element.type === "ThrowEvent")
{
fill = "black";
}
var path = paper.path("M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z");
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + (element.x - 1) + "," + (element.y - 1));
return path;
}
function _drawMessageIcon(paper, element)
{
var fill = "none";
if (element.type === "ThrowEvent")
{
fill = "black";
}
var path = paper.path("M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z");
path.attr({
"stroke": "black",
"stroke-width": 1,
"fill": fill
});
path.transform("T" + (element.x + 6) + "," + (element.y + 6));
return path;
}

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.css

@ -0,0 +1,24 @@
div[class*='ui-tooltip-kisbpm-'] {
background-color: #ffffff;
border-color: #c5c5c5;
color: #4a4a4a;
font-family: Verdana;
font-size: 12px;
}
div[class*='ui-tooltip-kisbpm-'] .qtip-content {
color: #4a4a4a;
background-color: #ffffff;
font-family: Verdana;
font-size: 12px;
}
.ui-tooltip-kisbpm-bpmn .qtip-titlebar {
color: #FFFFFF;
font-size: 12px;
background: #2B414F;
}
.ui-tooltip-kisbpm-bpmn .qtip-tip {
background-color: #2B414F;
}

19
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.html

@ -0,0 +1,19 @@
<html>
<head>
<!-- build:css display/styles/displaymodel-style.css -->
<link type="text/css" rel="stylesheet" href="display/jquery.qtip.min.css" />
<link type="text/css" rel="stylesheet" href="display/displaymodel.css" />
<!-- endbuild -->
<!-- build:js display/scripts/displaymodel-logic.js -->
<script type="text/javascript" src="display/jquery.qtip.min.js"></script>
<script type="text/javascript" src="display/raphael.min.js"></script>
<script type="text/javascript" src="display/bpmn-draw.js"></script>
<script type="text/javascript" src="display/bpmn-icons.js"></script>
<script type="text/javascript" src="display/Polyline.js"></script>
<script type="text/javascript" src="display/displaymodel.js"></script>
<!-- endbuild -->
</head>
</html>

316
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/displaymodel.js

@ -0,0 +1,316 @@
/* 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 = 1;
var SEQUENCEFLOW_STROKE = 1.5;
var ASSOCIATION_STROKE = 2;
var TASK_STROKE = 1;
var TASK_HIGHLIGHT_STROKE = 2;
var CALL_ACTIVITY_STROKE = 2;
var ENDEVENT_STROKE = 3;
var COMPLETED_COLOR= "#2632aa";
var TEXT_COLOR= "#373e48";
var CURRENT_COLOR= "#017501";
var HOVER_COLOR= "#666666";
var ACTIVITY_STROKE_COLOR = "#bbbbbb";
var ACTIVITY_FILL_COLOR = "#f9f9f9";
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');
// 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();
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 += "<b>Name</b>: <i>" + element.name + "</i><br/><br/>";
}
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 += '<b>' + propName + '</b>:<br/>';
for (var j = 0; j < element.properties[i].value.length; j++) {
documentation += '<i>' + element.properties[i].value[j] + '</i><br/>';
}
}
else {
documentation += '<b>' + propName + '</b>: <i>' + element.properties[i].value + '</i><br/>';
}
}
}
}
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 _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":strokeColor});
});
}
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.APP_URL.getProcessInstanceModelJsonHistoryUrl(historyModelId);
} else {
modelUrl = FLOWABLE.APP_URL.getProcessInstanceModelJsonUrl(modelId);
}
} else if (modelType == 'design') {
if (historyModelId) {
modelUrl = FLOWABLE.APP_URL.getModelHistoryModelJsonUrl(modelId, historyModelId);
} else {
modelUrl = FLOWABLE.APP_URL.getModelModelJsonUrl(modelId);
}
} else if (modelType == 'process-definition') {
modelUrl = FLOWABLE.APP_URL.getProcessDefinitionModelJsonUrl(processDefinitionId);
}
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);
//} 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);
}
}
}
});
request.error(function(jqXHR, textStatus, errorThrown) {
alert("error");
});

2
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/jquery.qtip.min.css

File diff suppressed because one or more lines are too long

5
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/jquery.qtip.min.js

File diff suppressed because one or more lines are too long

37
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/package.json

@ -0,0 +1,37 @@
{
"name": "displaymodel",
"version": "1.0.0",
"dependencies": {},
"devDependencies": {
"grunt": "0.4.2",
"grunt-autoprefixer": "0.4.0",
"grunt-bower-install": "0.7.0",
"grunt-concurrent": "0.4.1",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-coffee": "0.7.0",
"grunt-contrib-compass": "0.6.0",
"grunt-contrib-concat": "0.3.0",
"grunt-contrib-connect": "0.5.0",
"grunt-contrib-copy": "0.4.1",
"grunt-contrib-cssmin": "0.7.0",
"grunt-contrib-htmlmin": "0.1.3",
"grunt-contrib-imagemin": "0.3.0",
"grunt-contrib-jshint": "0.7.1",
"grunt-contrib-uglify": "0.2.0",
"grunt-contrib-watch": "0.5.2",
"grunt-google-cdn": "0.2.0",
"grunt-newer": "0.5.4",
"grunt-ng-annotate": "0.5.0",
"grunt-rev": "0.1.0",
"grunt-svgmin": "0.2.0",
"grunt-usemin": "2.0.0",
"jshint-stylish": "0.1.3",
"load-grunt-tasks": "0.2.0",
"time-grunt": "0.2.1",
"grunt-text-replace": "0.3.11",
"grunt-contrib-rename": "0.0.3"
},
"engines": {
"node": ">=0.8.0"
}
}

1
io.sc.platform.flowable/src/main/resources/flowable-modeler/display/raphael.min.js

File diff suppressed because one or more lines are too long

19
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/flowable-header-custom.js

@ -0,0 +1,19 @@
/* 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.
*/
'use strict';
FLOWABLE.HEADER_CONFIG.showAppTitle = false;
FLOWABLE.HEADER_CONFIG.showHeaderMenu = false;
FLOWABLE.HEADER_CONFIG.showMainNavigation = false;
FLOWABLE.HEADER_CONFIG.showPageHeader = false;

50
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/flowable-toolbar-custom-actions.js

@ -0,0 +1,50 @@
/* 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.
*/
// Create custom functions for the FLOWABLE-editor
FLOWABLE.TOOLBAR.ACTIONS.closeEditor = function(services) {
if (services.editorManager && services.editorManager.getStencilData()) {
var stencilNameSpace = services.editorManager.getStencilData().namespace;
if (stencilNameSpace !== undefined && stencilNameSpace !== null && stencilNameSpace.indexOf('cmmn1.1') !== -1) {
services.$location.path("/casemodels");
return;
}
if (stencilNameSpace !== undefined && stencilNameSpace !== null && stencilNameSpace.indexOf('dmn1.2') !== -1) {
services.$location.path("/decision-services");
return;
}
}
services.$location.path("/processes");
};
FLOWABLE.TOOLBAR.ACTIONS.navigateToProcess = function(processId) {
var navigateEvent = {
type: FLOWABLE.eventBus.EVENT_TYPE_NAVIGATE_TO_PROCESS,
processId: processId
};
FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_NAVIGATE_TO_PROCESS, navigateEvent);
},
// Add custom buttons
FLOWABLE.TOOLBAR_CONFIG.secondaryItems.push(
{
"type" : "button",
"title" : "Close",
"cssClass" : "glyphicon glyphicon-remove",
"action" : "FLOWABLE.TOOLBAR.ACTIONS.closeEditor"
}
);

507
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-assignment-controller.js

@ -0,0 +1,507 @@
/* 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.
*/
/*
* Assignment
*/
'use strict';
angular.module('flowableModeler').controller('FlowableAssignmentCtrl', [ '$scope', '$modal', function($scope, $modal) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/assignment-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableAssignmentPopupCtrl',
[ '$rootScope', '$scope', '$translate', '$http', 'UserService', 'GroupService', function($rootScope, $scope, $translate, $http, UserService, GroupService) {
// Put json representing assignment on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.assignment !== undefined
&& $scope.property.value.assignment !== null) {
$scope.assignment = $scope.property.value.assignment;
if (typeof $scope.assignment.type === 'undefined') {
$scope.assignment.type = 'static';
}
} else {
$scope.assignment = {type:'idm'};
}
$scope.popup = {
assignmentObject: {
type:$scope.assignment.type,
idm: {
type:undefined,
assignee: undefined,
candidateUsers: [],
candidateGroups: []
},
static: {
assignee: undefined,
candidateUsers: [],
candidateGroups: []
}
}
};
$scope.assignmentOptions = [
{id: "initiator", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR')},
{id: "user", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER')},
{id: "users", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS')},
{id: "groups", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS')}
];
if ($scope.assignment.idm && $scope.assignment.idm.type) {
for (var i = 0; i < $scope.assignmentOptions.length; i++) {
if ($scope.assignmentOptions[i].id == $scope.assignment.idm.type) {
$scope.assignmentOption = $scope.assignmentOptions[i];
break;
}
}
}
// fill the IDM area
if (!$scope.assignmentOption) {
// Default, first time opening the popup
$scope.assignmentOption = $scope.assignmentOptions[0];
} else {
// Values already filled
if ($scope.assignment.idm) { //fill the IDM tab
if ($scope.assignment.idm.assignee) {
if ($scope.assignment.idm.assignee.id) {
$scope.popup.assignmentObject.idm.assignee = $scope.assignment.idm.assignee;
} else {
$scope.popup.assignmentObject.idm.assignee = {email: $scope.assignment.idm.assignee.email};
}
}
if ($scope.assignment.idm.candidateUsers && $scope.assignment.idm.candidateUsers.length > 0) {
for (var i = 0; i < $scope.assignment.idm.candidateUsers.length; i++) {
$scope.popup.assignmentObject.idm.candidateUsers.push($scope.assignment.idm.candidateUsers[i]);
}
}
if ($scope.assignment.idm.candidateGroups && $scope.assignment.idm.candidateGroups.length > 0) {
for (var i = 0; i < $scope.assignment.idm.candidateGroups.length; i++) {
$scope.popup.assignmentObject.idm.candidateGroups.push($scope.assignment.idm.candidateGroups[i]);
}
}
}
}
//fill the static area
if ($scope.assignment.assignee) {
$scope.popup.assignmentObject.static.assignee = $scope.assignment.assignee;
}
if ($scope.assignment.candidateUsers && $scope.assignment.candidateUsers.length > 0) {
for (var i = 0; i < $scope.assignment.candidateUsers.length; i++) {
$scope.popup.assignmentObject.static.candidateUsers.push($scope.assignment.candidateUsers[i]);
}
}
if ($scope.assignment.candidateGroups && $scope.assignment.candidateGroups.length > 0) {
for (var i = 0; i < $scope.assignment.candidateGroups.length; i++) {
$scope.popup.assignmentObject.static.candidateGroups.push($scope.assignment.candidateGroups[i]);
}
}
initStaticContextForEditing($scope);
$scope.$watch('popup.groupFilter', function () {
$scope.updateGroupFilter();
});
$scope.$watch('popup.filter', function() {
$scope.updateFilter();
});
$scope.updateFilter = function() {
if ($scope.popup.oldFilter == undefined || $scope.popup.oldFilter != $scope.popup.filter) {
if (!$scope.popup.filter) {
$scope.popup.oldFilter = '';
} else {
$scope.popup.oldFilter = $scope.popup.filter;
}
if ($scope.popup.filter !== null && $scope.popup.filter !== undefined) {
UserService.getFilteredUsers($scope.popup.filter).then(function (result) {
var filteredUsers = [];
for (var i=0; i<result.data.length; i++) {
var filteredUser = result.data[i];
var foundCandidateUser = false;
if ($scope.popup.assignmentObject.idm.candidateUsers !== null && $scope.popup.assignmentObject.idm.candidateUsers !== undefined) {
for (var j=0; j<$scope.popup.assignmentObject.idm.candidateUsers.length; j++) {
var candidateUser = $scope.popup.assignmentObject.idm.candidateUsers[j];
if (candidateUser.id === filteredUser.id) {
foundCandidateUser = true;
break;
}
}
}
if (!foundCandidateUser) {
filteredUsers.push(filteredUser);
}
}
$scope.popup.userResults = filteredUsers;
$scope.resetSelection();
});
}
}
};
$scope.updateGroupFilter = function() {
if ($scope.popup.oldGroupFilter == undefined || $scope.popup.oldGroupFilter != $scope.popup.groupFilter) {
if (!$scope.popup.groupFilter) {
$scope.popup.oldGroupFilter = '';
} else {
$scope.popup.oldGroupFilter = $scope.popup.groupFilter;
}
GroupService.getFilteredGroups($scope.popup.groupFilter).then(function(result) {
$scope.popup.groupResults = result.data;
$scope.resetGroupSelection();
});
}
};
$scope.confirmUser = function(user) {
if (!user) {
// Selection is done with keyboard, use selection index
var users = $scope.popup.userResults;
if ($scope.popup.selectedIndex >= 0 && $scope.popup.selectedIndex < users.length) {
user = users[$scope.popup.selectedIndex];
}
}
if (user) {
if ("user" == $scope.assignmentOption.id) {
$scope.popup.assignmentObject.idm.assignee = user;
} else if ("users" == $scope.assignmentOption.id) {
// Only add if not yet part of candidate users
var found = false;
if ($scope.popup.assignmentObject.idm.candidateUsers) {
for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {
if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
found = true;
break;
}
}
}
if (!found) {
$scope.addCandidateUser(user);
}
}
}
};
$scope.confirmEmail = function() {
if ("user" == $scope.assignmentOption.id) {
$scope.popup.assignmentObject.idm.assignee = {email: $scope.popup.email};
} else if ("users" == $scope.assignmentOption.id) {
// Only add if not yet part of candidate users
var found = false;
if ($scope.popup.assignmentObject.idm.candidateUsers) {
for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {
if ($scope.popup.assignmentObject.idm.candidateUsers[i].id) {
if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
found = true;
break;
}
} else if ($scope.popup.assignmentObject.idm.candidateUsers[i].email) {
if ($scope.popup.assignmentObject.idm.candidateUsers[i].email === $scope.popup.email) {
found = true;
break;
}
}
}
}
if (!found) {
$scope.addCandidateUser({email: $scope.popup.email});
}
}
};
$scope.confirmGroup = function(group) {
if (!group) {
// Selection is done with keyboard, use selection index
var groups = $scope.popup.groupResults;
if ($scope.popup.selectedGroupIndex >= 0 && $scope.popup.selectedGroupIndex < groups.length) {
group = groups[$scope.popup.selectedGroupIndex];
}
}
if (group) {
// Only add if not yet part of candidate groups
var found = false;
if ($scope.popup.assignmentObject.idm.candidateGroups) {
for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateGroups.length; i++) {
if ($scope.popup.assignmentObject.idm.candidateGroups[i].id === group.id) {
found = true;
break;
}
}
}
if (!found) {
$scope.addCandidateGroup(group);
}
}
};
$scope.addCandidateUser = function(user) {
$scope.popup.assignmentObject.idm.candidateUsers.push(user);
};
$scope.removeCandidateUser = function(user) {
var users = $scope.popup.assignmentObject.idm.candidateUsers;
var indexToRemove = -1;
for (var i = 0; i < users.length; i++) {
if (user.id) {
if (user.id === users[i].id) {
indexToRemove = i;
break;
}
} else {
if (user.email === users[i].email) {
indexToRemove = i;
break;
}
}
}
if (indexToRemove >= 0) {
users.splice(indexToRemove, 1);
}
};
$scope.addCandidateGroup = function(group) {
$scope.popup.assignmentObject.idm.candidateGroups.push(group);
};
$scope.removeCandidateGroup = function(group) {
var groups = $scope.popup.assignmentObject.idm.candidateGroups;
var indexToRemove = -1;
for (var i = 0; i < groups.length; i++) {
if (group.id == groups[i].id) {
indexToRemove = i;
break;
}
}
if (indexToRemove >= 0) {
groups.splice(indexToRemove, 1);
}
};
$scope.resetSelection = function() {
if ($scope.popup.userResults && $scope.popup.userResults.length > 0) {
$scope.popup.selectedIndex = 0;
} else {
$scope.popup.selectedIndex = -1;
}
};
$scope.nextUser = function() {
var users = $scope.popup.userResults;
if (users && users.length > 0 && $scope.popup.selectedIndex < users.length -1) {
$scope.popup.selectedIndex += 1;
}
};
$scope.previousUser = function() {
var users = $scope.popup.userResults;
if (users && users.length > 0 && $scope.popup.selectedIndex > 0) {
$scope.popup.selectedIndex -= 1;
}
};
$scope.resetGroupSelection = function() {
if ($scope.popup.groupResults && $scope.popup.groupResults.length > 0) {
$scope.popup.selectedGroupIndex = 0;
} else {
$scope.popup.selectedGroupIndex = -1;
}
};
$scope.nextGroup = function() {
var groups = $scope.popup.groupResults;
if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex < groups.length -1) {
$scope.popup.selectedGroupIndex += 1;
}
};
$scope.previousGroup = function() {
var groups = $scope.popup.groupResults;
if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex > 0) {
$scope.popup.selectedGroupIndex -= 1;
}
};
$scope.removeAssignee = function() {
$scope.popup.assignmentObject.idm.assignee = undefined;
};
// Click handler for + button after enum value
$scope.addCandidateUserValue = function(index) {
$scope.popup.assignmentObject.static.candidateUsers.splice(index + 1, 0, {value: ''});
};
// Click handler for - button after enum value
$scope.removeCandidateUserValue = function(index) {
$scope.popup.assignmentObject.static.candidateUsers.splice(index, 1);
};
// Click handler for + button after enum value
$scope.addCandidateGroupValue = function(index) {
$scope.popup.assignmentObject.static.candidateGroups.splice(index + 1, 0, {value: ''});
};
// Click handler for - button after enum value
$scope.removeCandidateGroupValue = function(index) {
$scope.popup.assignmentObject.static.candidateGroups.splice(index, 1);
};
$scope.setSearchType = function() {
$scope.popup.assignmentObject.assignmentSourceType = 'search';
};
$scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);
$scope.save = function () {
handleAssignmentInput($scope.popup.assignmentObject.static);
$scope.assignment.type = $scope.popup.assignmentObject.type;
if ('idm' === $scope.popup.assignmentObject.type) { // IDM
$scope.popup.assignmentObject.static = undefined;
//Construct an IDM object to be saved to the process model.
var idm = {type: $scope.assignmentOption.id};
if ('user' == idm.type) {
if ($scope.popup.assignmentObject.idm.assignee) {
idm.assignee = $scope.popup.assignmentObject.idm.assignee;
}
} else if ('users' == idm.type) {
if ($scope.popup.assignmentObject.idm.candidateUsers && $scope.popup.assignmentObject.idm.candidateUsers.length > 0) {
idm.candidateUsers = $scope.popup.assignmentObject.idm.candidateUsers;
}
} else if ('groups' == idm.type) {
if ($scope.popup.assignmentObject.idm.candidateGroups && $scope.popup.assignmentObject.idm.candidateGroups.length > 0) {
idm.candidateGroups = $scope.popup.assignmentObject.idm.candidateGroups;
}
}
$scope.assignment.idm = idm;
$scope.assignment.assignee = undefined;
$scope.assignment.candidateUsers = undefined;
$scope.assignment.candidateGroups = undefined;
}
if ('static' === $scope.popup.assignmentObject.type) { // IDM
$scope.popup.assignmentObject.idm = undefined;
$scope.assignment.idm = undefined;
$scope.assignment.assignee = $scope.popup.assignmentObject.static.assignee;
$scope.assignment.candidateUsers = $scope.popup.assignmentObject.static.candidateUsers;
$scope.assignment.candidateGroups = $scope.popup.assignmentObject.static.candidateGroups;
}
$scope.property.value = {};
$scope.property.value.assignment = $scope.assignment;
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Close button handler
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
var handleAssignmentInput = function ($assignment) {
function isEmptyString(value) {
return (value === undefined || value === null || value.trim().length === 0);
}
if (isEmptyString($assignment.assignee)){
$assignment.assignee = undefined;
}
var toRemoveIndexes;
var removedItems=0;
var i = 0;
if ($assignment.candidateUsers) {
toRemoveIndexes = [];
for (i = 0; i < $assignment.candidateUsers.length; i++) {
if (isEmptyString($assignment.candidateUsers[i].value)) {
toRemoveIndexes[toRemoveIndexes.length] = i;
}
}
if (toRemoveIndexes.length == $assignment.candidateUsers.length) {
$assignment.candidateUsers = undefined;
} else {
removedItems=0;
for (i = 0; i < toRemoveIndexes.length; i++) {
$assignment.candidateUsers.splice(toRemoveIndexes[i]-removedItems, 1);
removedItems++;
}
}
}
if ($assignment.candidateGroups) {
toRemoveIndexes = [];
for (i = 0; i < $assignment.candidateGroups.length; i++) {
if (isEmptyString($assignment.candidateGroups[i].value)) {
toRemoveIndexes[toRemoveIndexes.length] = i;
}
}
if (toRemoveIndexes.length == $assignment.candidateGroups.length) {
$assignment.candidateGroups = undefined;
} else {
removedItems=0;
for (i = 0; i < toRemoveIndexes.length; i++) {
$assignment.candidateGroups.splice(toRemoveIndexes[i]-removedItems, 1);
removedItems++;
}
}
}
};
function initStaticContextForEditing($scope) {
if (!$scope.popup.assignmentObject.static.candidateUsers || $scope.popup.assignmentObject.static.candidateUsers.length==0) {
$scope.popup.assignmentObject.static.candidateUsers = [{value: ''}];
}
if (!$scope.popup.assignmentObject.static.candidateGroups || $scope.popup.assignmentObject.static.candidateGroups.length==0) {
$scope.popup.assignmentObject.static.candidateGroups = [{value: ''}];
}
}
}]);

28
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-calledelementtype-controller.js

@ -0,0 +1,28 @@
/* 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.
*/
/*
* Call activity calledElement type property
*/
angular.module('flowableModeler').controller('FlowableCalledElementTypeCtrl', [ '$scope', function($scope) {
if ($scope.property.value == undefined && $scope.property.value == null)
{
$scope.property.value = 'key';
}
$scope.calledElementTypeChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

86
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-case-reference-controller.js

@ -0,0 +1,86 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableCaseReferenceCtrl',
[ '$scope', '$modal', '$http', function($scope, $modal, $http) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/case-reference-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableCaseReferencePopupCtrl', [ '$scope', '$http', 'editorManager', '$location', function($scope, $http, editorManager, $location) {
$scope.state = {'loadingCases' : true, 'error' : false};
// Close button handler
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
// Selecting/deselecting a case
$scope.selectCase = function(caseModel, $event) {
$event.stopPropagation();
if ($scope.selectedCase && $scope.selectedCase.id && caseModel.id == $scope.selectedCase.id) {
// un-select the current selection
$scope.selectedCase = null;
} else {
$scope.selectedCase = caseModel;
}
};
$scope.open = function() {
if ($scope.selectedCase) {
$location.path("/editor/" + $scope.selectedCase.id);
}
};
// Saving the selected value
$scope.save = function() {
if ($scope.selectedCase) {
$scope.property.value = {'id' : $scope.selectedCase.id, 'name' : $scope.selectedCase.name, 'key': $scope.selectedCase.key};
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.loadCases = function() {
var modelMetaData = editorManager.getBaseModelData();
$http.get(FLOWABLE.APP_URL.getCaseModelsUrl('?excludeId=' + modelMetaData.modelId))
.success(
function(response) {
$scope.state.loadingCases = false;
$scope.state.caseError = false;
$scope.caseModels = response.data;
})
.error(
function(data, status, headers, config) {
$scope.state.loadingCases = false;
$scope.state.caseError = true;
});
};
if ($scope.property && $scope.property.value && $scope.property.value.id) {
$scope.selectedCase = $scope.property.value;
}
$scope.loadCases();
}]);

59
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-condition-expression-controller.js

@ -0,0 +1,59 @@
/* 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.
*/
/*
* Condition expression
*/
angular.module('flowableModeler').controller('FlowableConditionExpressionCtrl', [ '$scope', '$modal', function($scope, $modal) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/condition-expression-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableConditionExpressionPopupCtrl',
[ '$rootScope', '$scope', '$translate', 'FormBuilderService', function($rootScope, $scope, $translate, FormBuilderService) {
// Put json representing assignment on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.expression !== undefined
&& $scope.property.value.expression !== null) {
$scope.expression = $scope.property.value.expression;
} else if ($scope.property.value !== undefined && $scope.property.value !== null) {
$scope.expression = {type: 'static', staticValue: $scope.property.value};
} else {
$scope.expression = {};
}
$scope.save = function() {
$scope.property.value = {expression: $scope.expression};
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Close button handler
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

12
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-custom-controllers.js

@ -0,0 +1,12 @@
/* 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.
*/

330
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-data-properties-controller.js

@ -0,0 +1,330 @@
/* 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.
*/
/*
* Data Properties
*/
angular.module('flowableModeler').controller('FlowableDataPropertiesCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/data-properties-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableDataPropertiesPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing data properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.items !== undefined
&& $scope.property.value.items !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.dataProperties = angular.copy($scope.property.value.items);
for (var i = 0; i < $scope.dataProperties.length; i++) {
var dataProperty = $scope.dataProperties[i];
if (dataProperty.enumValues && dataProperty.enumValues.length > 0) {
for (var j = 0; j < dataProperty.enumValues.length; j++) {
var enumValue = dataProperty.enumValues[j];
if (!enumValue.id && !enumValue.name && enumValue.value) {
enumValue.id = enumValue.value;
enumValue.name = enumValue.value;
}
}
}
}
} else {
$scope.dataProperties = [];
}
$scope.enumValues = [];
$scope.translationsRetrieved = false;
$scope.labels = {};
var idPromise = $translate('PROPERTY.DATAPROPERTIES.ID');
var namePromise = $translate('PROPERTY.DATAPROPERTIES.NAME');
var typePromise = $translate('PROPERTY.DATAPROPERTIES.TYPE');
var valuePromise = $translate('PROPERTY.DATAPROPERTIES.VALUE');
$q.all([idPromise, namePromise, typePromise, valuePromise]).then(function (results) {
$scope.labels.idLabel = results[0];
$scope.labels.nameLabel = results[1];
$scope.labels.typeLabel = results[2];
$scope.labels.valueLabel = results[3];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.dataProperties,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'dataproperty_id', displayName: $scope.labels.idLabel},
{field: 'dataproperty_name', displayName: $scope.labels.nameLabel},
{field: 'dataproperty_type', displayName: $scope.labels.typeLabel},
{field: 'dataproperty_value', displayName: $scope.labels.valueLabel}]
};
$scope.enumGridOptions = {
data: $scope.enumValues,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },
{ field: 'name', displayName: $scope.labels.nameLabel}]
}
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedProperty = row.entity;
$scope.selectedEnumValue = undefined;
if ($scope.selectedProperty && $scope.selectedProperty.enumValues) {
$scope.enumValues.length = 0;
for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
$scope.enumValues.push($scope.selectedProperty.enumValues[i]);
}
}
});
};
$scope.enumGridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.enumGridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedEnumValue = row.entity;
});
};
});
// Handler for when the value of the type dropdown changes
$scope.propertyTypeChanged = function () {
// Check date. If date, show date pattern
if ($scope.selectedProperty.type === 'date') {
$scope.selectedProperty.datePattern = 'MM-dd-yyyy hh:mm';
} else {
delete $scope.selectedProperty.datePattern;
}
// Check enum. If enum, show list of options
if ($scope.selectedProperty.type === 'enum') {
$scope.selectedProperty.enumValues = [ {id: 'value1', name: 'Value 1'}, {id: 'value2', name: 'Value 2'}];
$scope.enumValues.length = 0;
for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
$scope.enumValues.push($scope.selectedProperty.enumValues[i]);
}
} else {
delete $scope.selectedProperty.enumValues;
$scope.enumValues.length = 0;
}
};
// Click handler for add button
var propertyIndex = 1;
$scope.addNewProperty = function () {
var newProperty = {
dataproperty_id: 'new_data_object_' + propertyIndex++,
dataproperty_name: '',
dataproperty_type: 'string',
readable: true,
writable: true
};
$scope.dataProperties.push(newProperty);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newProperty);
});
};
// Click handler for remove button
$scope.removeProperty = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.dataProperties.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.dataProperties.splice(index, 1);
if ($scope.dataProperties.length == 0) {
$scope.selectedProperty = undefined;
}
$timeout(function() {
if ($scope.dataProperties.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.dataProperties[0]);
}
});
}
};
// Click handler for up button
$scope.movePropertyUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.dataProperties.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.dataProperties[index];
$scope.dataProperties.splice(index, 1);
$timeout(function(){
$scope.dataProperties.splice(index + -1, 0, temp);
$timeout(function() {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.movePropertyDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.dataProperties.indexOf(selectedItems[0]);
if (index != $scope.dataProperties.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.dataProperties[index];
$scope.dataProperties.splice(index, 1);
$timeout(function(){
$scope.dataProperties.splice(index + 1, 0, temp);
$timeout(function() {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
$scope.addNewEnumValue = function() {
if ($scope.selectedProperty) {
var newEnumValue = { id : '', name : ''};
$scope.selectedProperty.enumValues.push(newEnumValue);
$scope.enumValues.push(newEnumValue);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(newEnumValue);
});
}
};
// Click handler for remove button
$scope.removeEnumValue = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
$scope.enumGridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
if ($scope.enumValues.length == 0) {
$scope.selectedEnumValue = undefined;
}
$timeout(function () {
if ($scope.enumValues.length > 0) {
$scope.enumGridApi.selection.toggleRowSelection($scope.enumValues[0]);
}
});
}
};
// Click handler for up button
$scope.moveEnumValueUp = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.enumValues[index];
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
$timeout(function () {
$scope.enumValues.splice(index + -1, 0, temp);
$scope.selectedProperty.enumValues.splice(index + -1, 0, temp);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveEnumValueDown = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
if (index != $scope.enumValues.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.enumValues[index];
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
$timeout(function () {
$scope.enumValues.splice(index + 1, 0, temp);
$scope.selectedProperty.enumValues.splice(index + 1, 0, temp);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.dataProperties.length > 0) {
$scope.property.value = {};
$scope.property.value.items = $scope.dataProperties;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
// Close button handler
$scope.close = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
}])
;

288
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-decisionservice-reference-controller.js

@ -0,0 +1,288 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableDecisionServiceReferenceCtrl',
[ '$scope', '$modal', '$http', function($scope, $modal, $http) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/decisionservice-reference-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableDecisionServiceReferencePopupCtrl', ['$rootScope', '$scope', '$http', '$location', 'editorManager',
function($rootScope, $scope, $http, $location, editorManager) {
$scope.state = {
'loadingDecisionServices': true,
'decisionServiceError': false
};
$scope.popup = {
'state': 'decisionServiceReference'
};
$scope.foldersBreadCrumbs = [];
// Make click outside dialog also call close.
$scope.$parent.$on('modal.hide.before', function() {
$scope.close();
$scope.$parent.$apply();
});
// Close button handler
$scope.close = function() {
$scope.property.newVariablesMapping = undefined;
$scope.property.mode = 'read';
$scope.$hide();
};
// Selecting/deselecting a decision service
$scope.selectDecisionService = function(decisionService, $event) {
$event.stopPropagation();
if ($scope.selectedDecisionService && $scope.selectedDecisionService.id && decisionService.id == $scope.selectedDecisionService.id) {
// un-select the current selection
$scope.selectedDecisionService = null;
} else {
$scope.selectedDecisionService = decisionService;
}
};
$scope.isSelected = function () {
if ($scope.selectedDecisionService && $scope.selectedDecisionService.id) {
return true;
}
return false;
};
// Saving the selected value
$scope.save = function() {
if ($scope.selectedDecisionService) {
$scope.property.value = {
'id': $scope.selectedDecisionService.id,
'name': $scope.selectedDecisionService.name,
'key': $scope.selectedDecisionService.key
};
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Open the selected value
$scope.open = function() {
if ($scope.selectedDecisionService) {
$scope.property.value = {
'id': $scope.selectedDecisionService.id,
'name': $scope.selectedDecisionService.name,
'key': $scope.selectedDecisionService.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated
};
// Update
$http({
method: 'POST',
data: params,
ignoreErrors: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)
})
.success(function(data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('decision-service-editor/' + $scope.selectedDecisionService.id);
})
.error(function(data, status, headers, config) {
});
$scope.close();
}
};
$scope.newDecisionService = function() {
$scope.property.value.variablesmapping = [];
$scope.popup.state = 'newDecisionService';
var modelMetaData = editorManager.getBaseModelData();
$scope.model = {
loading: false,
decisionService: {
name: '',
key: '',
description: '',
modelType: 6
},
defaultStencilSet: undefined,
decisionTableStencilSets: []
};
};
$scope.createDecisionService = function() {
if (!$scope.model.decisionService.name || $scope.model.decisionService.name.length == 0 ||
!$scope.model.decisionService.key || $scope.model.decisionService.key.length == 0) {
return;
}
var stencilSetId = $scope.model.decisionService.stencilSet;
$scope.model.loading = true;
$http({
method: 'POST',
url: FLOWABLE.APP_URL.getModelsUrl(),
data: $scope.model.decisionService
}).
success(function(data, status, headers, config) {
var newDecisionTableId = data.id;
$scope.property.value = {
'id': newDecisionTableId,
'name': data.name,
'key': data.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated,
stencilSet: stencilSetId
};
// Update
$http({
method: 'POST',
data: params,
ignoreErrors: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)
})
.success(function(data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$scope.model.loading = false;
$scope.$hide();
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('decision-service-editor/' + newDecisionTableId);
})
.error(function(data, status, headers, config) {
$scope.model.loading = false;
$scope.$hide();
});
}).
error(function(data, status, headers, config) {
$scope.model.loading = false;
$scope.model.errorMessage = data.message;
});
};
$scope.cancel = function() {
$scope.close();
};
$scope.resetCurrent = function () {
for (var i = 0, found = false; i < $scope.decisionServices.length && found === false; i++) {
var decision = $scope.decisionServices[i];
if (decision.id === $scope.property.value.id) {
$scope.selectedDecisionService = decision;
found = true;
}
}
};
$scope.loadDecisionServices = function() {
var modelMetaData = editorManager.getBaseModelData();
$http.get(FLOWABLE.APP_URL.getDecisionServiceModelsUrl())
.success(
function(response) {
$scope.state.loadingDecisionServices = false;
$scope.state.decisionServiceError = false;
$scope.decisionServices = response.data;
$scope.resetCurrent();
})
.error(
function(data, status, headers, config) {
$scope.state.loadingDecisionServices = false;
$scope.state.decisionServiceError = true;
});
};
if ($scope.property && $scope.property.value && $scope.property.value.id) {
$scope.selectedDecisionService = $scope.property.value;
$scope.storedId = $scope.property.value.id;
}
$scope.loadDecisionServices();
}
]);

288
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-decisiontable-reference-controller.js

@ -0,0 +1,288 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableDecisionTableReferenceCtrl',
[ '$scope', '$modal', '$http', function($scope, $modal, $http) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/decisiontable-reference-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableDecisionTableReferencePopupCtrl', ['$rootScope', '$scope', '$http', '$location', 'editorManager',
function($rootScope, $scope, $http, $location, editorManager) {
$scope.state = {
'loadingDecisionTables': true,
'decisionTableError': false
};
$scope.popup = {
'state': 'decisionTableReference'
};
$scope.foldersBreadCrumbs = [];
// Make click outside dialog also call close.
$scope.$parent.$on('modal.hide.before', function() {
$scope.close();
$scope.$parent.$apply();
});
// Close button handler
$scope.close = function() {
$scope.property.newVariablesMapping = undefined;
$scope.property.mode = 'read';
$scope.$hide();
};
// Selecting/deselecting a decision table
$scope.selectDecisionTable = function(decisionTable, $event) {
$event.stopPropagation();
if ($scope.selectedDecisionTable && $scope.selectedDecisionTable.id && decisionTable.id == $scope.selectedDecisionTable.id) {
// un-select the current selection
$scope.selectedDecisionTable = null;
} else {
$scope.selectedDecisionTable = decisionTable;
}
};
$scope.isSelected = function () {
if ($scope.selectedDecisionTable && $scope.selectedDecisionTable.id) {
return true;
}
return false;
};
// Saving the selected value
$scope.save = function() {
if ($scope.selectedDecisionTable) {
$scope.property.value = {
'id': $scope.selectedDecisionTable.id,
'name': $scope.selectedDecisionTable.name,
'key': $scope.selectedDecisionTable.key
};
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Open the selected value
$scope.open = function() {
if ($scope.selectedDecisionTable) {
$scope.property.value = {
'id': $scope.selectedDecisionTable.id,
'name': $scope.selectedDecisionTable.name,
'key': $scope.selectedDecisionTable.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated
};
// Update
$http({
method: 'POST',
data: params,
ignoreErrors: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)
})
.success(function(data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('decision-table-editor/' + $scope.selectedDecisionTable.id);
})
.error(function(data, status, headers, config) {
});
$scope.close();
}
};
$scope.newDecisionTable = function() {
$scope.property.value.variablesmapping = [];
$scope.popup.state = 'newDecisionTable';
var modelMetaData = editorManager.getBaseModelData();
$scope.model = {
loading: false,
decisionTable: {
name: '',
key: '',
description: '',
modelType: 4
},
defaultStencilSet: undefined,
decisionTableStencilSets: []
};
};
$scope.createDecisionTable = function() {
if (!$scope.model.decisionTable.name || $scope.model.decisionTable.name.length == 0 ||
!$scope.model.decisionTable.key || $scope.model.decisionTable.key.length == 0) {
return;
}
var stencilSetId = $scope.model.decisionTable.stencilSet;
$scope.model.loading = true;
$http({
method: 'POST',
url: FLOWABLE.APP_URL.getModelsUrl(),
data: $scope.model.decisionTable
}).
success(function(data, status, headers, config) {
var newDecisionTableId = data.id;
$scope.property.value = {
'id': newDecisionTableId,
'name': data.name,
'key': data.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated,
stencilSet: stencilSetId
};
// Update
$http({
method: 'POST',
data: params,
ignoreErrors: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)
})
.success(function(data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$scope.model.loading = false;
$scope.$hide();
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('decision-table-editor/' + newDecisionTableId);
})
.error(function(data, status, headers, config) {
$scope.model.loading = false;
$scope.$hide();
});
}).
error(function(data, status, headers, config) {
$scope.model.loading = false;
$scope.model.errorMessage = data.message;
});
};
$scope.cancel = function() {
$scope.close();
};
$scope.resetCurrent = function () {
for (var i = 0, found = false; i < $scope.decisionTables.length && found === false; i++) {
var table = $scope.decisionTables[i];
if (table.id === $scope.property.value.id) {
$scope.selectedDecisionTable = table;
found = true;
}
}
};
$scope.loadDecisionTables = function() {
var modelMetaData = editorManager.getBaseModelData();
$http.get(FLOWABLE.APP_URL.getDecisionTableModelsUrl())
.success(
function(response) {
$scope.state.loadingDecisionTables = false;
$scope.state.decisionTableError = false;
$scope.decisionTables = response.data;
$scope.resetCurrent();
})
.error(
function(data, status, headers, config) {
$scope.state.loadingDecisionTables = false;
$scope.state.decisionTableError = true;
});
};
if ($scope.property && $scope.property.value && $scope.property.value.id) {
$scope.selectedDecisionTable = $scope.property.value;
$scope.storedId = $scope.property.value.id;
}
$scope.loadDecisionTables();
}
]);

118
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-default-controllers.js

@ -0,0 +1,118 @@
/* 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.
*/
/*
* String controller
*/
angular.module('flowableModeler').controller('FlowableStringPropertyCtrl', [ '$scope', function ($scope) {
$scope.shapeId = $scope.selectedShape.id;
$scope.valueFlushed = false;
/** Handler called when input field is blurred */
$scope.inputBlurred = function() {
$scope.valueFlushed = true;
if ($scope.property.value) {
$scope.property.value = $scope.property.value.replace(/(<([^>]+)>)/ig,"");
}
$scope.updatePropertyInModel($scope.property);
};
$scope.enterPressed = function(keyEvent) {
// if enter is pressed
if (keyEvent && keyEvent.which === 13) {
keyEvent.preventDefault();
$scope.inputBlurred(); // we want to do the same as if the user would blur the input field
}
// else; do nothing
};
$scope.$on('$destroy', function controllerDestroyed() {
if(!$scope.valueFlushed) {
if ($scope.property.value) {
$scope.property.value = $scope.property.value.replace(/(<([^>]+)>)/ig,"");
}
$scope.updatePropertyInModel($scope.property, $scope.shapeId);
}
});
}]);
/*
* Boolean controller
*/
angular.module('flowableModeler').controller('FlowableBooleanPropertyCtrl', ['$scope', function ($scope) {
$scope.changeValue = function() {
if ($scope.property.key === 'oryx-defaultflow' && $scope.property.value) {
var selectedShape = $scope.selectedShape;
if (selectedShape) {
var incomingNodes = selectedShape.getIncomingShapes();
if (incomingNodes && incomingNodes.length > 0) {
// get first node, since there can be only one for a sequence flow
var rootNode = incomingNodes[0];
var flows = rootNode.getOutgoingShapes();
if (flows && flows.length > 1) {
// in case there are more flows, check if another flow is already defined as default
for (var i = 0; i < flows.length; i++) {
if (flows[i].resourceId != selectedShape.resourceId) {
var defaultFlowProp = flows[i].properties.get('oryx-defaultflow');
if (defaultFlowProp) {
flows[i].setProperty('oryx-defaultflow', false, true);
}
}
}
}
}
}
}
$scope.updatePropertyInModel($scope.property);
};
}]);
/*
* Text controller
*/
angular.module('flowableModeler').controller('FlowableTextPropertyCtrl', [ '$scope', '$modal', '$timeout', function($scope, $modal, $timeout) {
var opts = {
template: 'editor-app/configuration/properties/text-popup.html?version=' + Date.now(),
scope: $scope,
prefixEvent: 'textModalEvent'
};
$scope.$on('textModalEvent.hide.before', function() {
$timeout(function() {
$scope.property.mode = 'read';
}, 0);
});
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableTextPropertyPopupCtrl', ['$scope', function($scope) {
$scope.save = function() {
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

126
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-duedate-controller.js

@ -0,0 +1,126 @@
/* 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.
*/
/*
* Due date
*/
'use strict';
angular.module('flowableModeler').controller('BpmnEditorDueDateCtrl', [ '$scope', '$modal', function($scope, $modal) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/duedate-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('BpmnEditorDueDatePopupCtrl',
[ '$rootScope', '$scope', '$translate', function($rootScope, $scope, $translate) {
// Put json representing assignment on scope
if ($scope.property.value !== undefined && $scope.property.value !== null) {
if ($scope.property.value.duedate !== undefined && $scope.property.value.duedate !== null) {
$scope.popup = {'duedate': $scope.property.value.duedate};
} else if ($scope.property.value.duedateExpression !== undefined && $scope.property.value.duedateExpression !== null) {
$scope.popup = {'duedateExpression': $scope.property.value.duedateExpression};
} else {
$scope.popup = {'duedateExpression': $scope.property.value};
}
} else {
$scope.popup = {};
}
$scope.taskDueDateOptions = [
{id: "none", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.NO-DUEDATE')},
{id: "expression", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.EXPRESSION')},
{id: "static", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.STATIC')},
{id: "field", title: $translate.instant('PROPERTY.DUEDATE.TASK-DUE-DATE-OPTIONS.FIELD')}
];
if (!$scope.popup.duedate && !$scope.popup.duedateExpression) {
// Default, first time opening the popup
$scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[0].id;
} else if (!$scope.popup.duedate) {
$scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[1].id;
} else {
if ($scope.popup.duedate.fixed) {
$scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[2].id;
} else if ($scope.popup.duedate.field) {
$scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[3].id;
} else {
$scope.popup.selectedDueDateOption = $scope.taskDueDateOptions[0].id;
}
}
$scope.dueDateOptionChanged = function() {
if ($scope.popup.selectedDueDateOption === 'expression') {
$scope.popup.duedate = undefined;
} else if ($scope.popup.selectedDueDateOption === 'none') {
$scope.popup.duedate = undefined;
$scope.popup.duedateExpression = undefined;
} else if ($scope.popup.selectedDueDateOption === 'static') {
$scope.popup.duedate = {'fixed': {}};
$scope.popup.duedateExpression = undefined;
} else if ($scope.popup.selectedDueDateOption === 'field') {
$scope.popup.duedate = {'field': {}};
$scope.popup.duedateExpression = undefined;
}
};
$scope.setAddCalculationType = function() {
$scope.popup.duedate.field.taskDueDateCalculationType = 'add';
};
$scope.setSubtractCalculationType = function() {
$scope.popup.duedate.field.taskDueDateCalculationType = 'subtract';
};
$scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);
$scope.save = function () {
$scope.property.value = {};
if ($scope.popup.duedate) {
$scope.property.value.duedate = $scope.popup.duedate;
} else if ($scope.popup.duedateExpression) {
$scope.property.value.duedateExpression = $scope.popup.duedateExpression;
} else {
$scope.property.value = '';
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Close button handler
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

145
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-escalation-definitions-controller.js

@ -0,0 +1,145 @@
/* 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.
*/
/*
* Escalation definitions
*/
angular.module('flowableModeler').controller('FlowableEscalationDefinitionsCtrl', ['$scope', '$modal', function ($scope, $modal) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/escalation-definitions-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259
// Will be fixed in a newer version of Angular UI
angular.module('flowableModeler').controller('FlowableEscalationDefinitionsPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing signal definitions on scope
if ($scope.property.value !== undefined && $scope.property.value !== null && $scope.property.value.length > 0) {
if ($scope.property.value.constructor == String) {
$scope.escalationDefinitions = JSON.parse($scope.property.value);
}
else {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.escalationDefinitions = angular.copy($scope.property.value);
}
} else {
$scope.escalationDefinitions = [];
}
// Array to contain selected signal definitions (yes - we only can select one, but ng-grid isn't smart enough)
$scope.selectedEscalationDefinition = undefined;
$scope.translationsRetrieved = false;
$scope.labels = {};
var idPromise = $translate('PROPERTY.ESCALATIONDEFINITIONS.ID');
var namePromise = $translate('PROPERTY.ESCALATIONDEFINITIONS.NAME');
$q.all([idPromise, namePromise]).then(function (results) {
$scope.labels.idLabel = results[0];
$scope.labels.nameLabel = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.escalationDefinitions,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'id', displayName: $scope.labels.idLabel},
{field: 'name', displayName: $scope.labels.nameLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedEscalationDefinition = row.entity;
});
};
});
// Click handler for add button
$scope.addNewEscalationDefinition = function () {
var newEscalationDefinition = {id: '', name: ''};
$scope.escalationDefinitions.push(newEscalationDefinition);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newEscalationDefinition);
});
};
// Click handler for remove button
$scope.removeEscalationDefinition = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.escalationDefinitions.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.escalationDefinitions.splice(index, 1);
if ($scope.escalationDefinitions.length == 0) {
$scope.selectedEscalationDefinition = undefined;
}
$timeout(function () {
if ($scope.escalationDefinitions.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.escalationDefinitions[0]);
}
});
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.escalationDefinitions.length > 0) {
$scope.property.value = $scope.escalationDefinitions;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

42
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-escalation-scope-controller.js

@ -0,0 +1,42 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableEscalationRefCtrl', [ '$scope', function($scope) {
// Find the parent shape on which the signal definitions are defined
var escalationDefinitionsProperty = undefined;
var parent = $scope.selectedShape;
while (parent !== null && parent !== undefined && escalationDefinitionsProperty === undefined) {
if (parent.properties && parent.properties.get('oryx-escalationdefinitions')) {
escalationDefinitionsProperty = parent.properties.get('oryx-escalationdefinitions');
} else {
parent = parent.parent;
}
}
try {
escalationDefinitionsProperty = JSON.parse(escalationDefinitionsProperty);
if (typeof escalationDefinitionsProperty == 'string') {
escalationDefinitionsProperty = JSON.parse(escalationDefinitionsProperty);
}
} catch (err) {
// Do nothing here, just to be sure we try-catch it
}
$scope.escalationDefinitions = escalationDefinitionsProperty;
$scope.escalationChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-channel-type-controller.js

@ -0,0 +1,24 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableEventRegistryChannelTypeCtrl', [ '$scope', function($scope) {
if ($scope.property.value == undefined && $scope.property.value == null)
{
$scope.property.value = 'None';
}
$scope.channelTypeChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

141
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-correlation-parameters-controller.js

@ -0,0 +1,141 @@
/* 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.
*/
/*
* Input parameters for call activity
*/
angular.module('flowableModeler').controller('FlowableEventCorrelationParametersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/event-correlation-parameters-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableEventCorrelationParametersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.correlationParameters !== undefined
&& $scope.property.value.correlationParameters !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.parameters = angular.copy($scope.property.value.correlationParameters);
} else {
$scope.parameters = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var parameterName = $translate('PROPERTY.EVENTCORRELATIONPARAMETERS.NAME');
var parameterType = $translate('PROPERTY.EVENTCORRELATIONPARAMETERS.TYPE');
$q.all([parameterName, parameterType]).then(function (results) {
$scope.labels.parameterName = results[0];
$scope.labels.parameterType = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.parameters,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'name', displayName: $scope.labels.parameterName},
{field: 'type', displayName: $scope.labels.parameterType}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedParameter = row.entity;
});
};
});
// Click handler for add button
$scope.addNewParameter = function () {
var newParameter = {
name: '',
type: 'string',
value: ''
};
$scope.parameters.push(newParameter);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newParameter);
});
};
// Click handler for remove button
$scope.removeParameter = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.parameters.splice(index, 1);
if ($scope.parameters.length == 0) {
$scope.selectedParameter = undefined;
}
$timeout(function () {
if ($scope.parameters.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);
}
});
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.parameters.length > 0) {
$scope.property.value = {};
$scope.property.value.correlationParameters = $scope.parameters;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

141
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-in-parameters-controller.js

@ -0,0 +1,141 @@
/* 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.
*/
/*
* Input parameters for call activity
*/
angular.module('flowableModeler').controller('FlowableEventInParametersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/event-in-parameters-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableEventInParametersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.inParameters !== undefined
&& $scope.property.value.inParameters !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.parameters = angular.copy($scope.property.value.inParameters);
} else {
$scope.parameters = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var variableNameLabel = $translate('PROPERTY.EVENTINPARAMETERS.VARIABLENAME');
var eventNameLabel = $translate('PROPERTY.EVENTINPARAMETERS.EVENTNAME');
$q.all([variableNameLabel, eventNameLabel]).then(function (results) {
$scope.labels.variableNameLabel = results[1];
$scope.labels.eventNameLabel = results[0];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.parameters,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'variableName', displayName: $scope.labels.variableNameLabel},
{field: 'eventName', displayName: $scope.labels.eventNameLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedParameter = row.entity;
});
};
});
// Click handler for add button
$scope.addNewParameter = function () {
var newParameter = {
variableName: '',
eventName: '',
eventType: 'string'
};
$scope.parameters.push(newParameter);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newParameter);
});
};
// Click handler for remove button
$scope.removeParameter = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.parameters.splice(index, 1);
if ($scope.parameters.length == 0) {
$scope.selectedParameter = undefined;
}
$timeout(function () {
if ($scope.parameters.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);
}
});
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.parameters.length > 0) {
$scope.property.value = {};
$scope.property.value.inParameters = $scope.parameters;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

263
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-listeners-controller.js

@ -0,0 +1,263 @@
/* 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.
*/
/*
* Execution listeners
*/
angular.module('flowableModeler').controller('FlowableEventListenersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/event-listeners-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259
// Will be fixed in a newer version of Angular UI
angular.module('flowableModeler').controller('FlowableEventListenersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.eventListeners !== undefined
&& $scope.property.value.eventListeners !== null) {
if ($scope.property.value.eventListeners.constructor == String) {
$scope.eventListeners = JSON.parse($scope.property.value.eventListeners);
}
else {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.eventListeners = angular.copy($scope.property.value.eventListeners);
}
} else {
$scope.eventListeners = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var eventPromise = $translate('PROPERTY.EXECUTIONLISTENERS.EVENT');
var implementationPromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION');
var namePromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME');
$q.all([eventPromise, implementationPromise, namePromise]).then(function (results) {
$scope.labels.eventLabel = results[0];
$scope.labels.implementationLabel = results[1];
$scope.labels.nameLabel = results[2];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.eventListeners,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'event', displayName: $scope.labels.eventLabel},
{field: 'implementation', displayName: $scope.labels.implementationLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedListener = row.entity;
if ($scope.selectedListener) {
var fields = $scope.selectedListener.fields;
if (fields !== undefined && fields !== null) {
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (field.stringValue !== undefined && field.stringValue !== '') {
field.implementation = field.stringValue;
} else if (field.expression !== undefined && field.expression !== '') {
field.implementation = field.expression;
} else if (field.string !== undefined && field.string !== '') {
field.implementation = field.string;
}
}
} else {
$scope.selectedListener.fields = [];
}
if (!$scope.selectedListener.events) {
$scope.selectedListener.events = [{event: ''}];
}
}
});
};
});
// Click handler for + button after enum value
$scope.addEventValue = function (index) {
$scope.selectedListener.events.splice(index + 1, 0, {event: ''});
};
// Click handler for - button after enum value
$scope.removeEventValue = function (index) {
$scope.selectedListener.events.splice(index, 1);
$scope.listenerDetailsChanged();
};
$scope.listenerDetailsChanged = function () {
var listener = $scope.selectedListener;
if (listener.events) {
var eventText = '';
for (var i = 0; i < listener.events.length; i++) {
if (i > 0) {
eventText += ", ";
}
eventText += listener.events[i].event;
}
$scope.selectedListener.event = eventText;
}
if (listener.rethrowEvent) {
var implementationText = '';
if (listener.rethrowType && listener.rethrowType.length > 0) {
if (listener.rethrowType === 'error' && listener.errorcode !== '') {
implementationText = "Rethrow as error " + listener.errorcode;
}
else if (listener.rethrowType === 'message' && listener.messagename !== '') {
implementationText = "Rethrow as message " + listener.messagename;
}
else if ((listener.rethrowType === 'signal' || listener.rethrowType === 'globalSignal') && listener.signalname !== '') {
implementationText = "Rethrow as signal " + listener.signalname;
}
}
$scope.selectedListener.implementation = implementationText;
}
else {
if ($scope.selectedListener.className !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.className;
}
else if ($scope.selectedListener.delegateExpression !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;
}
else {
$scope.selectedListener.implementation = '';
}
}
};
// Click handler for add button
$scope.addNewListener = function () {
var newListener = {
event: '',
implementation: '',
className: '',
delegateExpression: '',
retrowEvent: false
};
$scope.eventListeners.push(newListener);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newListener);
});
};
// Click handler for remove button
$scope.removeListener = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.eventListeners.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.eventListeners.splice(index, 1);
if ($scope.eventListeners.length == 0) {
$scope.selectedListener = undefined;
}
$timeout(function () {
if ($scope.eventListeners.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.eventListeners[0]);
}
});
}
};
// Click handler for up button
$scope.moveListenerUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.eventListeners.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.eventListeners[index];
$scope.eventListeners.splice(index, 1);
$timeout(function () {
$scope.eventListeners.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveListenerDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.eventListeners.indexOf(selectedItems[0]);
if (index != $scope.eventListeners.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.eventListeners[index];
$scope.eventListeners.splice(index, 1);
$timeout(function () {
$scope.eventListeners.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.eventListeners.length > 0) {
$scope.property.value = {};
$scope.property.value.eventListeners = $scope.eventListeners;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

141
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-event-out-parameters-controller.js

@ -0,0 +1,141 @@
/* 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.
*/
/*
* Input parameters for call activity
*/
angular.module('flowableModeler').controller('FlowableEventOutParametersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/event-out-parameters-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableEventOutParametersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.outParameters !== undefined
&& $scope.property.value.outParameters !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.parameters = angular.copy($scope.property.value.outParameters);
} else {
$scope.parameters = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var eventNameLabel = $translate('PROPERTY.EVENTOUTPARAMETERS.EVENTNAME');
var variableNameLabel = $translate('PROPERTY.EVENTOUTPARAMETERS.VARIABLENAME');
$q.all([eventNameLabel, variableNameLabel]).then(function (results) {
$scope.labels.eventNameLabel = results[0];
$scope.labels.variableNameLabel = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.parameters,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'eventName', displayName: $scope.labels.eventNameLabel},
{field: 'variableName', displayName: $scope.labels.variableNameLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedParameter = row.entity;
});
};
});
// Click handler for add button
$scope.addNewParameter = function () {
var newParameter = {
eventName: '',
eventType: 'string',
variableName: ''
};
$scope.parameters.push(newParameter);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newParameter);
});
};
// Click handler for remove button
$scope.removeParameter = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.parameters.splice(index, 1);
if ($scope.parameters.length == 0) {
$scope.selectedParameter = undefined;
}
$timeout(function () {
if ($scope.parameters.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);
}
});
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.parameters.length > 0) {
$scope.property.value = {};
$scope.property.value.outParameters = $scope.parameters;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

184
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-exceptions-controller.js

@ -0,0 +1,184 @@
/* 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.
*/
/*
* Task listeners
*/
angular.module('flowableModeler').controller('FlowableExceptionsCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/exceptions-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableExceptionsPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.exceptions !== undefined
&& $scope.property.value.exceptions !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.exceptions = angular.copy($scope.property.value.exceptions);
} else {
$scope.exceptions = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var codePromise = $translate('PROPERTY.EXCEPTIONS.CODE');
var classPromise = $translate('PROPERTY.EXCEPTIONS.CLASS');
$q.all([codePromise, classPromise]).then(function (results) {
$scope.labels.codeLabel = results[0];
$scope.labels.classLabel = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.exceptions,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'code', displayName: $scope.labels.codeLabel},
{field: 'class', displayName: $scope.labels.classLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedException = row.entity;
});
};
});
$scope.exceptionDetailsChanged = function () {
if ($scope.selectedException.class != '') {
$scope.selectedException.class = $scope.selectedException.class;
}
};
// Click handler for add button
$scope.addNewException = function () {
var newException = {
code: '',
class: '',
children: false
};
$scope.exceptions.push(newException);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newException);
});
};
// Click handler for remove button
$scope.removeException = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.exceptions.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.exceptions.splice(index, 1);
if ($scope.exceptions.length == 0) {
$scope.selectedException = undefined;
}
$timeout(function () {
if ($scope.exceptions.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.exceptions[0]);
}
});
}
};
// Click handler for up button
$scope.moveExceptionUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.exceptions.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.exceptions[index];
$scope.exceptions.splice(index, 1);
$timeout(function () {
$scope.exceptions.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveExceptionDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.exceptions.indexOf(selectedItems[0]);
if (index != $scope.exceptions.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.exceptions[index];
$scope.exceptions.splice(index, 1);
$timeout(function () {
$scope.exceptions.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.exceptions.length > 0) {
$scope.property.value = {};
$scope.property.value.exceptions = $scope.exceptions;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.$hide();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

358
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-execution-listeners-controller.js

@ -0,0 +1,358 @@
/* 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.
*/
/*
* Execution listeners
*/
angular.module('flowableModeler').controller('FlowableExecutionListenersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/execution-listeners-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableExecutionListenersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.executionListeners !== undefined
&& $scope.property.value.executionListeners !== null) {
if ($scope.property.value.executionListeners.constructor == String) {
$scope.executionListeners = JSON.parse($scope.property.value.executionListeners);
}
else {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.executionListeners = angular.copy($scope.property.value.executionListeners);
}
for (var i = 0; i < $scope.executionListeners.length; i++) {
var executionListener = $scope.executionListeners[i];
if (executionListener.className !== undefined && executionListener.className !== '') {
executionListener.implementation = executionListener.className;
}
else if (executionListener.expression !== undefined && executionListener.expression !== '') {
executionListener.implementation = executionListener.expression;
}
else if (executionListener.delegateExpression !== undefined && executionListener.delegateExpression !== '') {
executionListener.implementation = executionListener.delegateExpression;
}
}
} else {
$scope.executionListeners = [];
}
$scope.selectedListener = undefined;
$scope.selectedField = undefined;
$scope.fields = [];
$scope.translationsRetrieved = false;
$scope.labels = {};
var eventPromise = $translate('PROPERTY.EXECUTIONLISTENERS.EVENT');
var implementationPromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION');
var namePromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME');
$q.all([eventPromise, implementationPromise, namePromise]).then(function (results) {
$scope.labels.eventLabel = results[0];
$scope.labels.implementationLabel = results[1];
$scope.labels.nameLabel = results[2];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.executionListeners,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'event', displayName: $scope.labels.eventLabel},
{field: 'implementation', displayName: $scope.labels.implementationLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedListener = row.entity;
$scope.selectedField = undefined;
if ($scope.selectedListener) {
var fields = $scope.selectedListener.fields;
if (fields !== undefined && fields !== null) {
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (field.stringValue !== undefined && field.stringValue !== '') {
field.implementation = field.stringValue;
} else if (field.expression !== undefined && field.expression !== '') {
field.implementation = field.expression;
} else if (field.string !== undefined && field.string !== '') {
field.implementation = field.string;
}
}
} else {
$scope.selectedListener.fields = [];
}
$scope.fields.length = 0;
for (var i = 0; i < $scope.selectedListener.fields.length; i++) {
$scope.fields.push($scope.selectedListener.fields[i]);
}
}
});
};
// Config for field grid
$scope.gridFieldOptions = {
data: $scope.fields,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'name', displayName: $scope.labels.name},
{field: 'implementation', displayName: $scope.labels.implementationLabel}]
};
$scope.gridFieldOptions.onRegisterApi = function (gridApi) {
// set gridApi on scope
$scope.fieldGridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedField = row.entity;
});
};
});
$scope.listenerDetailsChanged = function () {
if ($scope.selectedListener.className !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.className;
} else if ($scope.selectedListener.expression !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.expression;
} else if ($scope.selectedListener.delegateExpression !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;
} else {
$scope.selectedListener.implementation = '';
}
};
// Click handler for add button
$scope.addNewListener = function () {
var newListener = {
event: 'start',
implementation: '',
className: '',
expression: '',
delegateExpression: ''
};
$scope.executionListeners.push(newListener);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newListener);
});
};
// Click handler for remove button
$scope.removeListener = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.executionListeners.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.executionListeners.splice(index, 1);
if ($scope.executionListeners.length == 0) {
$scope.selectedListener = undefined;
}
$timeout(function () {
if ($scope.executionListeners.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.executionListeners[0]);
}
});
}
};
// Click handler for up button
$scope.moveListenerUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.executionListeners.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.executionListeners[index];
$scope.executionListeners.splice(index, 1);
$timeout(function () {
$scope.executionListeners.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveListenerDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.executionListeners.indexOf(selectedItems[0]);
if (index != $scope.executionListeners.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.executionListeners[index];
$scope.executionListeners.splice(index, 1);
$timeout(function () {
$scope.executionListeners.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
$scope.fieldDetailsChanged = function () {
if ($scope.selectedField.stringValue != '') {
$scope.selectedField.implementation = $scope.selectedField.stringValue;
} else if ($scope.selectedField.expression != '') {
$scope.selectedField.implementation = $scope.selectedField.expression;
} else if ($scope.selectedField.string != '') {
$scope.selectedField.implementation = $scope.selectedField.string;
} else {
$scope.selectedField.implementation = '';
}
};
// Click handler for add button
$scope.addNewField = function () {
if ($scope.selectedListener) {
if ($scope.selectedListener.fields == undefined) {
$scope.selectedListener.fields = [];
}
var newField = {
name: 'fieldName',
implementation: '',
stringValue: '',
expression: '',
string: ''
};
$scope.fields.push(newField);
$scope.selectedListener.fields.push(newField);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(newField);
});
}
};
// Click handler for remove button
$scope.removeField = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
$scope.fieldGridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.fields.splice(index, 1);
$scope.selectedListener.fields.splice(index, 1);
if ($scope.fields.length == 0) {
$scope.selectedField = undefined;
}
$timeout(function () {
if ($scope.fields.length > 0) {
$scope.fieldGridApi.selection.toggleRowSelection($scope.fields[0]);
}
});
}
};
// Click handler for up button
$scope.moveFieldUp = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$scope.selectedListener.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + -1, 0, temp);
$scope.selectedListener.fields.splice(index + -1, 0, temp);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveFieldDown = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$scope.selectedListener.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + 1, 0, temp);
$scope.selectedListener.fields.splice(index + 1, 0, temp);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.executionListeners.length > 0) {
$scope.property.value = {};
$scope.property.value.executionListeners = $scope.executionListeners;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
// Close button handler
$scope.close = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
}]);

206
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-fields-controller.js

@ -0,0 +1,206 @@
/* 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.
*/
/*
* Task listeners
*/
angular.module('flowableModeler').controller('FlowableFieldsCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/fields-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableFieldsPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.fields !== undefined
&& $scope.property.value.fields !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.fields = angular.copy($scope.property.value.fields);
for (var i = 0; i < $scope.fields.length; i++) {
var field = $scope.fields[i];
if (field.stringValue !== undefined && field.stringValue !== '') {
field.implementation = field.stringValue;
}
else if (field.expression !== undefined && field.expression !== '') {
field.implementation = field.expression;
}
else if (field.string !== undefined && field.string !== '') {
field.implementation = field.string;
}
}
} else {
$scope.fields = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var namePromise = $translate('PROPERTY.FIELDS.NAME');
var implementationPromise = $translate('PROPERTY.FIELDS.IMPLEMENTATION');
$q.all([namePromise, implementationPromise]).then(function (results) {
$scope.labels.nameLabel = results[0];
$scope.labels.implementationLabel = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.fields,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'name', displayName: $scope.labels.nameLabel},
{field: 'implementation', displayName: $scope.labels.implementationLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedField = row.entity;
});
};
});
$scope.fieldDetailsChanged = function () {
if ($scope.selectedField.stringValue != '') {
$scope.selectedField.implementation = $scope.selectedField.stringValue;
}
else if ($scope.selectedField.expression != '') {
$scope.selectedField.implementation = $scope.selectedField.expression;
}
else if ($scope.selectedField.string != '') {
$scope.selectedField.implementation = $scope.selectedField.string;
}
else {
$scope.selectedField.implementation = '';
}
};
// Click handler for add button
$scope.addNewField = function () {
var newField = {
name: 'fieldName',
implementation: '',
stringValue: '',
expression: '',
string: ''
};
$scope.fields.push(newField);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newField);
});
};
// Click handler for remove button
$scope.removeField = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.fields.splice(index, 1);
if ($scope.fields.length == 0) {
$scope.selectedField = undefined;
}
$timeout(function () {
if ($scope.fields.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.fields[0]);
}
});
}
};
// Click handler for up button
$scope.moveFieldUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveFieldDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.fields.length > 0) {
$scope.property.value = {};
$scope.property.value.fields = $scope.fields;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.$hide();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

327
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-form-properties-controller.js

@ -0,0 +1,327 @@
/* 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.
*/
/*
* Form Properties
*/
angular.module('flowableModeler').controller('FlowableFormPropertiesCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/form-properties-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableFormPropertiesPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.formProperties !== undefined
&& $scope.property.value.formProperties !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happended
$scope.formProperties = angular.copy($scope.property.value.formProperties);
for (var i = 0; i < $scope.formProperties.length; i++) {
var formProperty = $scope.formProperties[i];
if (formProperty.enumValues && formProperty.enumValues.length > 0) {
for (var j = 0; j < formProperty.enumValues.length; j++) {
var enumValue = formProperty.enumValues[j];
if (!enumValue.id && !enumValue.name && enumValue.value) {
enumValue.id = enumValue.value;
enumValue.name = enumValue.value;
}
}
}
}
} else {
$scope.formProperties = [];
}
$scope.enumValues = [];
$scope.translationsRetrieved = false;
$scope.labels = {};
var idPromise = $translate('PROPERTY.FORMPROPERTIES.ID');
var namePromise = $translate('PROPERTY.FORMPROPERTIES.NAME');
var typePromise = $translate('PROPERTY.FORMPROPERTIES.TYPE');
$q.all([idPromise, namePromise, typePromise]).then(function (results) {
$scope.labels.idLabel = results[0];
$scope.labels.nameLabel = results[1];
$scope.labels.typeLabel = results[2];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.formProperties,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'id', displayName: $scope.labels.idLabel},
{field: 'name', displayName: $scope.labels.nameLabel},
{field: 'type', displayName: $scope.labels.typeLabel}]
};
$scope.enumGridOptions = {
data: $scope.enumValues,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },
{ field: 'name', displayName: $scope.labels.nameLabel}]
}
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedProperty = row.entity;
$scope.selectedEnumValue = undefined;
if ($scope.selectedProperty && $scope.selectedProperty.enumValues) {
$scope.enumValues.length = 0;
for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
$scope.enumValues.push($scope.selectedProperty.enumValues[i]);
}
}
});
};
$scope.enumGridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.enumGridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedEnumValue = row.entity;
});
};
});
// Handler for when the value of the type dropdown changes
$scope.propertyTypeChanged = function () {
// Check date. If date, show date pattern
if ($scope.selectedProperty.type === 'date') {
$scope.selectedProperty.datePattern = 'MM-dd-yyyy hh:mm';
} else {
delete $scope.selectedProperty.datePattern;
}
// Check enum. If enum, show list of options
if ($scope.selectedProperty.type === 'enum') {
$scope.selectedProperty.enumValues = [ {id: 'value1', name: 'Value 1'}, {id: 'value2', name: 'Value 2'}];
$scope.enumValues.length = 0;
for (var i = 0; i < $scope.selectedProperty.enumValues.length; i++) {
$scope.enumValues.push($scope.selectedProperty.enumValues[i]);
}
} else {
delete $scope.selectedProperty.enumValues;
$scope.enumValues.length = 0;
}
};
// Click handler for add button
var propertyIndex = 1;
$scope.addNewProperty = function () {
var newProperty = {
id: 'new_property_' + propertyIndex++,
name: '',
type: 'string',
readable: true,
writable: true
};
$scope.formProperties.push(newProperty);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newProperty);
});
};
// Click handler for remove button
$scope.removeProperty = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.formProperties.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.formProperties.splice(index, 1);
if ($scope.formProperties.length == 0) {
$scope.selectedProperty = undefined;
}
$timeout(function() {
if ($scope.formProperties.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.formProperties[0]);
}
});
}
};
// Click handler for up button
$scope.movePropertyUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.formProperties.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.formProperties[index];
$scope.formProperties.splice(index, 1);
$timeout(function(){
$scope.formProperties.splice(index + -1, 0, temp);
$timeout(function() {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.movePropertyDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.formProperties.indexOf(selectedItems[0]);
if (index != $scope.formProperties.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.formProperties[index];
$scope.formProperties.splice(index, 1);
$timeout(function(){
$scope.formProperties.splice(index + 1, 0, temp);
$timeout(function() {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
$scope.addNewEnumValue = function() {
if ($scope.selectedProperty) {
var newEnumValue = { id : '', name : ''};
$scope.selectedProperty.enumValues.push(newEnumValue);
$scope.enumValues.push(newEnumValue);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(newEnumValue);
});
}
};
// Click handler for remove button
$scope.removeEnumValue = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
$scope.enumGridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
if ($scope.enumValues.length == 0) {
$scope.selectedEnumValue = undefined;
}
$timeout(function () {
if ($scope.enumValues.length > 0) {
$scope.enumGridApi.selection.toggleRowSelection($scope.enumValues[0]);
}
});
}
};
// Click handler for up button
$scope.moveEnumValueUp = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.enumValues[index];
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
$timeout(function () {
$scope.enumValues.splice(index + -1, 0, temp);
$scope.selectedProperty.enumValues.splice(index + -1, 0, temp);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveEnumValueDown = function() {
var selectedItems = $scope.enumGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.enumValues.indexOf(selectedItems[0]);
if (index != $scope.enumValues.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.enumValues[index];
$scope.enumValues.splice(index, 1);
$scope.selectedProperty.enumValues.splice(index, 1);
$timeout(function () {
$scope.enumValues.splice(index + 1, 0, temp);
$scope.selectedProperty.enumValues.splice(index + 1, 0, temp);
$timeout(function () {
$scope.enumGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.formProperties.length > 0) {
$scope.property.value = {};
$scope.property.value.formProperties = $scope.formProperties;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
// Close button handler
$scope.close = function () {
$scope.$hide();
$scope.property.mode = 'read';
};
}])
;

261
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-form-reference-controller.js

@ -0,0 +1,261 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableFormReferenceDisplayCtrl',
[ '$scope', '$modal', '$http', function($scope, $modal, $http) {
if ($scope.property && $scope.property.value && $scope.property.value.id) {
$http.get(FLOWABLE.APP_URL.getModelUrl($scope.property.value.id))
.success(
function(response) {
$scope.form = {
id: response.id,
name: response.name
};
});
}
}]);
angular.module('flowableModeler').controller('FlowableFormReferenceCtrl',
[ '$scope', '$modal', '$http', function($scope, $modal, $http) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/form-reference-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableFormReferencePopupCtrl',
[ '$rootScope', '$scope', '$http', '$location', 'editorManager', function($rootScope, $scope, $http, $location, editorManager) {
$scope.state = {'loadingForms' : true, 'formError' : false};
$scope.popup = {'state' : 'formReference'};
$scope.foldersBreadCrumbs = [];
// Close button handler
$scope.close = function() {
$scope.property.mode = 'read';
$scope.$hide();
};
// Selecting/deselecting a subprocess
$scope.selectForm = function(form, $event) {
$event.stopPropagation();
if ($scope.selectedForm && $scope.selectedForm.id && form.id == $scope.selectedForm.id) {
// un-select the current selection
$scope.selectedForm = null;
} else {
$scope.selectedForm = form;
}
};
// Saving the selected value
$scope.save = function() {
if ($scope.selectedForm) {
$scope.property.value = {
'id' : $scope.selectedForm.id,
'name' : $scope.selectedForm.name,
'key' : $scope.selectedForm.key
};
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
// Open the selected value
$scope.open = function() {
if ($scope.selectedForm) {
$scope.property.value = {
'id' : $scope.selectedForm.id,
'name' : $scope.selectedForm.name,
'key' : $scope.selectedForm.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated
};
// Update
$http({ method: 'POST',
data: params,
ignoreErrors: true,
headers: {'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)})
.success(function (data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
var allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('form-editor/' + $scope.selectedForm.id);
})
.error(function (data, status, headers, config) {
});
$scope.close();
}
};
$scope.newForm = function() {
$scope.popup.state = 'newForm';
var modelMetaData = editorManager.getBaseModelData();
$scope.model = {
loading: false,
form: {
name: '',
key: '',
description: '',
modelType: 2
}
};
};
$scope.createForm = function() {
if (!$scope.model.form.name || $scope.model.form.name.length == 0 ||
!$scope.model.form.key || $scope.model.form.key.length == 0) {
return;
}
$scope.model.loading = true;
$http({method: 'POST', url: FLOWABLE.APP_URL.getModelsUrl(), data: $scope.model.form}).
success(function(data, status, headers, config) {
var newFormId = data.id;
$scope.property.value = {
'id' : newFormId,
'name' : data.name,
'key' : data.key
};
$scope.updatePropertyInModel($scope.property);
var modelMetaData = editorManager.getBaseModelData();
var json = editorManager.getModel();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: modelMetaData.name,
key: modelMetaData.key,
description: modelMetaData.description,
newversion: false,
lastUpdated: modelMetaData.lastUpdated
};
// Update
$http({ method: 'POST',
data: params,
ignoreErrors: true,
headers: {'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: FLOWABLE.URL.putModel(modelMetaData.modelId)})
.success(function (data, status, headers, config) {
editorManager.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$scope.model.loading = false;
$scope.$hide();
var allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);
$rootScope.addHistoryItem($scope.selectedShape.resourceId);
$location.path('form-editor/' + newFormId);
})
.error(function (data, status, headers, config) {
$scope.model.loading = false;
$scope.$hide();
});
}).
error(function(data, status, headers, config) {
$scope.model.loading = false;
$scope.model.errorMessage = data.message;
});
};
$scope.cancel = function() {
$scope.close();
};
$scope.loadForms = function() {
var modelMetaData = editorManager.getBaseModelData();
$http.get(FLOWABLE.APP_URL.getFormModelsUrl())
.success(
function(response) {
$scope.state.loadingForms = false;
$scope.state.formError = false;
$scope.forms = response.data;
})
.error(
function(data, status, headers, config) {
$scope.state.loadingForms = false;
$scope.state.formError = true;
});
};
if ($scope.property && $scope.property.value && $scope.property.value.id) {
$scope.selectedForm = $scope.property.value;
}
$scope.loadForms();
}]);

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-httprequest-controller.js

@ -0,0 +1,24 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableHttpRequestMethodCtrl', [ '$scope', function($scope) {
if ($scope.property.value == undefined && $scope.property.value == null)
{
$scope.property.value = 'GET';
}
$scope.httpRequestMethodChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

184
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-in-parameters-controller.js

@ -0,0 +1,184 @@
/* 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.
*/
/*
* Input parameters for call activity
*/
angular.module('flowableModeler').controller('FlowableInParametersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/in-parameters-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableInParametersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.inParameters !== undefined
&& $scope.property.value.inParameters !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.parameters = angular.copy($scope.property.value.inParameters);
} else {
$scope.parameters = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var sourcePromise = $translate('PROPERTY.PARAMETER.SOURCE');
var sourceExpressionPromise = $translate('PROPERTY.PARAMETER.SOURCEEXPRESSION');
var targetPromise = $translate('PROPERTY.PARAMETER.TARGET');
var targetExpressionPromise = $translate('PROPERTY.PARAMETER.TARGETEXPRESSION');
$q.all([sourcePromise, sourceExpressionPromise, targetPromise, targetExpressionPromise]).then(function (results) {
$scope.labels.sourceLabel = results[0];
$scope.labels.sourceExpressionLabel = results[1];
$scope.labels.targetLabel = results[2];
$scope.labels.targetExpressionLabel = results[3];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.parameters,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'source', displayName: $scope.labels.sourceLabel},
{field: 'sourceExpression', displayName: $scope.labels.sourceExpressionLabel},
{field: 'target', displayName: $scope.labels.targetLabel},
{field: 'targetExpression', displayName: $scope.labels.targetExpressionLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedParameter = row.entity;
});
};
});
// Click handler for add button
$scope.addNewParameter = function () {
var newParameter = {
source: '',
sourceExpression: '',
target: '',
targetExpression: ''
};
$scope.parameters.push(newParameter);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newParameter);
});
};
// Click handler for remove button
$scope.removeParameter = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.parameters.splice(index, 1);
if ($scope.parameters.length == 0) {
$scope.selectedParameter = undefined;
}
$timeout(function () {
if ($scope.parameters.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);
}
});
}
};
// Click handler for up button
$scope.moveParameterUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.parameters[index];
$scope.parameters.splice(index, 1);
$timeout(function () {
$scope.parameters.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveParameterDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.parameters[index];
$scope.parameters.splice(index, 1);
$timeout(function () {
$scope.parameters.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.parameters.length > 0) {
$scope.property.value = {};
$scope.property.value.inParameters = $scope.parameters;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

145
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-message-definitions-controller.js

@ -0,0 +1,145 @@
/* 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.
*/
/*
* Execution listeners
*/
angular.module('flowableModeler').controller('FlowableMessageDefinitionsCtrl', ['$scope', '$modal', function ($scope, $modal) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/message-definitions-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259
// Will be fixed in a newer version of Angular UI
angular.module('flowableModeler').controller('FlowableMessageDefinitionsPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing mesage definitions on scope
if ($scope.property.value !== undefined && $scope.property.value !== null && $scope.property.value.length > 0) {
if ($scope.property.value.constructor == String) {
$scope.messageDefinitions = JSON.parse($scope.property.value);
}
else {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.messageDefinitions = angular.copy($scope.property.value);
}
} else {
$scope.messageDefinitions = [];
}
// Array to contain selected mesage definitions (yes - we only can select one, but ng-grid isn't smart enough)
$scope.selectedMessageDefinition = undefined;
$scope.translationsRetrieved = false;
$scope.labels = {};
var idPromise = $translate('PROPERTY.MESSAGEDEFINITIONS.ID');
var namePromise = $translate('PROPERTY.MESSAGEDEFINITIONS.NAME');
$q.all([idPromise, namePromise]).then(function (results) {
$scope.labels.idLabel = results[0];
$scope.labels.nameLabel = results[1];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.messageDefinitions,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'id', displayName: $scope.labels.idLabel},
{field: 'name', displayName: $scope.labels.nameLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedMessageDefinition = row.entity;
});
};
});
// Click handler for add button
$scope.addNewMessageDefinition = function () {
var newMessageDefinition = {id: '', name: ''};
$scope.messageDefinitions.push(newMessageDefinition);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newMessageDefinition);
});
};
// Click handler for remove button
$scope.removeMessageDefinition = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.messageDefinitions.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.messageDefinitions.splice(index, 1);
if ($scope.messageDefinitions.length == 0) {
$scope.selectedMesageDefinition = undefined;
}
$timeout(function () {
if ($scope.messageDefinitions.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.messageDefinitions[0]);
}
});
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.messageDefinitions.length > 0) {
$scope.property.value = $scope.messageDefinitions;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

41
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-message-scope-controller.js

@ -0,0 +1,41 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableMessageRefCtrl', [ '$scope', function($scope) {
// Find the parent shape on which the message definitions are defined
var messageDefinitionsProperty = undefined;
var parent = $scope.selectedShape;
while (parent !== null && parent !== undefined && messageDefinitionsProperty === undefined) {
if (parent.properties && parent.properties.get('oryx-messagedefinitions')) {
messageDefinitionsProperty = parent.properties.get('oryx-messagedefinitions');
} else {
parent = parent.parent;
}
}
try {
messageDefinitionsProperty = JSON.parse(messageDefinitionsProperty);
if (typeof messageDefinitionsProperty == 'string') {
messageDefinitionsProperty = JSON.parse(messageDefinitionsProperty);
}
} catch (err) {
// Do nothing here, just to be sure we try-catch it
}
$scope.messageDefinitions = messageDefinitionsProperty;
$scope.messageChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

24
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-multiinstance-controller.js

@ -0,0 +1,24 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowableMultiInstanceCtrl', [ '$scope', function($scope) {
if ($scope.property.value == undefined && $scope.property.value == null)
{
$scope.property.value = 'None';
}
$scope.multiInstanceChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

28
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-ordering-controller.js

@ -0,0 +1,28 @@
/* 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.
*/
/*
* Adhoc sub process ordering property
*/
angular.module('flowableModeler').controller('FlowableOrderingCtrl', [ '$scope', function($scope) {
if ($scope.property.value == undefined && $scope.property.value == null)
{
$scope.property.value = 'Parallel';
}
$scope.orderingChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

180
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-out-parameters-controller.js

@ -0,0 +1,180 @@
/* 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.
*/
/*
* Input parameters for call activity
*/
angular.module('flowableModeler').controller('FlowableOutParametersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/out-parameters-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowableOutParametersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.outParameters !== undefined
&& $scope.property.value.outParameters !== null) {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.parameters = angular.copy($scope.property.value.outParameters);
} else {
$scope.parameters = [];
}
$scope.translationsRetrieved = false;
$scope.labels = {};
var sourcePromise = $translate('PROPERTY.PARAMETER.SOURCE');
var sourceExpressionPromise = $translate('PROPERTY.PARAMETER.SOURCEEXPRESSION');
var targetPromise = $translate('PROPERTY.PARAMETER.TARGET');
var targetExpressionPromise = $translate('PROPERTY.PARAMETER.TARGETEXPRESSION');
$q.all([sourcePromise, sourceExpressionPromise, targetPromise, targetExpressionPromise]).then(function (results) {
$scope.labels.sourceLabel = results[0];
$scope.labels.sourceExpressionLabel = results[1];
$scope.labels.targetLabel = results[2];
$scope.labels.targetExpressionLabel = results[3];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.parameters,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [{field: 'source', displayName: $scope.labels.sourceLabel},
{field: 'sourceExpression', displayName: $scope.labels.sourceExpressionLabel},
{field: 'target', displayName: $scope.labels.targetLabel},
{field: 'targetExpression', displayName: $scope.labels.targetExpressionLabel}]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedParameter = row.entity;
});
};
});
// Click handler for add button
$scope.addNewParameter = function () {
var newParameter = {
source: '',
sourceExpression: '',
target: '',
targetExpression: ''};
$scope.parameters.push(newParameter);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newParameter);
});
};
// Click handler for remove button
$scope.removeParameter = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.parameters.splice(index, 1);
if ($scope.parameters.length == 0) {
$scope.selectedParameter = undefined;
}
$timeout(function () {
if ($scope.parameters.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.parameters[0]);
}
});
}
};
// Click handler for up button
$scope.moveParameterUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.parameters[index];
$scope.parameters.splice(index, 1);
$timeout(function () {
$scope.parameters.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveParameterDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.parameters.indexOf(selectedItems[0]);
if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.parameters[index];
$scope.parameters.splice(index, 1);
$timeout(function () {
$scope.parameters.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.parameters.length > 0) {
$scope.property.value = {};
$scope.property.value.outParameters = $scope.parameters;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

357
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-plan-item-lifecycle-listeners-controller.js

@ -0,0 +1,357 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowablePlanItemLifecycleListenersCtrl',
['$scope', '$modal', '$timeout', '$translate', function ($scope, $modal, $timeout, $translate) {
// Config for the modal window
var opts = {
template: 'editor-app/configuration/properties/plan-item-lifecycle-listeners-popup.html?version=' + Date.now(),
scope: $scope
};
// Open the dialog
_internalCreateModal(opts, $modal, $scope);
}]);
angular.module('flowableModeler').controller('FlowablePlanItemLifecycleListenersPopupCtrl',
['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {
// Put json representing form properties on scope
if ($scope.property.value !== undefined && $scope.property.value !== null
&& $scope.property.value.planItemLifecycleListeners !== undefined
&& $scope.property.value.planItemLifecycleListeners !== null) {
if ($scope.property.value.planItemLifecycleListeners.constructor == String) {
$scope.planItemLifecycleListeners = JSON.parse($scope.property.value.planItemLifecycleListeners);
}
else {
// Note that we clone the json object rather then setting it directly,
// this to cope with the fact that the user can click the cancel button and no changes should have happened
$scope.planItemLifecycleListeners = angular.copy($scope.property.value.planItemLifecycleListeners);
}
for (var i = 0; i < $scope.planItemLifecycleListeners.length; i++) {
var planItemLifeCycleListener = $scope.planItemLifecycleListeners[i];
if (planItemLifeCycleListener.className !== undefined && planItemLifeCycleListener.className !== '') {
planItemLifeCycleListener.implementation = planItemLifeCycleListener.className;
}
else if (planItemLifeCycleListener.expression !== undefined && planItemLifeCycleListener.expression !== '') {
planItemLifeCycleListener.implementation = planItemLifeCycleListener.expression;
}
else if (planItemLifeCycleListener.delegateExpression !== undefined && planItemLifeCycleListener.delegateExpression !== '') {
planItemLifeCycleListener.implementation = planItemLifeCycleListener.delegateExpression;
}
}
} else {
$scope.planItemLifecycleListeners = [];
}
$scope.selectedListener = undefined;
$scope.selectedField = undefined;
$scope.fields = [];
$scope.translationsRetrieved = false;
$scope.labels = {};
var sourceStatePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.SOURCE_STATE');
var targetStatePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.TARGET_STATE');
var implementationPromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.IMPLEMENTATION');
var namePromise = $translate('PROPERTY.PLANITEMLIFECYCLELISTENERS.FIELDS.NAME');
$q.all([sourceStatePromise, targetStatePromise, implementationPromise, namePromise]).then(function (results) {
$scope.labels.sourceStateLabel = results[1];
$scope.labels.targetStateLabel = results[2];
$scope.labels.implementationLabel = results[3];
$scope.labels.nameLabel = results[4];
$scope.translationsRetrieved = true;
// Config for grid
$scope.gridOptions = {
data: $scope.planItemLifecycleListeners,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
enableHorizontalScrollbar: 0,
enableColumnMenus: false,
enableSorting: false,
columnDefs: [
{field: 'sourceState', displayName: $scope.labels.sourceStateLabel},
{field: 'targetState', displayName: $scope.labels.targetStateLabel},
{field: 'implementation', displayName: $scope.labels.implementationLabel}
]
};
$scope.gridOptions.onRegisterApi = function (gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedListener = row.entity;
$scope.selectedField = undefined;
if ($scope.selectedListener) {
var fields = $scope.selectedListener.fields;
if (fields !== undefined && fields !== null) {
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (field.stringValue !== undefined && field.stringValue !== '') {
field.implementation = field.stringValue;
} else if (field.expression !== undefined && field.expression !== '') {
field.implementation = field.expression;
} else if (field.string !== undefined && field.string !== '') {
field.implementation = field.string;
}
}
} else {
$scope.selectedListener.fields = [];
}
$scope.fields.length = 0;
for (var i = 0; i < $scope.selectedListener.fields.length; i++) {
$scope.fields.push($scope.selectedListener.fields[i]);
}
}
});
};
// Config for field grid
$scope.gridFieldOptions = {
data: $scope.fields,
headerRowHeight: 28,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
columnDefs: [{field: 'name', displayName: $scope.labels.name},
{field: 'implementation', displayName: $scope.labels.implementationLabel}]
};
$scope.gridFieldOptions.onRegisterApi = function (gridApi) {
// set gridApi on scope
$scope.fieldGridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.selectedField = row.entity;
});
};
});
$scope.listenerDetailsChanged = function () {
if ($scope.selectedListener.className !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.className;
} else if ($scope.selectedListener.expression !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.expression;
} else if ($scope.selectedListener.delegateExpression !== '') {
$scope.selectedListener.implementation = $scope.selectedListener.delegateExpression;
} else {
$scope.selectedListener.implementation = '';
}
};
// Click handler for add button
$scope.addNewListener = function () {
var newListener = {
sourceState: 'available',
targetState: 'active',
implementation: '',
className: '',
expression: '',
delegateExpression: ''
};
$scope.planItemLifecycleListeners.push(newListener);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(newListener);
});
};
// Click handler for remove button
$scope.removeListener = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);
$scope.gridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.planItemLifecycleListeners.splice(index, 1);
if ($scope.planItemLifecycleListeners.length == 0) {
$scope.selectedListener = undefined;
}
$timeout(function () {
if ($scope.planItemLifecycleListeners.length > 0) {
$scope.gridApi.selection.toggleRowSelection($scope.planItemLifecycleListeners[0]);
}
});
}
};
// Click handler for up button
$scope.moveListenerUp = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.planItemLifecycleListeners[index];
$scope.planItemLifecycleListeners.splice(index, 1);
$timeout(function () {
$scope.planItemLifecycleListeners.splice(index + -1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveListenerDown = function () {
var selectedItems = $scope.gridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.planItemLifecycleListeners.indexOf(selectedItems[0]);
if (index != $scope.planItemLifecycleListeners.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.planItemLifecycleListeners[index];
$scope.planItemLifecycleListeners.splice(index, 1);
$timeout(function () {
$scope.planItemLifecycleListeners.splice(index + 1, 0, temp);
$timeout(function () {
$scope.gridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
$scope.fieldDetailsChanged = function () {
if ($scope.selectedField.stringValue != '') {
$scope.selectedField.implementation = $scope.selectedField.stringValue;
} else if ($scope.selectedField.expression != '') {
$scope.selectedField.implementation = $scope.selectedField.expression;
} else if ($scope.selectedField.string != '') {
$scope.selectedField.implementation = $scope.selectedField.string;
} else {
$scope.selectedField.implementation = '';
}
};
// Click handler for add button
$scope.addNewField = function () {
if ($scope.selectedListener) {
if ($scope.selectedListener.fields == undefined) {
$scope.selectedListener.fields = [];
}
var newField = {
name: 'fieldName',
implementation: '',
stringValue: '',
expression: '',
string: ''
};
$scope.fields.push(newField);
$scope.selectedListener.fields.push(newField);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(newField);
});
}
};
// Click handler for remove button
$scope.removeField = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
$scope.fieldGridApi.selection.toggleRowSelection(selectedItems[0]);
$scope.fields.splice(index, 1);
$scope.selectedListener.fields.splice(index, 1);
if ($scope.fields.length == 0) {
$scope.selectedField = undefined;
}
$timeout(function () {
if ($scope.fields.length > 0) {
$scope.fieldGridApi.selection.toggleRowSelection($scope.fields[0]);
}
});
}
};
// Click handler for up button
$scope.moveFieldUp = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != 0) { // If it's the first, no moving up of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$scope.selectedListener.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + -1, 0, temp);
$scope.selectedListener.fields.splice(index + -1, 0, temp);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for down button
$scope.moveFieldDown = function () {
var selectedItems = $scope.fieldGridApi.selection.getSelectedRows();
if (selectedItems && selectedItems.length > 0) {
var index = $scope.fields.indexOf(selectedItems[0]);
if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course
var temp = $scope.fields[index];
$scope.fields.splice(index, 1);
$scope.selectedListeners.fields.splice(index, 1);
$timeout(function () {
$scope.fields.splice(index + 1, 0, temp);
$scope.selectedListener.fields.splice(index + 1, 0, temp);
$timeout(function () {
$scope.fieldGridApi.selection.toggleRowSelection(temp);
});
});
}
}
};
// Click handler for save button
$scope.save = function () {
if ($scope.planItemLifecycleListeners.length > 0) {
$scope.property.value = {};
$scope.property.value.planItemLifecycleListeners = $scope.planItemLifecycleListeners;
} else {
$scope.property.value = null;
}
$scope.updatePropertyInModel($scope.property);
$scope.close();
};
$scope.cancel = function () {
$scope.close();
};
// Close button handler
$scope.close = function () {
$scope.property.mode = 'read';
$scope.$hide();
};
}]);

82
io.sc.platform.flowable/src/main/resources/flowable-modeler/editor-app/configuration/properties-planitem-dropdown-controller.js

@ -0,0 +1,82 @@
/* 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.
*/
angular.module('flowableModeler').controller('FlowablePlanItemDropdownCtrl', [ '$scope', function($scope) {
// Find all planitems
var selectedShape = $scope.selectedShape;
if (selectedShape) {
// Go up in parent chain until plan model is found
var planModel;
var parent = selectedShape.parent;
if (parent) {
while (planModel === undefined && parent !== null && parent !== undefined) {
if (parent.resourceId !== null && parent.resourceId !== undefined && 'casePlanModel' === parent.resourceId) {
planModel = parent;
} else {
parent = parent.parent;
}
}
}
var planItems = [];
if (planModel !== null && planModel !== undefined) {
var toVisit = [];
for (var i=0; i<planModel.children.length; i++) {
toVisit.push(planModel.children[i]);
}
while (toVisit.length > 0) {
var child = toVisit.pop();
if (typeof child.getStencil === 'function'
&& (child.getStencil()._jsonStencil.groups.indexOf('Activities') >= 0 || (child.getStencil()._jsonStencil.title === 'Stage') )) {
planItems.push(child);
}
if (child.children !== null && child.children !== undefined) {
for (var i=0; i<child.children.length; i++) {
toVisit.push(child.children[i]);
}
}
}
}
var simplifiedPlanItems = [];
for (var i=0; i<planItems.length; i++) {
simplifiedPlanItems.push({ id: planItems[i].resourceId, name: planItems[i].properties.get('oryx-name') });
}
if (simplifiedPlanItems.length > 0) {
simplifiedPlanItems.sort(function(a,b) {
if(a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
});
}
$scope.planItems = simplifiedPlanItems;
}
if ($scope.property.value == undefined && $scope.property.value == null) {
$scope.property.value = '';
}
$scope.planItemChanged = function() {
$scope.updatePropertyInModel($scope.property);
};
}]);

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save