@processmaker/screen-builder 3.0.1 → 3.0.3

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 (31) hide show
  1. package/dist/vue-form-builder.css +1 -1
  2. package/dist/vue-form-builder.es.js +6134 -5704
  3. package/dist/vue-form-builder.es.js.map +1 -1
  4. package/dist/vue-form-builder.umd.js +51 -51
  5. package/dist/vue-form-builder.umd.js.map +1 -1
  6. package/package.json +3 -3
  7. package/src/assets/Shape.svg +3 -0
  8. package/src/assets/pencil-square.svg +3 -0
  9. package/src/components/ScreenTemplateCard.vue +128 -74
  10. package/src/components/ScreenTemplates.vue +138 -110
  11. package/src/components/accordions.js +1 -1
  12. package/src/components/editor/loop.vue +26 -0
  13. package/src/components/editor/multi-column.vue +26 -0
  14. package/src/components/inspector/collection-data-source.vue +3 -1
  15. package/src/components/inspector/collection-designer-mode.vue +73 -0
  16. package/src/components/inspector/color-select-modern.vue +101 -0
  17. package/src/components/inspector/encrypted-config.vue +1 -1
  18. package/src/components/inspector/index.js +3 -0
  19. package/src/components/renderer/file-upload.vue +60 -13
  20. package/src/components/renderer/form-collection-record-control.vue +5 -4
  21. package/src/components/renderer/form-collection-view-control.vue +2 -2
  22. package/src/components/renderer/form-masked-input.vue +7 -5
  23. package/src/components/renderer/form-record-list.vue +200 -23
  24. package/src/components/sortable/tableStyles.scss +42 -0
  25. package/src/components/task.vue +82 -38
  26. package/src/components/vue-form-builder.vue +84 -7
  27. package/src/form-builder-controls.js +14 -2
  28. package/src/form-control-common-properties.js +115 -2
  29. package/src/main.js +8 -0
  30. package/src/mixins/Clipboard.js +15 -5
  31. package/src/mixins/HasColorProperty.js +5 -0
@@ -1,32 +1,29 @@
1
1
  <template>
2
- <div
3
- class="screen-templates-container"
4
- data-cy="screen-templates-section"
5
- >
2
+ <div class="screen-templates-container" data-cy="screen-templates-section">
6
3
  <div class="d-flex justify-content-between">
7
4
  <h6 class="pt-2">{{ $t("Select a Template") }}</h6>
8
5
  <button
9
6
  class="panel-close-btn"
10
- @click="$emit('close-templates-panel')"
11
7
  data-cy="close-templates-section"
8
+ @click="$emit('close-templates-panel')"
12
9
  >
13
10
  <i class="fas fa-times"></i>
14
11
  </button>
15
12
  </div>
16
13
  <div class="d-flex template-tabs justify-content-center">
17
14
  <b-button
18
- @click="showMyTemplates"
19
15
  class="d-inline default-template-btn px-1"
20
16
  :class="{ 'my-templates-selected': myTemplatesSelected }"
21
17
  data-cy="my-templates-tab"
18
+ @click="showMyTemplates"
22
19
  >
23
20
  {{ $t("My Templates") }}
24
21
  </b-button>
25
22
  <b-button
26
- @click="showSharedTemplates"
27
23
  class="d-inline default-template-btn"
28
24
  :class="{ 'shared-templates-selected': sharedTemplatesSelected }"
29
25
  data-cy="shared-templates-tab"
26
+ @click="showSharedTemplates"
30
27
  >
31
28
  {{ $t("Shared Templates") }}
32
29
  </b-button>
@@ -38,6 +35,9 @@
38
35
  data-cy="my-templates-list"
39
36
  >
40
37
  <b-card-group>
38
+ <b-card-body v-if="loading" class="d-flex justify-content-center">
39
+ <b-spinner variant="primary" label="Spinning"></b-spinner>
40
+ </b-card-body>
41
41
  <b-card-body
42
42
  v-if="noMyTemplatesFound"
43
43
  class="p-2 h-100 overflow-auto"
@@ -45,12 +45,14 @@
45
45
  <h5>{{ $t("No templates found.") }}</h5>
