FormProps.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. 'use strict';
  2. var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
  3. getExtensionElements = require('../../../helper/ExtensionElementsHelper').getExtensionElements,
  4. removeEntry = require('../../../helper/ExtensionElementsHelper').removeEntry,
  5. extensionElements = require('./implementation/ExtensionElements'),
  6. properties = require('./implementation/Properties'),
  7. entryFactory = require('../../../factory/EntryFactory'),
  8. elementHelper = require('../../../helper/ElementHelper'),
  9. cmdHelper = require('../../../helper/CmdHelper'),
  10. formHelper = require('../../../helper/FormHelper'),
  11. utils = require('../../../Utils'),
  12. is = require('bpmn-js/lib/util/ModelUtil').is,
  13. find = require('lodash/find'),
  14. each = require('lodash/forEach');
  15. function generateValueId() {
  16. return utils.nextId('Value_');
  17. }
  18. /**
  19. * Generate a form field specific textField using entryFactory.
  20. *
  21. * @param {string} options.id
  22. * @param {string} options.label
  23. * @param {string} options.modelProperty
  24. * @param {function} options.validate
  25. *
  26. * @return {Object} an entryFactory.textField object
  27. */
  28. function formFieldTextField(options, getSelectedFormField) {
  29. var id = options.id,
  30. label = options.label,
  31. modelProperty = options.modelProperty,
  32. validate = options.validate;
  33. return entryFactory.textField({
  34. id: id,
  35. label: label,
  36. modelProperty: modelProperty,
  37. get: function(element, node) {
  38. var selectedFormField = getSelectedFormField(element, node) || {},
  39. values = {};
  40. values[modelProperty] = selectedFormField[modelProperty];
  41. return values;
  42. },
  43. set: function(element, values, node) {
  44. var commands = [];
  45. if (typeof options.set === 'function') {
  46. var cmd = options.set(element, values, node);
  47. if (cmd) {
  48. commands.push(cmd);
  49. }
  50. }
  51. var formField = getSelectedFormField(element, node),
  52. properties = {};
  53. properties[modelProperty] = values[modelProperty] || undefined;
  54. commands.push(cmdHelper.updateBusinessObject(element, formField, properties));
  55. return commands;
  56. },
  57. hidden: function(element, node) {
  58. return !getSelectedFormField(element, node);
  59. },
  60. validate: validate
  61. });
  62. }
  63. function ensureFormKeyAndDataSupported(element) {
  64. return (
  65. is(element, 'bpmn:StartEvent') && !is(element.parent, 'bpmn:SubProcess')
  66. ) || is(element, 'bpmn:UserTask');
  67. }
  68. module.exports = function(group, element, bpmnFactory, translate) {
  69. if (!ensureFormKeyAndDataSupported(element)) {
  70. return;
  71. }
  72. /**
  73. * Return the currently selected form field querying the form field select box
  74. * from the DOM.
  75. *
  76. * @param {djs.model.Base} element
  77. * @param {DOMElement} node - DOM element of any form field text input
  78. *
  79. * @return {ModdleElement} the currently selected form field
  80. */
  81. function getSelectedFormField(element, node) {
  82. var selected = formFieldsEntry.getSelected(element, node.parentNode);
  83. if (selected.idx === -1) {
  84. return;
  85. }
  86. return formHelper.getFormField(element, selected.idx);
  87. }
  88. // [FormKey] form key text input field
  89. group.entries.push(entryFactory.textField({
  90. id : 'form-key',
  91. label : translate('Form Key'),
  92. modelProperty: 'formKey',
  93. get: function(element, node) {
  94. var bo = getBusinessObject(element);
  95. return {
  96. formKey: bo.get('activiti:formKey')
  97. };
  98. },
  99. set: function(element, values, node) {
  100. var bo = getBusinessObject(element),
  101. formKey = values.formKey || undefined;
  102. return cmdHelper.updateBusinessObject(element, bo, { 'activiti:formKey': formKey });
  103. }
  104. }));
  105. // [FormData] form field select box
  106. var formFieldsEntry = extensionElements(element, bpmnFactory, {
  107. id: 'form-fields',
  108. label: translate('Form Fields'),
  109. modelProperty: 'id',
  110. prefix: 'FormProperty',
  111. createExtensionElement: function(element, extensionElements, value) {
  112. var bo = getBusinessObject(element), commands = [];
  113. if (!extensionElements) {
  114. extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
  115. commands.push(cmdHelper.updateProperties(element, { extensionElements: extensionElements }));
  116. }
  117. /* var formData = formHelper.getFormData(element);
  118. if (!formData) {
  119. formData = elementHelper.createElement('activiti:FormData', { fields: [] }, extensionElements, bpmnFactory);
  120. commands.push(cmdHelper.addAndRemoveElementsFromList(
  121. element,
  122. extensionElements,
  123. 'values',
  124. 'extensionElements',
  125. [formData],
  126. []
  127. ));
  128. }*/
  129. /**activiti 是向 extensionElements 下追加元素,而不是 formData 下,*/
  130. var field = elementHelper.createElement('activiti:FormProperty', { id: value }, extensionElements, bpmnFactory);
  131. if (typeof extensionElements.values !== 'undefined') {
  132. commands.push(cmdHelper.addElementsTolist(element, extensionElements, 'values', [ field ]));
  133. } else {
  134. commands.push(cmdHelper.updateBusinessObject(element, extensionElements, {
  135. values: [ field ]
  136. }));
  137. }
  138. return commands;
  139. },
  140. removeExtensionElement: function(element, extensionElements, value, idx) {
  141. var fields = formHelper.getFormFields(element);
  142. var entry = fields[idx],
  143. commands = [];
  144. if (fields.length < 2) {
  145. commands.push(removeEntry(getBusinessObject(element), element, extensionElements));
  146. } else {
  147. commands.push(cmdHelper.removeElementsFromList(element, extensionElements, 'values', null, [entry]));
  148. /* if (entry.id === formData.get('businessKey')) {
  149. commands.push(cmdHelper.updateBusinessObject(element, extensionElements, { 'businessKey': undefined }));
  150. }*/
  151. }
  152. return commands;
  153. },
  154. getExtensionElements: function(element) {
  155. return formHelper.getFormFields(element);
  156. },
  157. hideExtensionElements: function(element, node) {
  158. return false;
  159. }
  160. });
  161. group.entries.push(formFieldsEntry);
  162. // [FormData] Form Field label
  163. group.entries.push(entryFactory.label({
  164. id: 'form-field-header',
  165. labelText: translate('Form Field'),
  166. showLabel: function(element, node) {
  167. return !!getSelectedFormField(element, node);
  168. }
  169. }));
  170. // [FormData] form field id text input field
  171. group.entries.push(entryFactory.validationAwareTextField({
  172. id: 'form-field-id',
  173. label: translate('ID'),
  174. modelProperty: 'id',
  175. getProperty: function(element, node) {
  176. var selectedFormField = getSelectedFormField(element, node) || {};
  177. return selectedFormField.id;
  178. },
  179. setProperty: function(element, properties, node) {
  180. var formField = getSelectedFormField(element, node);
  181. return cmdHelper.updateBusinessObject(element, formField, properties);
  182. },
  183. hidden: function(element, node) {
  184. return !getSelectedFormField(element, node);
  185. },
  186. validate: function(element, values, node) {
  187. var formField = getSelectedFormField(element, node);
  188. if (formField) {
  189. var idValue = values.id;
  190. if (!idValue || idValue.trim() === '') {
  191. return { id: 'Form field id must not be empty' };
  192. }
  193. var formFields = formHelper.getFormFields(element);
  194. var existingFormField = find(formFields, function(f) {
  195. return f !== formField && f.id === idValue;
  196. });
  197. if (existingFormField) {
  198. return { id: 'Form field id already used in form data.' };
  199. }
  200. }
  201. }
  202. }));
  203. // [FormData] form field type combo box
  204. group.entries.push(entryFactory.comboBox({
  205. id: 'form-field-type',
  206. label: translate('Type'),
  207. selectOptions: [
  208. { name: 'string', value: 'string' },
  209. { name: 'long', value: 'long' },
  210. { name: 'boolean', value: 'boolean' },
  211. { name: 'date', value: 'date' },
  212. { name: 'enum', value: 'enum' }
  213. ],
  214. modelProperty: 'type',
  215. emptyParameter: true,
  216. get: function(element, node) {
  217. var selectedFormField = getSelectedFormField(element, node);
  218. if (selectedFormField) {
  219. return { type: selectedFormField.type };
  220. } else {
  221. return {};
  222. }
  223. },
  224. set: function(element, values, node) {
  225. var selectedFormField = getSelectedFormField(element, node),
  226. commands = [];
  227. if (selectedFormField.type === 'enum' && values.type !== 'enum') {
  228. // delete activiti:value objects from formField.values when switching from type enum
  229. commands.push(cmdHelper.updateBusinessObject(element, selectedFormField, { values: undefined }));
  230. }
  231. commands.push(cmdHelper.updateBusinessObject(element, selectedFormField, values));
  232. return commands;
  233. },
  234. hidden: function(element, node) {
  235. return !getSelectedFormField(element, node);
  236. }
  237. }));
  238. // [FormData] form field label text input field
  239. group.entries.push(formFieldTextField({
  240. id: 'form-field-label',
  241. label: translate('Label'),
  242. modelProperty: 'label'
  243. }, getSelectedFormField));
  244. // [FormData] form field defaultValue text input field
  245. group.entries.push(formFieldTextField({
  246. id: 'form-field-defaultValue',
  247. label: translate('Default Value'),
  248. modelProperty: 'defaultValue'
  249. }, getSelectedFormField));
  250. // [FormData] form field enum values label
  251. group.entries.push(entryFactory.label({
  252. id: 'form-field-enum-values-header',
  253. labelText: translate('Values'),
  254. divider: true,
  255. showLabel: function(element, node) {
  256. var selectedFormField = getSelectedFormField(element, node);
  257. return selectedFormField && selectedFormField.type === 'enum';
  258. }
  259. }));
  260. // [FormData] form field enum values table
  261. group.entries.push(entryFactory.table({
  262. id: 'form-field-enum-values',
  263. labels: [ translate('Id'), translate('Name') ],
  264. modelProperties: [ 'id', 'name' ],
  265. addLabel:translate('Add Value'),
  266. show: function(element, node) {
  267. var selectedFormField = getSelectedFormField(element, node);
  268. return selectedFormField && selectedFormField.type === 'enum';
  269. },
  270. getElements: function(element, node) {
  271. var selectedFormField = getSelectedFormField(element, node);
  272. return formHelper.getEnumValues(selectedFormField);
  273. },
  274. addElement: function(element, node) {
  275. var selectedFormField = getSelectedFormField(element, node),
  276. id = generateValueId();
  277. var enumValue = elementHelper.createElement(
  278. 'activiti:Value',
  279. { id: id, name: undefined },
  280. getBusinessObject(element),
  281. bpmnFactory
  282. );
  283. return cmdHelper.addElementsTolist(element, selectedFormField, 'values', [enumValue]);
  284. },
  285. removeElement: function(element, node, idx) {
  286. var selectedFormField = getSelectedFormField(element, node),
  287. enumValue = selectedFormField.values[idx];
  288. return cmdHelper.removeElementsFromList(element, selectedFormField, 'values', null, [enumValue]);
  289. },
  290. updateElement: function(element, value, node, idx) {
  291. var selectedFormField = getSelectedFormField(element, node),
  292. enumValue = selectedFormField.values[idx];
  293. value.name = value.name || undefined;
  294. return cmdHelper.updateBusinessObject(element, enumValue, value);
  295. },
  296. validate: function(element, value, node, idx) {
  297. var selectedFormField = getSelectedFormField(element, node),
  298. enumValue = selectedFormField.values[idx];
  299. if (enumValue) {
  300. // check if id is valid
  301. var validationError = utils.isIdValid(enumValue, value.id, translate);
  302. if (validationError) {
  303. return { id: validationError };
  304. }
  305. }
  306. }
  307. }));
  308. // [FormData] Validation label
  309. group.entries.push(entryFactory.label({
  310. id: 'form-field-validation-header',
  311. labelText: translate('Validation'),
  312. divider: true,
  313. showLabel: function(element, node) {
  314. return !!getSelectedFormField(element, node);
  315. }
  316. }));
  317. // [FormData] form field constraints table
  318. group.entries.push(entryFactory.table({
  319. id: 'constraints-list',
  320. modelProperties: [ 'name', 'config' ],
  321. labels: [ translate('Name'), translate('Config') ],
  322. addLabel: translate('Add Constraint'),
  323. getElements: function(element, node) {
  324. var formField = getSelectedFormField(element, node);
  325. return formHelper.getConstraints(formField);
  326. },
  327. addElement: function(element, node) {
  328. var commands = [],
  329. formField = getSelectedFormField(element, node),
  330. validation = formField.validation;
  331. if (!validation) {
  332. // create validation business object and add it to form data, if it doesn't exist
  333. validation = elementHelper.createElement('activiti:Validation', {}, getBusinessObject(element), bpmnFactory);
  334. commands.push(cmdHelper.updateBusinessObject(element, formField, { 'validation': validation }));
  335. }
  336. var newConstraint = elementHelper.createElement(
  337. 'activiti:Constraint',
  338. { name: undefined, config: undefined },
  339. validation,
  340. bpmnFactory
  341. );
  342. commands.push(cmdHelper.addElementsTolist(element, validation, 'constraints', [ newConstraint ]));
  343. return commands;
  344. },
  345. updateElement: function(element, value, node, idx) {
  346. var formField = getSelectedFormField(element, node),
  347. constraint = formHelper.getConstraints(formField)[idx];
  348. value.name = value.name || undefined;
  349. value.config = value.config || undefined;
  350. return cmdHelper.updateBusinessObject(element, constraint, value);
  351. },
  352. removeElement: function(element, node, idx) {
  353. var commands = [],
  354. formField = getSelectedFormField(element, node),
  355. constraints = formHelper.getConstraints(formField),
  356. currentConstraint = constraints[idx];
  357. commands.push(cmdHelper.removeElementsFromList(
  358. element,
  359. formField.validation,
  360. 'constraints',
  361. null,
  362. [ currentConstraint ]
  363. ));
  364. if (constraints.length === 1) {
  365. // remove activiti:validation if the last existing constraint has been removed
  366. commands.push(cmdHelper.updateBusinessObject(element, formField, { validation: undefined }));
  367. }
  368. return commands;
  369. },
  370. show: function(element, node) {
  371. return !!getSelectedFormField(element, node);
  372. }
  373. }));
  374. // [FormData] Properties label
  375. group.entries.push(entryFactory.label({
  376. id: 'form-field-properties-header',
  377. labelText: translate('Properties'),
  378. divider: true,
  379. showLabel: function(element, node) {
  380. return !!getSelectedFormField(element, node);
  381. }
  382. }));
  383. // [FormData] activiti:properties table
  384. group.entries.push(properties(element, bpmnFactory, {
  385. id: 'form-field-properties',
  386. modelProperties: [ 'id', 'value' ],
  387. labels: [ translate('Id'), translate('Value') ],
  388. getParent: function(element, node) {
  389. return getSelectedFormField(element, node);
  390. },
  391. show: function(element, node) {
  392. return !!getSelectedFormField(element, node);
  393. }
  394. }, translate));
  395. };