@processmaker/screen-builder 2.99.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/vue-form-builder.css +1 -1
  2. package/dist/vue-form-builder.es.js +9091 -7132
  3. package/dist/vue-form-builder.es.js.map +1 -1
  4. package/dist/vue-form-builder.umd.js +53 -53
  5. package/dist/vue-form-builder.umd.js.map +1 -1
  6. package/package.json +2 -1
  7. package/src/App.vue +14 -2
  8. package/src/DataProvider.js +42 -1
  9. package/src/VariableDataTypeProperties.js +1 -1
  10. package/src/components/ClipboardButton.vue +77 -0
  11. package/src/components/CssIcon.vue +21 -0
  12. package/src/components/ScreenTemplateCard.vue +257 -0
  13. package/src/components/ScreenTemplates.vue +216 -0
  14. package/src/components/ScreenToolbar.vue +24 -2
  15. package/src/components/SelectUserGroup.vue +274 -0
  16. package/src/components/TabsBar.vue +47 -1
  17. package/src/components/accordions.js +7 -1
  18. package/src/components/editor/loop.vue +22 -1
  19. package/src/components/editor/multi-column.vue +22 -2
  20. package/src/components/editor/pagesDropdown.vue +20 -2
  21. package/src/components/index.js +7 -1
  22. package/src/components/inspector/collection-data-source.vue +200 -0
  23. package/src/components/inspector/collection-display-mode.vue +87 -0
  24. package/src/components/inspector/collection-records-list.vue +156 -0
  25. package/src/components/inspector/column-setup.vue +123 -7
  26. package/src/components/inspector/encrypted-config.vue +78 -0
  27. package/src/components/inspector/index.js +4 -0
  28. package/src/components/inspector/page-select.vue +1 -0
  29. package/src/components/renderer/file-upload.vue +136 -3
  30. package/src/components/renderer/form-collection-record-control.vue +248 -0
  31. package/src/components/renderer/form-collection-view-control.vue +236 -0
  32. package/src/components/renderer/form-masked-input.vue +194 -9
  33. package/src/components/renderer/form-record-list.vue +271 -69
  34. package/src/components/renderer/index.js +2 -0
  35. package/src/components/screen-renderer.vue +2 -0
  36. package/src/components/task.vue +2 -1
  37. package/src/components/vue-form-builder.vue +156 -22
  38. package/src/components/vue-form-renderer.vue +10 -2
  39. package/src/form-builder-controls.js +168 -21
  40. package/src/global-properties.js +8 -0
  41. package/src/main.js +60 -1
  42. package/src/mixins/Clipboard.js +153 -0
  43. package/src/mixins/ScreenBase.js +7 -1
  44. package/src/mixins/index.js +1 -0
  45. package/src/store/modules/ClipboardManager.js +79 -0
  46. package/src/store/modules/clipboardModule.js +210 -0
  47. package/src/stories/ClipboardButton.stories.js +66 -0
  48. package/src/stories/PagesDropdown.stories.js +11 -8