46
46
  </b-card-body>
47
47
  <screen-template-card
48
- v-else
49
48
  v-for="template in myTemplatesData"
49
+ v-else
50
50
  :key="template.id"
51
51
  :template="template"
52
52
  :screen-id="screenId"
53
- :currentScreenPage="currentScreenPage"
53
+ :current-screen-page="currentScreenPage"
54
+ :active-template-id="activeTemplateId"
55
+ @toggle-active="setActiveTemplate"
54
56
  />
55
57
  </b-card-group>
56
58
  </div>
@@ -60,6 +62,9 @@
60
62
  data-cy="shared-templates-list"
61
63
  >
62
64
  <b-card-group>
65
+ <b-card-body v-if="loading" class="d-flex justify-content-center">
66
+ <b-spinner variant="primary" label="Spinning"></b-spinner>
67
+ </b-card-body>
63
68
  <b-card-body
64
69
  v-if="noSharedTemplatesFound"
65
70
  class="p-2 h-100 overflow-auto"
@@ -67,96 +72,116 @@
67
72
  <h5>{{ $t("No templates found.") }}</h5>
68
73
  </b-card-body>
69
74
  <screen-template-card
70
- v-else
71
75
  v-for="template in sharedTemplatesData"
76
+ v-else
72
77
  :key="template.id"
73
78
  :template="template"
74
79
  :screen-id="screenId"
75
- :currentScreenPage="currentScreenPage"
80
+ :current-screen-page="currentScreenPage"
81
+ :active-template-id="activeTemplateId"
82
+ @toggle-active="setActiveTemplate"
76
83
  />
77
84
  </b-card-group>
78
85
  </div>
79
86
  </div>
80
87
  </div>
81
88
  </template>
82
-
89
+
83
90
  <script>
84
- import ScreenTemplateCard from './ScreenTemplateCard.vue';
91
+ import ScreenTemplateCard from "./ScreenTemplateCard.vue";
85
92
 
86
- export default {
87
- components: {
88
- ScreenTemplateCard,
93
+ export default {
94
+ components: {
95
+ ScreenTemplateCard
96
+ },
97
+ props: {
98
+ screenId: {
99
+ type: Number,
100
+ required: true
101
+ },
102
+ currentScreenPage: {
103
+ type: Number,
104
+ default: 0
89
105
  },
90
- props: {
91
- screenId: {
92
- type: Number,
93
- required: true,
94
- },
95
- currentScreenPage: {
96
- type: Number,
97
- default: 0,
98
- },
99
- screenType: {
100
- type: String,
101
- default: 'FORM',
102
- }
106
+ screenType: {
107
+ type: String,
108
+ default: "FORM"
109
+ }
110
+ },
111
+ data() {
112
+ return {
113
+ myTemplatesData: null,
114
+ sharedTemplatesData: null,
115
+ myTemplatesSelected: true,
116
+ sharedTemplatesSelected: false,
117
+ noMyTemplatesFound: false,
118
+ noSharedTemplatesFound: false,
119
+ activeTemplateId: null,
120
+ loading: false
121
+ };
122
+ },
123
+ mounted() {
124
+ this.showMyTemplates();
125
+ },
126
+ methods: {
127
+ setActiveTemplate(id) {
128
+ // If the same template that is already active is clicked, it deactivates it.
129
+ this.activeTemplateId = this.activeTemplateId === id ? null : id;
103
130
  },
104
- data() {
105
- return {
106
- myTemplatesData: null,
107
- sharedTemplatesData: null,
108
- myTemplatesSelected: true,
109
- sharedTemplatesSelected: false,
110
- noMyTemplatesFound: false,
111
- noSharedTemplatesFound: false,
112
- };
131
+ showMyTemplates() {
132
+ this.myTemplatesSelected = true;
133
+ this.sharedTemplatesSelected = false;
134
+ this.activeTemplateId = null;
135
+ this.fetchMyTemplates();
113
136
  },
114
- methods: {
115
- showMyTemplates() {
116
- this.myTemplatesSelected = true;
117
- this.sharedTemplatesSelected = false;
118
- this.fetchMyTemplates();
119
- },
120
- fetchMyTemplates() {
121
- ProcessMaker.apiClient
122
- .get(
123
- `templates/screen?is_public=0&screen_type=${this.screenType}`,
124
- )
137
+ fetchMyTemplates() {
138
+ this.loading = true;
139
+ ProcessMaker.apiClient
140
+ .get(`templates/screen?is_public=0&screen_type=${this.screenType}`)
125
141
  .then((response) => {
126
142
  this.myTemplatesData = response.data.data;
127
- if (this.myTemplatesData.length === 0 || this.myTemplatesData === undefined) {
143
+ if (
144
+ this.myTemplatesData.length === 0 ||
145
+ this.myTemplatesData === undefined
146
+ ) {
128
147
  this.noMyTemplatesFound = true;
129
148
  }
130
149
  })
131
150
  .catch((error) => {
132
151
  console.error(error);
152
+ })
153
+ .finally(() => {
154
+ this.loading = false;
133
155
  });
134
- },
135
- fetchSharedTemplates() {
156
+ },
157
+ fetchSharedTemplates() {
158
+ this.loading = true;
136
159
  ProcessMaker.apiClient
137
- .get(
138
- `templates/screen?is_public=1&screen_type=${this.screenType}`,
139
- )
160
+ .get(`templates/screen?is_public=1&screen_type=${this.screenType}`)
140
161
  .then((response) => {
141
162
  this.sharedTemplatesData = response.data.data;
142
- if (this.sharedTemplatesData.length === 0 || this.sharedTemplatesData === undefined) {
163
+ if (
164
+ this.sharedTemplatesData.length === 0 ||
165
+ this.sharedTemplatesData === undefined
166
+ ) {
143
167
  this.noSharedTemplatesFound = true;
144
168
  }
145
169
  })
146
170
  .catch((error) => {
147
171
  console.error(error);
172
+ })
173
+ .finally(() => {
174
+ this.loading = false;
148
175
  });
149
- },
150
- showSharedTemplates() {
151
- this.myTemplatesSelected = false;
152
- this.sharedTemplatesSelected = true;
153
- this.fetchSharedTemplates();
154
- },
155
176
  },
156
- mounted() {
157
- this.showMyTemplates();
177
+ showSharedTemplates() {
178
+ this.myTemplatesSelected = false;
179
+ this.sharedTemplatesSelected = true;
180
+ this.activeTemplateId = null;
181
+ this.fetchSharedTemplates();
158
182
  }
159
- };
183
+ }
184
+ };
160
185
  </script>
161
186
 
162
187
  <style lang="scss" scoped>
@@ -164,53 +189,56 @@
164
189
  height: 100%;
165
190
  }
166
191
 
167
- .panel-close-btn {
168
- background-color: transparent;
169
- border: none;
170
- color: #596372;
171
- }
172
-
173
- .template-tabs {
174
- padding: 4px;
175
- background-color: #E9ECF1;
176
- border-radius: 8px;
177
- margin-top: 0.5rem;
178
- margin-bottom: 0.5rem;
179
- }
192
+ .panel-close-btn {
193
+ background-color: transparent;
194
+ border: none;
195
+ color: #596372;
196
+ }
180
197
 
181
- .default-template-btn {
182
- width: 50%;
183
- background-color: transparent;
184
- border: none;
185
- color: #596372;
186
- font-size: 12px;
187
- padding-left: 0px;
188
- padding-right: 0px;
189
- text-transform: none;
190
- }
198
+ .template-tabs {
199
+ padding: 4px;
200
+ background-color: #e9ecf1;
201
+ border-radius: 8px;
202
+ margin-top: 0.5rem;
203
+ margin-bottom: 0.5rem;
204
+ }
191
205
 
192
- .my-templates-selected {
193
- background-color: #ffffff;
194
- color: #20242A;
195
- border-radius: 8px;
196
- border: none;
197
- font-weight: 600;
198
- font-size: 12px;
199
- padding-left: 0px;
200
- padding-right: 0px;
201
- box-shadow: 0px 3px 6px -3px rgb(0, 0, 0, 0.05), 0px 2px 4px -2px rgba(0, 0, 0, 0.05), 0px 1px 2px -1px rgb(0, 0, 0, 0.05), 0px 1px 0px -1px rgb(0, 0, 0, 0.05);
202
- }
206
+ .default-template-btn {
207
+ width: 50%;
208
+ background-color: transparent;
209
+ border: none;
210
+ color: #596372;
211
+ font-size: 12px;
212
+ padding-left: 0px;
213
+ padding-right: 0px;
214
+ text-transform: none;
215
+ }
203
216
 
204
- .shared-templates-selected {
205
- background-color: #ffffff;
206
- color: #20242A;
207
- border-radius: 8px;
208
- border: none;
209
- font-weight: 600;
210
- font-size: 12px;
211
- padding-left: 0px;
212
- padding-right: 0px;
213
- box-shadow: 0px 3px 6px -3px rgb(0, 0, 0, 0.05), 0px 2px 4px -2px rgba(0, 0, 0, 0.05), 0px 1px 2px -1px rgb(0, 0, 0, 0.05), 0px 1px 0px -1px rgb(0, 0, 0, 0.05);
214
- }
217
+ .my-templates-selected {
218
+ background-color: #ffffff;
219
+ color: #20242a;
220
+ border-radius: 8px;
221
+ border: none;
222
+ font-weight: 600;
223
+ font-size: 12px;
224
+ padding-left: 0px;
225
+ padding-right: 0px;
226
+ box-shadow: 0px 3px 6px -3px rgb(0, 0, 0, 0.05),
227
+ 0px 2px 4px -2px rgba(0, 0, 0, 0.05), 0px 1px 2px -1px rgb(0, 0, 0, 0.05),
228
+ 0px 1px 0px -1px rgb(0, 0, 0, 0.05);
229
+ }
215
230
 
231
+ .shared-templates-selected {
232
+ background-color: #ffffff;
233
+ color: #20242a;
234
+ border-radius: 8px;
235
+ border: none;
236
+ font-weight: 600;
237
+ font-size: 12px;
238
+ padding-left: 0px;
239
+ padding-right: 0px;
240
+ box-shadow: 0px 3px 6px -3px rgb(0, 0, 0, 0.05),
241
+ 0px 2px 4px -2px rgba(0, 0, 0, 0.05), 0px 1px 2px -1px rgb(0, 0, 0, 0.05),
242
+ 0px 1px 0px -1px rgb(0, 0, 0, 0.05);
243
+ }
216
244
  </style>
@@ -58,7 +58,7 @@ export default [
58
58
  },
59
59
  {
60
60
  name: 'Design',
61
- fields: ['color', 'bgcolor', 'variant', 'toggle', 'height', 'width'],
61
+ fields: ['color', 'bgcolor', 'variant', 'toggle', 'height', 'width', 'designerMode', 'bgcolormodern'],
62
62
  open: false,
63
63
  },
64
64
  {
@@ -27,6 +27,15 @@
27
27
  class="mr-2 ml-1"
28
28
  />
29
29
  {{ element.config.name || $t("Variable Name") }}
30
+ <b-badge
31
+ v-if="isInClipboard(items[index])"
32
+ data-cy="copied-badge"
33
+ class="m-2 custom-badge"
34
+ pill
35
+ >
36
+ <i class="far fa-check-circle"></i>
37
+ <span class="pl-2">{{ $t('Copied')}}</span>
38
+ </b-badge>
30
39
  <div class="ml-auto">
31
40
  <clipboard-button
32
41
  :index="index"
@@ -91,6 +100,15 @@
91
100
  class="mr-2 ml-1"
92
101
  />
93
102
  {{ element.config.name || $t("Variable Name") }}
103
+ <b-badge
104
+ v-if="isInClipboard(items[index])"
105
+ data-cy="copied-badge"
106
+ class="m-2 custom-badge"
107
+ pill
108
+ >
109
+ <i class="far fa-check-circle"></i>
110
+ <span class="pl-2">{{ $t('Copied')}}</span>
111
+ </b-badge>
94
112
  <div class="ml-auto">
95
113
  <clipboard-button
96
114
  :index="index"
@@ -334,4 +352,12 @@ export default {
334
352
  box-shadow: 0 0 0 13px rgba(0, 0, 0, 0);
335
353
  }
336
354
  }
355
+ .custom-badge {
356
+ background-color: #D1F4D7 !important;
357
+ color: #06723A !important;
358
+ padding: 0.5rem 0.75rem;
359
+ border-radius: 8px;
360
+ font-weight: 500;
361
+ font-size: 14px;
362
+ }
337
363
  </style>
@@ -42,6 +42,15 @@
42
42
  class="mr-2 ml-1"
43
43
  />
44
44
  {{ element.config.name || $t("Variable Name") }}
45
+ <b-badge
46
+ v-if="isInClipboard(element)"
47
+ data-cy="copied-badge"
48
+ class="m-2 custom-badge"
49
+ pill
50
+ >
51
+ <i class="far fa-check-circle"></i>
52
+ <span class="pl-2">{{ $t('Copied')}}</span>
53
+ </b-badge>
45
54
  <div class="ml-auto">
46
55
  <clipboard-button
47
56
  :index="index"
@@ -108,6 +117,15 @@
108
117
  class="mr-2 ml-1"
109
118
  />
110
119
  {{ element.config.name || $t("Variable Name") }}
120
+ <b-badge
121
+ v-if="isInClipboard(element)"
122
+ data-cy="copied-badge"
123
+ class="m-2 custom-badge"
124
+ pill
125
+ >
126
+ <i class="far fa-check-circle"></i>
127
+ <span class="pl-2">{{ $t('Copied')}}</span>
128
+ </b-badge>
111
129
  <div class="ml-auto">
112
130
  <clipboard-button
113
131
  :index="index"
@@ -375,4 +393,12 @@ export default {
375
393
  box-shadow: 0 0 0 13px rgba(0, 0, 0, 0);
376
394
  }
377
395
  }
396
+ .custom-badge {
397
+ background-color: #D1F4D7 !important;
398
+ color: #06723A !important;
399
+ padding: 0.5rem 0.75rem;
400
+ border-radius: 8px;
401
+ font-weight: 500;
402
+ font-size: 14px;
403
+ }
378
404
  </style>
@@ -73,7 +73,6 @@
73
73
  "variableStore",
74
74
  "dataSelectionOptions",
75
75
  "singleField"
76
-
77
76
  ];
78
77
  export default {
79
78
  components: {
@@ -195,6 +194,9 @@
195
194
  },
196
195
  deep: true
197
196
  },
197
+ dataSelectionOptions() {
198
+ this.singleField = null;
199
+ }
198
200
  },
199
201
  };
200
202
  </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div>
3
+ <div>
4
+ <label for="collectiondesigner">{{ $t("Table Style") }}</label>
5
+ <b-form-select
6
+ id="collectiondesigner"
7
+ v-model="designerOptions"
8
+ :options="designerListOptions"
9
+ data-cy="inspector-collection-designer-model"
10
+ />
11
+ </div>
12
+ </div>
13
+ </template>
14
+ <script>
15
+
16
+ import { cloneDeep } from "lodash";
17
+
18
+ const CONFIG_FIELDS = [
19
+ "designerOptions"
20
+ ];
21
+ export default {
22
+ props: ["value", "screenType"],
23
+ data() {
24
+ return {
25
+ fields: [],
26
+ designerOptions: "Classic",
27
+ designerListOptions: [
28
+ {
29
+ text: this.$t('Classic'),
30
+ value: 'Classic',
31
+ },
32
+ {
33
+ text: this.$t('Modern'),
34
+ value: 'Modern',
35
+ },
36
+ ],
37
+ };
38
+ },
39
+ mounted () {
40
+ this.callBuilder(this.designerOptions);
41
+ },
42
+ computed: {
43
+ options() {
44
+ return Object.fromEntries(
45
+ CONFIG_FIELDS.map((field) => [field, this[field]])
46
+ );
47
+ }
48
+ },
49
+ watch: {
50
+ value: {
51
+ handler(value) {
52
+ if (!value) {
53
+ return;
54
+ }
55
+ CONFIG_FIELDS.forEach((field) => (this[field] = value[field]));
56
+ },
57
+ immediate: true
58
+ },
59
+ options: {
60
+ handler() {
61
+ this.$emit("input", this.options);
62
+ this.callBuilder(this.options.designerOptions);
63
+ },
64
+ deep: true
65
+ },
66
+ },
67
+ methods: {
68
+ callBuilder(option) {
69
+ this.$root.$emit("style-mode", option);
70
+ }
71
+ }
72
+ };
73
+ </script>
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <div class="form-group">
3
+ <div>
4
+ <b-button-toolbar>
5
+ <b-button-group size="lg">
6
+ <b-button
7
+ v-for="option in options"
8
+ :key="option.value"
9
+ size="sm"
10
+ variant="outline-light"
11
+ class="color-option"
12
+ :class="['bg-' + parsedColor(option.value)]"
13
+ :title="option.content"
14
+ >
15
+ <i
16
+ class="fas fa-check"
17
+ :class="[
18
+ option.value === value
19
+ ? 'text-light'
20
+ : 'text-' + parsedColor(option.value)
21
+ ]"
22
+ @click="selectColor(option.value)"
23
+ />
24
+ </b-button>
25
+ </b-button-group>
26
+ </b-button-toolbar>
27
+ </div>
28
+ </div>
29
+ </template>
30
+
31
+ <script>
32
+ export default {
33
+ components: {},
34
+ props: {
35
+ /**
36
+ * The label for the color select
37
+ */
38
+ label: {},
39
+ /**
40
+ * The value of the color select. eg. `alert alert-success`
41
+ */
42
+ value: {},
43
+ /**
44
+ * The helper text for the color select (not visible yet)
45
+ */
46
+ helper: {},
47
+ /**
48
+ * The options for the color select
49
+ */
50
+ options: {},
51
+ },
52
+ data() {
53
+ return {
54
+ newColor: ""
55
+ };
56
+ },
57
+ computed: {
58
+ hasColor() {
59
+ return Boolean(this.value);
60
+ }
61
+ },
62
+ methods: {
63
+ emitChanges(value) {
64
+ this.$emit("input", value);
65
+ this.$emit("update-state");
66
+ },
67
+ checkColor() {
68
+ if (this.hasColor) {
69
+ this.emitChanges("");
70
+ }
71
+ },
72
+ selectColor(color) {
73
+ this.emitChanges(color);
74
+ },
75
+ parsedColor(color) {
76
+ return color.split("-")[1];
77
+ }
78
+ }
79
+ };
80
+ </script>
81
+
82
+ <style lang="scss" scoped>
83
+ .image-preview {
84
+ border: 1px solid #ced4da;
85
+ border-radius: 4px;
86
+ height: 4em;
87
+ text-align: center;
88
+ overflow: hidden;
89
+ }
90
+ .color-option {
91
+ left: -8px;
92
+ border-radius: 4px;
93
+ width: 48px;
94
+ height: 48px;
95
+ margin-right: 15px;
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ position: relative;
100
+ }
101
+ </style>
@@ -13,7 +13,7 @@
13
13
  <div v-if="settings.encrypted">
14
14
  <select-user-group
15
15
  :key="componentKey"
16
- :label="$t('Users/Groups to View')"
16
+ :label="$t('Users/Groups to View Encrypted Fields')"
17
17
  v-model="settings.assignments"
18
18
  :multiple="true"
19
19
  @input="emitChanges"
@@ -2,7 +2,10 @@ export { default as CollectionSelectList } from "./collection-select-list.vue";
2
2
  export { default as CollectionRecordsList } from "./collection-records-list.vue";
3
3
  export { default as collectionDataSource } from "./collection-data-source.vue";
4
4
  export { default as CollectionDisplayMode } from "./collection-display-mode.vue";
5
+ export { default as CollectionDesignerMode } from "./collection-designer-mode.vue";
5
6
  export { default as ColorSelect } from "./color-select.vue";
7
+ export { default as ColorSelectRecord } from "./color-select.vue";
8
+ export { default as ColorSelectModern } from "./color-select-modern.vue";
6
9
  export { default as ColumnSetup } from "./column-setup.vue";
7
10
  export { default as ContainerColumns } from "./container-columns.vue";
8
11
  export { default as DataMapping } from "./data-mapping.vue";