@@ -0,0 +1,200 @@
1
+ <template>
2
+ <div>
3
+ <div>
4
+ <label for="collectionsource">{{ $t("Source of Record List") }}</label>
5
+ <b-form-select
6
+ id="collectionsource"
7
+ v-model="sourceOptions"
8
+ :options="sourceDisplayOptions"
9
+ data-cy="inspector-collection-data-source"
10
+ @change="displayOptionChange"
11
+ />
12
+ <small class="mt-3 form-text text-muted">{{
13
+ $t("A record list can display the data of a defined variable or a collection")
14
+ }}</small>
15
+ </div>
16
+ <div class="mt-2" v-if="sourceOptions === 'Collection'">
17
+
18
+ <CollectionRecordsList
19
+ v-model="collectionFields"
20
+ :record-pmql="pmql"
21
+ @change="collectionChanged"/>
22
+
23
+ <pmql-input
24
+ v-model="pmql"
25
+ :search-type="'collections_w_mustaches'"
26
+ class="mt-3 mb-1"
27
+ data-cy="inspector-collection-pmql"
28
+ :input-label="'PMQL'"
29
+ :condensed="true"
30
+ :ai-enabled="true"
31
+ :placeholder="$t('PMQL')"
32
+ >
33
+ </pmql-input>
34
+ <small class="mt-3 form-text text-muted">{{
35
+ $t("Leave this field empty to show all the records of the collection")
36
+ }}</small>
37
+ <label class="mt-3" id="data-selection">{{ $t("Data Selection") }}</label>
38
+
39
+ <b-form-select
40
+ id="data-selection"
41
+ v-model="dataSelectionOptions"
42
+ :options="dataSelectionDisplayOptions"
43
+ data-cy="inspector-collection-data-selection"
44
+ />
45
+ <small class="mt-3 form-text text-muted">{{
46
+ $t("The user can select specific data to be stored into a variable")
47
+ }}</small>
48
+
49
+ <div class="mt-3" v-if="dataSelectionOptions === 'single-field'">
50
+ <label id="single-columns">{{ $t('Column') }}</label>
51
+ <b-form-select
52
+ id="single-columns"
53
+ v-model="singleField"
54
+ :options="singleFieldOptions"
55
+ data-cy="inspector-collection-single-field"
56
+ >
57
+ <option disabled value="">{{ $t("Select a column") }}</option>
58
+ </b-form-select>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </template>
63
+ <script>
64
+
65
+ import CollectionRecordsList from "./collection-records-list.vue"
66
+ import { cloneDeep } from "lodash";
67
+
68
+ const CONFIG_FIELDS = [
69
+ "collectionFields",
70
+ "collectionFieldsColumns",
71
+ "pmql",
72
+ "sourceOptions",
73
+ "variableStore",
74
+ "dataSelectionOptions",
75
+ "singleField"
76
+
77
+ ];
78
+ export default {
79
+ components: {
80
+ CollectionRecordsList
81
+ },
82
+ props: ["value", "screenType"],
83
+ data() {
84
+ return {
85
+ fields: [],
86
+ sourceOptions: "Variable",
87
+ submitCollectionCheck: true,
88
+ sourceDisplayOptions: [],
89
+ collectionFields: [],
90
+ collectionFieldsColumns: [],
91
+ variableStore: null,
92
+ pmql: null,
93
+ sourceDisplayOptions: [
94
+ {
95
+ text: this.$t('Variable'),
96
+ value: 'Variable',
97
+ },
98
+ {
99
+ text: this.$t('Collection'),
100
+ value: 'Collection',
101
+ },
102
+ ],
103
+ dataSelectionDisplayOptions: [
104
+ {
105
+ text: this.$t('Do not allow selection'),
106
+ value: 'no-selection',
107
+ },
108
+ {
109
+ text: this.$t('Single field of record'),
110
+ value: 'single-field',
111
+ },
112
+ {
113
+ text: this.$t('Single record'),
114
+ value: 'single-record',
115
+ },
116
+ {
117
+ text: this.$t('Multiple records'),
118
+ value: 'multiple-records',
119
+ },
120
+ ],
121
+ dataSelectionOptions: "no-selection",
122
+ collectionColumns: [],
123
+ singleFieldOptions: [],
124
+ singleField: null
125
+ };
126
+ },
127
+ methods: {
128
+ displayOptionChange() {
129
+ this.collectionFields = [];
130
+ this.collectionFieldsColumns = [];
131
+ this.pmql = null;
132
+ this.$root.$emit("collection-changed", true);
133
+ },
134
+ collectionChanged(data) {
135
+ if (Array.isArray(data)) {
136
+ const [firstItem] = data;
137
+ const collectionId = firstItem?.collection_id;
138
+ if(collectionId !== this.collectionFields.collectionId) {
139
+ this.$root.$emit("collection-changed", true);
140
+ }
141
+ }
142
+ },
143
+ getCollectionColumns(records) {
144
+ const [firstRecord] = records?.dataRecordList || [];
145
+
146
+ if (firstRecord?.data) {
147
+ const dataObject = firstRecord.data;
148
+
149
+ for (const [key, value] of Object.entries(dataObject)) {
150
+ this.singleFieldOptions.push({ text: key, value: key });
151
+ }
152
+ }
153
+ },
154
+ },
155
+ computed: {
156
+ options() {
157
+ return Object.fromEntries(
158
+ CONFIG_FIELDS.map((field) => [field, this[field]])
159
+ );
160
+ }
161
+ },
162
+ watch: {
163
+ value: {
164
+ handler(value) {
165
+ if (!value) {
166
+ return;
167
+ }
168
+ CONFIG_FIELDS.forEach((field) => (this[field] = value[field]));
169
+ },
170
+ immediate: true
171
+ },
172
+ sourceOptions: {
173
+ handler(changeOption) {
174
+ this.$root.$emit("record-list-option", changeOption);
175
+ }
176
+ },
177
+ collectionFields: {
178
+ handler(collectionFieldsData) {
179
+ this.getCollectionColumns(collectionFieldsData);
180
+ this.$root.$emit("record-list-collection", collectionFieldsData);
181
+ },
182
+ deep: true
183
+ },
184
+ pmql: {
185
+ handler(newPmql) {
186
+ this.$root.$emit("change-pmql", newPmql);
187
+ }
188
+ },
189
+ submitCollectionCheck(newValue) {
190
+ this.submitCollectionCheck = newValue;
191
+ },
192
+ options: {
193
+ handler() {
194
+ this.$emit("input", this.options);
195
+ },
196
+ deep: true
197
+ },
198
+ },
199
+ };
200
+ </script>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <div>
3
+ <div>
4
+ <label for="collectionmode">{{ $t("Mode") }}</label>
5
+ <b-form-select
6
+ id="collectionmode"
7
+ v-model="modeId"
8
+ :options="displayOptions"
9
+ data-cy="inspector-collection"
10
+ />
11
+ </div>
12
+ <div class="mt-2" v-if="modeId !== 'View'">
13
+ <b-form-checkbox v-model="submitCollectionCheck">
14
+ {{ $t("Update collection on submit") }}
15
+ </b-form-checkbox>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import ScreenVariableSelector from "../screen-variable-selector.vue";
22
+
23
+ const CONFIG_FIELDS = ["modeId", "submitCollectionCheck"];
24
+ export default {
25
+ components: {
26
+ ScreenVariableSelector
27
+ },
28
+ props: ["value", "screenType"],
29
+ data() {
30
+ return {
31
+ fields: [],
32
+ modeId: null,
33
+ submitCollectionCheck: true,
34
+ displayOptions: []
35
+ };
36
+ },
37
+ mounted() {
38
+ this.getFields();
39
+ },
40
+ computed: {
41
+ options() {
42
+ return Object.fromEntries(
43
+ CONFIG_FIELDS.map((field) => [field, this[field]])
44
+ );
45
+ }
46
+ },
47
+ watch: {
48
+ value: {
49
+ handler(value) {
50
+ if (!value) {
51
+ return;
52
+ }
53
+ CONFIG_FIELDS.forEach((field) => (this[field] = value[field]));
54
+ },
55
+ immediate: true
56
+ },
57
+ modeId: {
58
+ handler() {
59
+ this.getFields();
60
+ }
61
+ },
62
+ submitCollectionCheck(newValue) {
63
+ this.submitCollectionCheck = newValue;
64
+ },
65
+ screenType: {
66
+ handler() {
67
+ this.getFields();
68
+ },
69
+ immediate: true
70
+ },
71
+ options: {
72
+ handler() {
73
+ this.$emit("input", this.options);
74
+ },
75
+ deep: true
76
+ }
77
+ },
78
+ methods: {
79
+ getFields() {
80
+ this.displayOptions = [
81
+ { value: "Edit", text: "Edit" },
82
+ { value: "View", text: "View" }
83
+ ];
84
+ }
85
+ }
86
+ };
87
+ </script>
@@ -0,0 +1,156 @@
1
+ <template>
2
+ <div>
3
+ <div>
4
+ <label for="collection">{{ $t("Collection") }}</label>
5
+ <b-form-select
6
+ id="collection"
7
+ v-model="collectionId"
8
+ :options="collections"
9
+ data-cy="inspector-collection"
10
+ />
11
+ </div>
12
+ <div v-if="collectionId > 0" class="screen-link mt-2">
13
+ <a
14
+ :href="`/designer/screen-builder/${
15
+ screenMode === 'display' ? idCollectionScreenView : idCollectionScreenEdit
16
+ }/edit`"
17
+ target="_blank">
18
+ {{ $t(screenMode === 'display' ? "Open View Screen" : "Open Edit Screen") }}
19
+ <i class="ml-1 fas fa-external-link-alt" />
20
+ </a>
21
+ </div>
22
+ </div>
23
+ </template>
24
+
25
+ <script>
26
+ import { debounce } from "lodash";
27
+ import MustacheHelper from "./mustache-helper.vue";
28
+ import ScreenVariableSelector from "../screen-variable-selector.vue";
29
+
30
+ const CONFIG_FIELDS = [
31
+ "collectionId",
32
+ "pmql",
33
+ "dataRecordList"
34
+ ];
35
+
36
+ export default {
37
+ components: {
38
+ MustacheHelper,
39
+ ScreenVariableSelector
40
+ },
41
+ props: ["value"],
42
+ data() {
43
+ return {
44
+ collections: [],
45
+ fields: [],
46
+ collectionId: null,
47
+ pmql: "",
48
+ unique: false,
49
+ dataRecordList: [],
50
+ idCollectionScreenView: null,
51
+ idCollectionScreenEdit: null,
52
+ screenMode: null
53
+ };
54
+ },
55
+ computed: {
56
+ options() {
57
+ return Object.fromEntries(
58
+ CONFIG_FIELDS.map((field) => [field, this[field]])
59
+ );
60
+ }
61
+ },
62
+ watch: {
63
+ value: {
64
+ handler(value) {
65
+ if (!value) {
66
+ return;
67
+ }
68
+ CONFIG_FIELDS.forEach((field) => (this[field] = value[field]));
69
+ },
70
+ immediate: true
71
+ },
72
+ collectionId: {
73
+ handler() {
74
+ this.getFields();
75
+ }
76
+ },
77
+ options: {
78
+ handler() {
79
+ this.$emit("input", this.options);
80
+ },
81
+ deep: true
82
+ }
83
+ },
84
+ created() {
85
+ this.onDebouncedPmqlChange = debounce((pmql) => {
86
+ this.onPmqlChange(pmql);
87
+ }, 1000);
88
+ },
89
+ mounted() {
90
+ this.$root.$on("change-pmql", (val) => {
91
+ this.pmql = val;
92
+ });
93
+ this.getCollections();
94
+ if (this.collectionId) {
95
+ this.getFields();
96
+ }
97
+ this.$root.$on("collection-screen-mode", (mode) => {
98
+ this.screenMode = mode;
99
+ });
100
+ },
101
+ methods: {
102
+ onCollectionChange() {
103
+ this.$dataProvider
104
+ .getCollectionRecordsList(this.collectionId)
105
+ .then((response) => {
106
+ this.dataRecordList = response.data;
107
+ });
108
+ this.$emit('change', this.dataRecordList);
109
+ },
110
+ getCollections() {
111
+ this.$dataProvider.getCollections().then((response) => {
112
+ const [firstItem = {}] = response.data.data || [];
113
+ this.idCollectionScreenView = firstItem.read_screen_id;
114
+ this.idCollectionScreenEdit = firstItem.create_screen_id;
115
+ this.collections = [
116
+ { value: null, text: this.$t("Select a collection") },
117
+ ...response.data.data.map((collection) => {
118
+ return {
119
+ text: collection.name,
120
+ value: collection.id
121
+ };
122
+ })
123
+ ];
124
+ });
125
+ },
126
+ getFields() {
127
+ if (!this.collectionId) {
128
+ return;
129
+ }
130
+
131
+ this.$dataProvider
132
+ .getCollectionFields(this.collectionId)
133
+ .then((response) => {
134
+ this.fields = [
135
+ { value: null, text: this.$t("Select a field") },
136
+ { value: "id", text: this.$t("Collection Record ID") },
137
+ ...response.data.data.map((field) => {
138
+ return {
139
+ text: field.label,
140
+ value: field.field
141
+ };
142
+ })
143
+ ];
144
+
145
+ this.onCollectionChange();
146
+ });
147
+ },
148
+ onNLQConversion(pmql) {
149
+ this.pmql = pmql;
150
+ },
151
+ onPmqlChange(pmql) {
152
+ this.pmql = pmql;
153
+ }
154
+ }
155
+ };
156
+ </script>
@@ -17,7 +17,7 @@
17
17
  <div v-else class="card-header">
18
18
  {{ $t('Edit Column') }}
19
19
  </div>
20
- <div class="card-body p-2">
20
+ <div v-if="!isCollection" class="card-body p-2">
21
21
  <label class="mt-3" for="option-content">{{ $t('Column Header') }}</label>
22
22
  <b-form-input id="option-content" v-model="optionContent"/>
23
23
  <label for="option-value">{{ $t('Value') }}</label>
@@ -26,12 +26,27 @@
26
26
  <div>{{ optionError }}</div>
27
27
  </div>
28
28
  </div>
29
+ <div v-else class="card-body p-2">
30
+ <label class="mt-3" for="option-content">{{ $t('Column') }}</label>
31
+ <b-form-select
32
+ id="columnCollection"
33
+ v-model="optionValueCollection"
34
+ :options="collectionOptions"
35
+ data-cy="inspector-collection-columns"
36
+ @change="handleColumnSelection"
37
+ />
38
+ <label v-show="!hideLabelAll" for="option-label-column">{{ $t('Column Label') }}</label>
39
+ <b-form-input v-show="!hideLabelAll" id="option-label-column" v-model="optionContentCollection" :classs="optionKeyClass" />
40
+ <div v-if="optionError" class="invalid-feedback d-block text-right">
41
+ <div>{{ optionError }}</div>
42
+ </div>
43
+ </div>
29
44
 
30
45
  <div class="card-footer text-right p-2">
31
46
  <button type="button" class="btn btn-sm btn-outline-secondary mr-2" @click="showOptionCard=false">
32
47
  {{ $t('Cancel') }}
33
48
  </button>
34
- <button type="button" class="btn btn-sm btn-secondary" @click="addOption()">
49
+ <button type="button" class="btn btn-sm btn-secondary" @click="isCollection ? addOptionCollection() : addOption()">
35
50
  {{ $t('Save') }}
36
51
  </button>
37
52
  </div>
@@ -65,7 +80,7 @@
65
80
  <div v-else class="card-header">
66
81
  {{ $t('Edit Option') }}
67
82
  </div>
68
- <div class="card-body p-2">
83
+ <div v-if="!isCollection" class="card-body p-2">
69
84
  <label class="mt-3" for="option-content">{{ $t('Column Header') }}</label>
70
85
  <b-form-input id="option-content" v-model="optionContent"/>
71
86
  <label for="option-value">{{ $t('Value') }}</label>
@@ -74,12 +89,26 @@
74
89
  <div>{{ optionError }}</div>
75
90
  </div>
76
91
  </div>
92
+ <div v-else class="card-body p-2">
93
+ <label class="mt-3" for="option-content-collection">{{ $t('Column') }}</label>
94
+ <b-form-select
95
+ id="columnCollection"
96
+ v-model="optionValueCollection"
97
+ :options="collectionOptions"
98
+ data-cy="inspector-collection-columns"
99
+ />
100
+ <label for="option-value-collection">{{ $t('Column Label') }}</label>
101
+ <b-form-input id="option-value-collection" v-model="optionContentCollection" :classs="optionKeyClass" />
102
+ <div v-if="optionError" class="invalid-feedback d-block text-right">
103
+ <div>{{ optionError }}</div>
104
+ </div>
105
+ </div>
77
106
 
78
107
  <div class="card-footer text-right p-2">
79
108
  <button type="button" class="btn btn-sm btn-outline-secondary mr-2" @click="editIndex=null">
80
109
  {{ $t('Cancel') }}
81
110
  </button>
82
- <button type="button" class="btn btn-sm btn-secondary" @click="addOption()">
111
+ <button type="button" class="btn btn-sm btn-secondary" @click="isCollection ? addOptionCollection() : addOption()">
83
112
  {{ $t('Update') }}
84
113
  </button>
85
114
  </div>
@@ -186,6 +215,7 @@
186
215
  import draggable from 'vuedraggable';
187
216
  import { dataSources, dataSourceValues } from './data-source-types';
188
217
  import MonacoEditor from 'vue-monaco';
218
+ import { cloneDeep } from "lodash";
189
219
 
190
220
  export default {
191
221
  components: {
@@ -219,6 +249,8 @@ export default {
219
249
  removeIndex: null,
220
250
  optionValue: '',
221
251
  optionContent: '',
252
+ optionValueCollection: '',
253
+ optionContentCollection: '',
222
254
  showRenderAs: false,
223
255
  renderAs: 'dropdown',
224
256
  allowMultiSelect: false,
@@ -242,6 +274,9 @@ export default {
242
274
  automaticLayout: true,
243
275
  },
244
276
  showPopup: false,
277
+ isCollection: null,
278
+ collectionOptions: [],
279
+ hideLabelAll: false
245
280
  };
246
281
  },
247
282
  watch: {
@@ -284,6 +319,9 @@ export default {
284
319
  keyField() {
285
320
  return this.key || 'value';
286
321
  },
322
+ keyFieldCollection() {
323
+ return this.key || 'key';
324
+ },
287
325
  valueField() {
288
326
  return this.value || 'content';
289
327
  },
@@ -321,8 +359,53 @@ export default {
321
359
  },
322
360
  mounted() {
323
361
  this.initData();
362
+ this.$root.$on("record-list-option", (val) => {
363
+ this.$nextTick(()=>{
364
+ this.isCollection = (val === "Collection") ? true : false;
365
+ });
366
+
367
+ });
368
+ this.$root.$on("record-list-collection", (collectionData) => {
369
+ this.getCollectionColumns(collectionData);
370
+ });
371
+ this.$root.$on("collection-changed", (change) => {
372
+ if(change) {
373
+ this.optionsList = [];
374
+ }
375
+ });
376
+ this.$root.$on("option-source-changed", (change) => {
377
+ if(change) {
378
+ this.optionsList = [];
379
+ }
380
+ });
324
381
  },
325
382
  methods: {
383
+ handleColumnSelection() {
384
+ if (this.optionValueCollection === "all") {
385
+ this.optionsList = [];
386
+ this.hideLabelAll = true;
387
+ this.collectionOptions.forEach(option => {
388
+ if(option.value !== "all") {
389
+ this.optionsList.push({
390
+ content: option.value,
391
+ key: option.value
392
+ });
393
+ }
394
+ });
395
+ }
396
+ },
397
+ getCollectionColumns(collection) {
398
+ this.collectionOptions = [{ text: "All columns", value: "all" }];
399
+ const [firstRecord] = collection?.dataRecordList || [];
400
+
401
+ if (firstRecord?.data) {
402
+ const dataObject = firstRecord.data;
403
+
404
+ for (const [key, value] of Object.entries(dataObject)) {
405
+ this.collectionOptions.push({ text: key, value: key });
406
+ }
407
+ }
408
+ },
326
409
  initData() {
327
410
  this.dataSource = this.options.dataSource;
328
411
  this.jsonData = this.options.jsonData;
@@ -391,12 +474,16 @@ export default {
391
474
  this.editIndex = index;
392
475
  this.optionContent = this.optionsList[index][this.valueField];
393
476
  this.optionValue = this.optionsList[index][this.keyField];
477
+ this.optionContentCollection = this.optionsList[index][this.keyFieldCollection];
478
+ this.optionValueCollection = this.optionsList[index][this.valueField];
394
479
  this.optionError = '';
395
480
  },
396
481
  showAddOption() {
397
482
  this.optionCardType = 'insert';
398
483
  this.optionContent = '';
399
484
  this.optionValue = '';
485
+ this.optionContentCollection = '';
486
+ this.optionValueCollection = '';
400
487
  this.showOptionCard = true;
401
488
  this.optionError = '';
402
489
  this.editIndex = null;
@@ -412,6 +499,7 @@ export default {
412
499
  this.optionError = 'An item with the same key already exists';
413
500
  return;
414
501
  }
502
+
415
503
  this.optionsList.push(
416
504
  {
417
505
  [this.valueField]: this.optionContent,
@@ -420,7 +508,7 @@ export default {
420
508
  );
421
509
  }
422
510
  else {
423
- if (this.optionsList.find((item, index) => { return item[that.keyField] === this.optionValue && index !== this.editIndex ; })) {
511
+ if (this.optionsList.find((item, index) => { return item[that.keyField] === this.optionValue && index !== this.editIndex; })) {
424
512
  this.optionError = 'An item with the same key already exists';
425
513
  return;
426
514
  }
@@ -434,19 +522,47 @@ export default {
434
522
  this.optionError = '';
435
523
  this.editIndex = null;
436
524
  },
525
+ addOptionCollection() {
526
+ const that = this;
527
+ if (this.optionsList === undefined) {
528
+ this.initData();
529
+ }
530
+
531
+ if (this.optionCardType === 'insert') {
532
+ if (this.optionsList.find(item => { return item[that.keyFieldCollection] === this.optionContentCollection; })) {
533
+ this.optionError = 'An item with the same key already exists';
534
+ return;
535
+ }
536
+
537
+ this.optionsList.push(
538
+ {
539
+ [this.keyFieldCollection]: this.optionContentCollection,
540
+ [this.valueField]: this.optionValueCollection,
541
+ }
542
+ );
543
+ this.optionsList = this.optionsList.filter(option => option["content"] !== "all");
544
+ }
545
+ else {
546
+ this.optionsList[this.editIndex][this.keyFieldCollection] = this.optionContentCollection;
547
+ this.optionsList[this.editIndex][this.valueField] = this.optionValueCollection;
548
+ }
437
549
 
550
+ this.jsonError = '';
551
+ this.jsonData = JSON.stringify(this.optionsList);
552
+ this.showOptionCard = false;
553
+ this.optionError = '';
554
+ this.editIndex = null;
555
+ },
438
556
  deleteOption() {
439
557
  this.optionsList.splice(this.removeIndex, 1);
440
558
  this.jsonData = JSON.stringify(this.optionsList);
441
559
  this.showRemoveWarning = false;
442
560
  this.removeIndex = null;
443
561
  },
444
-
445
562
  removeOption(index) {
446
563
  this.removeIndex = index;
447
564
  this.showRemoveWarning = true;
448
565
  },
449
-
450
566
  expandEditor() {
451
567
  this.showPopup = true;
452
568
  },