@processmaker/screen-builder 2.83.11 → 2.84.1
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.
- package/dist/vue-form-builder.css +1 -1
- package/dist/vue-form-builder.es.js +4504 -4042
- package/dist/vue-form-builder.es.js.map +1 -1
- package/dist/vue-form-builder.umd.js +52 -52
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/package.json +18 -2
- package/src/App.vue +34 -56
- package/src/assets/css/custom.css +11 -0
- package/src/assets/css/tabs.css +118 -0
- package/src/bootstrap.js +111 -0
- package/src/components/ScreenToolbar.vue +100 -0
- package/src/components/TabsBar.vue +233 -0
- package/src/components/editor/pagesDropdown.vue +125 -0
- package/src/components/index.js +1 -0
- package/src/components/inspector/color-select.vue +18 -1
- package/src/components/sortable/Sortable.vue +80 -0
- package/src/components/sortable/sortable.scss +25 -0
- package/src/components/sortable/sortableList/SortableList.vue +141 -0
- package/src/components/sortable/sortableList/sortableList.scss +73 -0
- package/src/components/vue-form-builder.vue +342 -253
- package/src/main.js +1 -2
- package/src/mixins/canOpenJsonFile.js +1 -1
- package/src/stories/ColorSelect.stories.js +79 -0
- package/src/stories/Configure.mdx +78 -0
- package/src/stories/DropdownAndPages.stories.js +113 -0
- package/src/stories/PageTabs.stories.js +338 -0
- package/src/stories/PagesDropdown.stories.js +132 -0
- package/src/stories/ScreenToolbar.stories.js +188 -0
- package/src/stories/Sortable.stories.js +236 -0
|
@@ -98,231 +98,192 @@
|
|
|
98
98
|
<!-- Renderer -->
|
|
99
99
|
<b-col
|
|
100
100
|
id="screen-container"
|
|
101
|
-
|
|
101
|
+
ref="screen-container"
|
|
102
|
+
class="overflow-auto mh-100 p-0 d-flex flex-column position-relative"
|
|
102
103
|
>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
class="form-control"
|
|
108
|
-
data-cy="toolbar-page"
|
|
109
|
-
>
|
|
110
|
-
<option v-for="(data, page) in config" :key="page" :value="page">
|
|
111
|
-
{{ data.name }}
|
|
112
|
-
</option>
|
|
113
|
-
</b-form-select>
|
|
114
|
-
|
|
115
|
-
<div v-if="showToolbar">
|
|
116
|
-
<b-button
|
|
117
|
-
size="sm"
|
|
118
|
-
variant="secondary"
|
|
119
|
-
class="ml-1"
|
|
120
|
-
:title="$t('Edit Page Title')"
|
|
121
|
-
data-cy="toolbar-edit"
|
|
122
|
-
@click="openEditPageModal(currentPage)"
|
|
123
|
-
>
|
|
124
|
-
<i class="far fa-edit" />
|
|
125
|
-
</b-button>
|
|
126
|
-
|
|
127
|
-
<b-button
|
|
128
|
-
size="sm"
|
|
129
|
-
variant="danger"
|
|
130
|
-
class="ml-1"
|
|
131
|
-
:title="$t('Delete Page')"
|
|
132
|
-
:disabled="!displayDelete"
|
|
133
|
-
data-cy="toolbar-remove"
|
|
134
|
-
@click="confirmDelete()"
|
|
135
|
-
>
|
|
136
|
-
<i class="far fa-trash-alt" />
|
|
137
|
-
</b-button>
|
|
138
|
-
|
|
139
|
-
<b-button
|
|
140
|
-
v-b-modal.addPageModal
|
|
141
|
-
size="sm"
|
|
142
|
-
variant="secondary"
|
|
143
|
-
class="ml-1 mr-1"
|
|
144
|
-
:title="$t('Add New Page')"
|
|
145
|
-
data-cy="toolbar-add"
|
|
146
|
-
@click="originalPageName = null"
|
|
147
|
-
>
|
|
148
|
-
<i class="fas fa-plus" />
|
|
149
|
-
</b-button>
|
|
150
|
-
</div>
|
|
151
|
-
|
|
152
|
-
<b-button-group size="sm" class="ml-1 ml-auto">
|
|
153
|
-
<b-button :disabled="!canUndo" data-cy="toolbar-undo" @click="undo">{{
|
|
154
|
-
$t("Undo")
|
|
155
|
-
}}</b-button>
|
|
156
|
-
<b-button :disabled="!canRedo" data-cy="toolbar-redo" @click="redo">{{
|
|
157
|
-
$t("Redo")
|
|
158
|
-
}}</b-button>
|
|
159
|
-
</b-button-group>
|
|
160
|
-
|
|
161
|
-
<hr class="w-100" />
|
|
162
|
-
</b-input-group>
|
|
163
|
-
|
|
164
|
-
<div
|
|
165
|
-
v-if="isCurrentPageEmpty"
|
|
166
|
-
data-cy="screen-drop-zone"
|
|
167
|
-
class="d-flex justify-content-center align-items-center drag-placeholder text-center position-absolute rounded mt-4 flex-column"
|
|
104
|
+
<tabs-bar
|
|
105
|
+
ref="tabsBar"
|
|
106
|
+
:pages="config"
|
|
107
|
+
@tab-opened="currentPage = $event"
|
|
168
108
|
>
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
<path
|
|
177
|
-
d="M47.125 28.6562V0.5H5.71875C2.96523 0.5 0.75 2.71523 0.75 5.46875V101.531C0.75 104.285 2.96523 106.5 5.71875 106.5H75.2812C78.0348 106.5 80.25 104.285 80.25 101.531V33.625H52.0938C49.3609 33.625 47.125 31.3891 47.125 28.6562ZM60.375 77.5156C60.375 78.882 59.257 80 57.8906 80H23.1094C21.743 80 20.625 78.882 20.625 77.5156V75.8594C20.625 74.493 21.743 73.375 23.1094 73.375H57.8906C59.257 73.375 60.375 74.493 60.375 75.8594V77.5156ZM60.375 64.2656C60.375 65.632 59.257 66.75 57.8906 66.75H23.1094C21.743 66.75 20.625 65.632 20.625 64.2656V62.6094C20.625 61.243 21.743 60.125 23.1094 60.125H57.8906C59.257 60.125 60.375 61.243 60.375 62.6094V64.2656ZM60.375 49.3594V51.0156C60.375 52.382 59.257 53.5 57.8906 53.5H23.1094C21.743 53.5 20.625 52.382 20.625 51.0156V49.3594C20.625 47.993 21.743 46.875 23.1094 46.875H57.8906C59.257 46.875 60.375 47.993 60.375 49.3594ZM80.25 25.7371V27H53.75V0.5H55.0129C56.3379 0.5 57.6008 1.01758 58.5324 1.94922L78.8008 22.2383C79.7324 23.1699 80.25 24.4328 80.25 25.7371Z"
|
|
178
|
-
fill="#699CFF"
|
|
109
|
+
<template #tabs-start>
|
|
110
|
+
<pages-dropdown
|
|
111
|
+
v-if="showToolbar"
|
|
112
|
+
:data="sortedPages"
|
|
113
|
+
@addPage="$bvModal.show('addPageModal')"
|
|
114
|
+
@clickPage="onClick"
|
|
115
|
+
@seeAllPages="$bvModal.show('openSortable')"
|
|
179
116
|
/>
|
|
180
|
-
</
|
|
181
|
-
<
|
|
182
|
-
<p>
|
|
183
|
-
{{
|
|
184
|
-
$t(
|
|
185
|
-
"To begin creating a screen, drag and drop items from the Controls Menu on the left."
|
|
186
|
-
)
|
|
187
|
-
}}
|
|
188
|
-
</p>
|
|
189
|
-
<!-- {{ $t("Drag an element here") }} -->
|
|
190
|
-
</div>
|
|
191
|
-
|
|
192
|
-
<draggable
|
|
193
|
-
v-if="renderControls"
|
|
194
|
-
:key="editorContentKey"
|
|
195
|
-
data-cy="editor-content"
|
|
196
|
-
class="h-100"
|
|
197
|
-
ghost-class="form-control-ghost"
|
|
198
|
-
:value="config[currentPage].items"
|
|
199
|
-
v-bind="{
|
|
200
|
-
group: { name: 'controls' },
|
|
201
|
-
swapThreshold: 0.5
|
|
202
|
-
}"
|
|
203
|
-
@input="updateConfig"
|
|
204
|
-
>
|
|
205
|
-
<div
|
|
206
|
-
v-for="(element, index) in config[currentPage].items"
|
|
207
|
-
:key="index"
|
|
208
|
-
class="control-item mt-4 mb-4"
|
|
209
|
-
:class="{
|
|
210
|
-
selected: selected === element,
|
|
211
|
-
hasError: hasError(element)
|
|
212
|
-
}"
|
|
213
|
-
:selector="element.config.customCssSelector"
|
|
214
|
-
@click="inspect(element)"
|
|
215
|
-
>
|
|
117
|
+
</template>
|
|
118
|
+
<template #default="{ currentPage: tabPage }">
|
|
216
119
|
<div
|
|
217
|
-
v-if="
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
data-cy="screen-element-container"
|
|
221
|
-
@click="inspect(element)"
|
|
120
|
+
v-if="isCurrentPageEmpty(tabPage)"
|
|
121
|
+
data-cy="screen-drop-zone"
|
|
122
|
+
class="d-flex justify-content-center align-items-center drag-placeholder text-center position-absolute rounded mt-4 flex-column"
|
|
222
123
|
>
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
124
|
+
<svg
|
|
125
|
+
width="81"
|
|
126
|
+
height="107"
|
|
127
|
+
viewBox="0 0 81 107"
|
|
128
|
+
fill="none"
|
|
129
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
227
130
|
>
|
|
228
|
-
<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
:class="element.config.icon"
|
|
232
|
-
class="mr-2 ml-1"
|
|
131
|
+
<path
|
|
132
|
+
d="M47.125 28.6562V0.5H5.71875C2.96523 0.5 0.75 2.71523 0.75 5.46875V101.531C0.75 104.285 2.96523 106.5 5.71875 106.5H75.2812C78.0348 106.5 80.25 104.285 80.25 101.531V33.625H52.0938C49.3609 33.625 47.125 31.3891 47.125 28.6562ZM60.375 77.5156C60.375 78.882 59.257 80 57.8906 80H23.1094C21.743 80 20.625 78.882 20.625 77.5156V75.8594C20.625 74.493 21.743 73.375 23.1094 73.375H57.8906C59.257 73.375 60.375 74.493 60.375 75.8594V77.5156ZM60.375 64.2656C60.375 65.632 59.257 66.75 57.8906 66.75H23.1094C21.743 66.75 20.625 65.632 20.625 64.2656V62.6094C20.625 61.243 21.743 60.125 23.1094 60.125H57.8906C59.257 60.125 60.375 61.243 60.375 62.6094V64.2656ZM60.375 49.3594V51.0156C60.375 52.382 59.257 53.5 57.8906 53.5H23.1094C21.743 53.5 20.625 52.382 20.625 51.0156V49.3594C20.625 47.993 21.743 46.875 23.1094 46.875H57.8906C59.257 46.875 60.375 47.993 60.375 49.3594ZM80.25 25.7371V27H53.75V0.5H55.0129C56.3379 0.5 57.6008 1.01758 58.5324 1.94922L78.8008 22.2383C79.7324 23.1699 80.25 24.4328 80.25 25.7371Z"
|
|
133
|
+
fill="#699CFF"
|
|
233
134
|
/>
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
</button>
|
|
245
|
-
<button
|
|
246
|
-
v-if="!(isAiSection(element) && aiPreview(element))"
|
|
247
|
-
data-test="copy-control-btn"
|
|
248
|
-
class="btn btn-sm btn-secondary mr-2"
|
|
249
|
-
:title="$t('Copy Control')"
|
|
250
|
-
@click="duplicateItem(index)"
|
|
251
|
-
>
|
|
252
|
-
<i class="fas fa-copy text-light" />
|
|
253
|
-
</button>
|
|
254
|
-
<button
|
|
255
|
-
data-test="delete-control-btn"
|
|
256
|
-
class="btn btn-sm btn-danger"
|
|
257
|
-
:title="$t('Delete Control')"
|
|
258
|
-
@click="deleteItem(index)"
|
|
259
|
-
>
|
|
260
|
-
<i class="far fa-trash-alt text-light" />
|
|
261
|
-
</button>
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
<component
|
|
265
|
-
:is="element['editor-component']"
|
|
266
|
-
v-model="element.items"
|
|
267
|
-
:validation-errors="validationErrors"
|
|
268
|
-
class="card-body"
|
|
269
|
-
:class="elementCssClass(element)"
|
|
270
|
-
:selected="selected"
|
|
271
|
-
:config="element.config"
|
|
272
|
-
:ai-element="element"
|
|
273
|
-
@inspect="inspect"
|
|
274
|
-
@update-state="updateState"
|
|
275
|
-
/>
|
|
135
|
+
</svg>
|
|
136
|
+
<h3>{{ $t("Place your controls here.") }}</h3>
|
|
137
|
+
<p>
|
|
138
|
+
{{
|
|
139
|
+
$t(
|
|
140
|
+
"To begin creating a screen, drag and drop items from the Controls Menu on the left."
|
|
141
|
+
)
|
|
142
|
+
}}
|
|
143
|
+
</p>
|
|
144
|
+
<!-- {{ $t("Drag an element here") }} -->
|
|
276
145
|
</div>
|
|
277
146
|
|
|
278
|
-
<
|
|
147
|
+
<draggable
|
|
148
|
+
v-if="renderControls"
|
|
149
|
+
:key="editorContentKey"
|
|
150
|
+
data-cy="editor-content"
|
|
151
|
+
class="h-100"
|
|
152
|
+
ghost-class="form-control-ghost"
|
|
153
|
+
:value="config[tabPage].items"
|
|
154
|
+
v-bind="{
|
|
155
|
+
group: { name: 'controls' },
|
|
156
|
+
swapThreshold: 0.5
|
|
157
|
+
}"
|
|
158
|
+
@input="updateConfig"
|
|
159
|
+
>
|
|
279
160
|
<div
|
|
280
|
-
v-
|
|
281
|
-
|
|
161
|
+
v-for="(element, index) in config[tabPage].items"
|
|
162
|
+
:key="index"
|
|
163
|
+
class="control-item mt-4 mb-4"
|
|
164
|
+
:class="{
|
|
165
|
+
selected: selected === element,
|
|
166
|
+
hasError: hasError(element)
|
|
167
|
+
}"
|
|
168
|
+
:selector="element.config.customCssSelector"
|
|
169
|
+
@click="inspect(element)"
|
|
282
170
|
>
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
:class="element
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
class="
|
|
293
|
-
:
|
|
294
|
-
@click="duplicateItem(index)"
|
|
171
|
+
<div
|
|
172
|
+
v-if="element.container"
|
|
173
|
+
class="card container-lement"
|
|
174
|
+
:class="{ 'ai-section-card': isAiSection(element) }"
|
|
175
|
+
data-cy="screen-element-container"
|
|
176
|
+
@click="inspect(element)"
|
|
177
|
+
>
|
|
178
|
+
<div
|
|
179
|
+
v-if="selected === element"
|
|
180
|
+
class="card-header form-element-header d-flex align-items-center"
|
|
181
|
+
:class="{ pulse: isAiSection(element) && aiPreview(element) }"
|
|
295
182
|
>
|
|
296
|
-
<i class="fas fa-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
183
|
+
<i class="fas fa-arrows-alt-v mr-1 text-muted" />
|
|
184
|
+
<i
|
|
185
|
+
v-if="element.config.icon"
|
|
186
|
+
:class="element.config.icon"
|
|
187
|
+
class="mr-2 ml-1"
|
|
188
|
+
/>
|
|
189
|
+
{{ element.config.name || element.label || $t("Field Name") }}
|
|
190
|
+
<div class="ml-auto">
|
|
191
|
+
<button
|
|
192
|
+
v-if="isAiSection(element) && aiPreview(element)"
|
|
193
|
+
data-test="apply-ai-btn"
|
|
194
|
+
class="btn btn-sm btn-primary mr-2"
|
|
195
|
+
:title="$t('Apply Changes')"
|
|
196
|
+
@click="applyAiChanges(element)"
|
|
197
|
+
>
|
|
198
|
+
{{ $t("Apply Changes") }}
|
|
199
|
+
</button>
|
|
200
|
+
<button
|
|
201
|
+
v-if="!(isAiSection(element) && aiPreview(element))"
|
|
202
|
+
data-test="copy-control-btn"
|
|
203
|
+
class="btn btn-sm btn-secondary mr-2"
|
|
204
|
+
:title="$t('Copy Control')"
|
|
205
|
+
@click="duplicateItem(index)"
|
|
206
|
+
>
|
|
207
|
+
<i class="fas fa-copy text-light" />
|
|
208
|
+
</button>
|
|
209
|
+
<button
|
|
210
|
+
data-test="delete-control-btn"
|
|
211
|
+
class="btn btn-sm btn-danger"
|
|
212
|
+
:title="$t('Delete Control')"
|
|
213
|
+
@click="deleteItem(index)"
|
|
214
|
+
>
|
|
215
|
+
<i class="far fa-trash-alt text-light" />
|
|
216
|
+
</button>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
<component
|
|
220
|
+
:is="element['editor-component']"
|
|
221
|
+
v-model="element.items"
|
|
222
|
+
:validation-errors="validationErrors"
|
|
223
|
+
class="card-body"
|
|
224
|
+
:class="elementCssClass(element)"
|
|
225
|
+
:selected="selected"
|
|
226
|
+
:config="element.config"
|
|
227
|
+
:ai-element="element"
|
|
228
|
+
@inspect="inspect"
|
|
229
|
+
@update-state="updateState"
|
|
230
|
+
/>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<div v-else class="card" data-cy="screen-element-container">
|
|
234
|
+
<div
|
|
235
|
+
v-if="selected === element"
|
|
236
|
+
class="card-header form-element-header d-flex align-items-center"
|
|
302
237
|
>
|
|
303
|
-
<i class="
|
|
304
|
-
|
|
238
|
+
<i class="fas fa-arrows-alt-v mr-1 text-muted" />
|
|
239
|
+
<i
|
|
240
|
+
v-if="element.config.icon"
|
|
241
|
+
:class="element.config.icon"
|
|
242
|
+
class="mr-2 ml-1"
|
|
243
|
+
/>
|
|
244
|
+
{{ element.config.name || $t("Variable Name") }}
|
|
245
|
+
<div class="ml-auto">
|
|
246
|
+
<button
|
|
247
|
+
class="btn btn-sm btn-secondary mr-2"
|
|
248
|
+
:title="$t('Copy Control')"
|
|
249
|
+
@click="duplicateItem(index)"
|
|
250
|
+
>
|
|
251
|
+
<i class="fas fa-copy text-light" />
|
|
252
|
+
</button>
|
|
253
|
+
<button
|
|
254
|
+
class="btn btn-sm btn-danger"
|
|
255
|
+
:title="$t('Delete Control')"
|
|
256
|
+
@click="deleteItem(index)"
|
|
257
|
+
>
|
|
258
|
+
<i class="far fa-trash-alt text-light" />
|
|
259
|
+
</button>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
<component
|
|
263
|
+
v-bind="element.config"
|
|
264
|
+
:is="element['editor-component']"
|
|
265
|
+
:tabindex="element.config.interactive ? 0 : -1"
|
|
266
|
+
class="card-body m-0 pb-4 pt-4"
|
|
267
|
+
:class="[
|
|
268
|
+
elementCssClass(element),
|
|
269
|
+
{ 'prevent-interaction': !element.config.interactive }
|
|
270
|
+
]"
|
|
271
|
+
@input="
|
|
272
|
+
element.config.interactive
|
|
273
|
+
? (element.config.content = $event)
|
|
274
|
+
: null
|
|
275
|
+
"
|
|
276
|
+
@focusout.native="updateState"
|
|
277
|
+
/>
|
|
305
278
|
</div>
|
|
306
279
|
</div>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
class="card-body m-0 pb-4 pt-4"
|
|
312
|
-
:class="[
|
|
313
|
-
elementCssClass(element),
|
|
314
|
-
{ 'prevent-interaction': !element.config.interactive }
|
|
315
|
-
]"
|
|
316
|
-
@input="
|
|
317
|
-
element.config.interactive
|
|
318
|
-
? (element.config.content = $event)
|
|
319
|
-
: null
|
|
320
|
-
"
|
|
321
|
-
@focusout.native="updateState"
|
|
322
|
-
/>
|
|
280
|
+
</draggable>
|
|
281
|
+
|
|
282
|
+
<div v-if="!isCurrentPageEmpty(tabPage)" data-cy="screen-drop-zone">
|
|
283
|
+
|
|
323
284
|
</div>
|
|
324
|
-
</
|
|
325
|
-
</
|
|
285
|
+
</template>
|
|
286
|
+
</tabs-bar>
|
|
326
287
|
</b-col>
|
|
327
288
|
|
|
328
289
|
<!-- Inspector -->
|
|
@@ -396,27 +357,61 @@
|
|
|
396
357
|
</b-col>
|
|
397
358
|
|
|
398
359
|
<!-- Modals -->
|
|
360
|
+
<b-modal
|
|
361
|
+
id="openSortable"
|
|
362
|
+
ref="openSortable"
|
|
363
|
+
header-close-content="×"
|
|
364
|
+
role="dialog"
|
|
365
|
+
size="lg"
|
|
366
|
+
:title="$t('Edit Pages')"
|
|
367
|
+
:ok-title="$t('DONE')"
|
|
368
|
+
ok-only
|
|
369
|
+
ok-variant="secondary"
|
|
370
|
+
header-class = "modal-header-custom"
|
|
371
|
+
>
|
|
372
|
+
<template #modal-title>
|
|
373
|
+
<h5 class="modal-title">{{ $t('Edit Pages') }}</h5>
|
|
374
|
+
<span class="modal-subtitle">{{ $t('Change pages order and name') }}</span>
|
|
375
|
+
</template>
|
|
376
|
+
<template #modal-header-close="{ close }">
|
|
377
|
+
<button type="button" aria-label="Close" class="close" @click="close()">×</button>
|
|
378
|
+
</template>
|
|
379
|
+
<Sortable
|
|
380
|
+
:items="config"
|
|
381
|
+
filter-key="name"
|
|
382
|
+
@item-edit="() => {}"
|
|
383
|
+
@item-delete="confirmDelete"
|
|
384
|
+
@add-page="$bvModal.show('addPageModal')"
|
|
385
|
+
/>
|
|
386
|
+
</b-modal>
|
|
387
|
+
|
|
399
388
|
<b-modal
|
|
400
389
|
id="addPageModal"
|
|
401
|
-
|
|
402
|
-
|
|
390
|
+
ref="addPageModal"
|
|
391
|
+
header-class="pb-2"
|
|
392
|
+
size="lg"
|
|
393
|
+
:ok-title="$t('SAVE')"
|
|
394
|
+
:cancel-title="$t('CANCEL')"
|
|
403
395
|
cancel-variant="btn btn-outline-secondary"
|
|
404
396
|
ok-variant="btn btn-secondary ml-2"
|
|
405
|
-
:title="$t('Add New Page')"
|
|
406
397
|
header-close-content="×"
|
|
407
398
|
data-cy="add-page-modal"
|
|
399
|
+
:ok-disabled="!addPageName || !!checkPageName(addPageName)"
|
|
408
400
|
@ok="addPage"
|
|
401
|
+
@show="addPageName = ''; showAddPageValidations=false;"
|
|
409
402
|
>
|
|
410
|
-
<
|
|
403
|
+
<template #modal-title>
|
|
404
|
+
<h5 class="modal-title">{{ $t('Create New Page') }}</h5>
|
|
405
|
+
<small class="modal-subtitle mb-n2">{{ $t('Create a new page in your screen') }}</small>
|
|
406
|
+
</template>
|
|
411
407
|
<form-input
|
|
412
408
|
ref="addPageInput"
|
|
413
409
|
v-model="addPageName"
|
|
414
410
|
:name="$t('Page Name')"
|
|
415
411
|
:label="$t('Page Name') + ' *'"
|
|
416
412
|
:helper="$t('The name of the new page to add')"
|
|
417
|
-
|
|
413
|
+
:error="checkPageName(addPageName)"
|
|
418
414
|
data-cy="add-page-name"
|
|
419
|
-
required
|
|
420
415
|
aria-required="true"
|
|
421
416
|
/>
|
|
422
417
|
</b-modal>
|
|
@@ -438,7 +433,8 @@
|
|
|
438
433
|
:name="$t('Page Name')"
|
|
439
434
|
:label="$t('Page Name') + ' *'"
|
|
440
435
|
:helper="$t('The new name of the page')"
|
|
441
|
-
validation="
|
|
436
|
+
validation="required"
|
|
437
|
+
:error="checkPageName(editPageName)"
|
|
442
438
|
required
|
|
443
439
|
aria-required="true"
|
|
444
440
|
/>
|
|
@@ -481,11 +477,14 @@ import "@processmaker/vue-form-elements/dist/vue-form-elements.css";
|
|
|
481
477
|
import accordions from "./accordions";
|
|
482
478
|
import { keyNameProperty } from "../form-control-common-properties";
|
|
483
479
|
import VariableNameGenerator from "@/components/VariableNameGenerator";
|
|
480
|
+
import PagesDropdown from "@/components/editor/pagesDropdown";
|
|
484
481
|
import testing from "@/mixins/testing";
|
|
485
482
|
import defaultValueEditor from "./inspector/default-value-editor";
|
|
486
483
|
import RequiredCheckbox from "./utils/required-checkbox";
|
|
487
484
|
import MultipleUploadsCheckbox from "./utils/multiple-uploads-checkbox";
|
|
488
485
|
import { formTypes } from "@/global-properties";
|
|
486
|
+
import TabsBar from "./TabsBar.vue";
|
|
487
|
+
import Sortable from './sortable/Sortable.vue';
|
|
489
488
|
|
|
490
489
|
// To include another language in the Validator with variable processmaker
|
|
491
490
|
const globalObject = typeof window === "undefined" ? global : window;
|
|
@@ -537,6 +536,7 @@ const DEFAULT_GROUP = "Advanced";
|
|
|
537
536
|
|
|
538
537
|
export default {
|
|
539
538
|
components: {
|
|
539
|
+
TabsBar,
|
|
540
540
|
draggable,
|
|
541
541
|
FormInput,
|
|
542
542
|
FormSelectList,
|
|
@@ -549,7 +549,9 @@ export default {
|
|
|
549
549
|
MultipleUploadsCheckbox,
|
|
550
550
|
defaultValueEditor,
|
|
551
551
|
...inspector,
|
|
552
|
-
...renderer
|
|
552
|
+
...renderer,
|
|
553
|
+
PagesDropdown,
|
|
554
|
+
Sortable,
|
|
553
555
|
},
|
|
554
556
|
mixins: [HasColorProperty, testing],
|
|
555
557
|
props: {
|
|
@@ -588,6 +590,8 @@ export default {
|
|
|
588
590
|
}
|
|
589
591
|
|
|
590
592
|
return {
|
|
593
|
+
showAddPageValidations: false,
|
|
594
|
+
openedPages: [0],
|
|
591
595
|
currentPage: 0,
|
|
592
596
|
selected: null,
|
|
593
597
|
display: "editor",
|
|
@@ -616,19 +620,16 @@ export default {
|
|
|
616
620
|
editorContentKey: 0,
|
|
617
621
|
cancelledJobs: [],
|
|
618
622
|
collapse: {},
|
|
619
|
-
groupOrder: {}
|
|
623
|
+
groupOrder: {}
|
|
620
624
|
};
|
|
621
625
|
},
|
|
622
626
|
computed: {
|
|
627
|
+
sortedPages() {
|
|
628
|
+
return [...this.config].sort((a, b) => a.order - b.order);
|
|
629
|
+
},
|
|
623
630
|
builder() {
|
|
624
631
|
return this;
|
|
625
632
|
},
|
|
626
|
-
canUndo() {
|
|
627
|
-
return this.$store.getters["undoRedoModule/canUndo"];
|
|
628
|
-
},
|
|
629
|
-
canRedo() {
|
|
630
|
-
return this.$store.getters["undoRedoModule/canRedo"];
|
|
631
|
-
},
|
|
632
633
|
displayDelete() {
|
|
633
634
|
return this.config.length > 1;
|
|
634
635
|
},
|
|
@@ -685,9 +686,6 @@ export default {
|
|
|
685
686
|
|
|
686
687
|
return grouped;
|
|
687
688
|
},
|
|
688
|
-
isCurrentPageEmpty() {
|
|
689
|
-
return this.config[this.currentPage].items.length === 0;
|
|
690
|
-
},
|
|
691
689
|
showToolbar() {
|
|
692
690
|
return this.screenType === formTypes.form;
|
|
693
691
|
}
|
|
@@ -732,16 +730,6 @@ export default {
|
|
|
732
730
|
}
|
|
733
731
|
},
|
|
734
732
|
created() {
|
|
735
|
-
Validator.register(
|
|
736
|
-
"unique-page-name",
|
|
737
|
-
(value) => {
|
|
738
|
-
const pageNames = this.config
|
|
739
|
-
.map((config) => config.name)
|
|
740
|
-
.filter((name) => name !== this.originalPageName);
|
|
741
|
-
return !pageNames.includes(value);
|
|
742
|
-
},
|
|
743
|
-
this.$t("Must be unique")
|
|
744
|
-
);
|
|
745
733
|
this.$store.dispatch("undoRedoModule/pushState", {
|
|
746
734
|
config: JSON.stringify(this.config),
|
|
747
735
|
currentPage: this.currentPage
|
|
@@ -775,6 +763,24 @@ export default {
|
|
|
775
763
|
this.setGroupOrder(defaultGroupOrder);
|
|
776
764
|
},
|
|
777
765
|
methods: {
|
|
766
|
+
isCurrentPageEmpty(currentPage) {
|
|
767
|
+
return this.config[currentPage]?.items?.length === 0;
|
|
768
|
+
},
|
|
769
|
+
onClick(page) {
|
|
770
|
+
this.$refs.tabsBar.openPageByIndex(this.config.indexOf(page));
|
|
771
|
+
},
|
|
772
|
+
checkPageName(value, force = false) {
|
|
773
|
+
if (!force && !this.showAddPageValidations) {
|
|
774
|
+
return null;
|
|
775
|
+
}
|
|
776
|
+
if (!value.trim()) {
|
|
777
|
+
return this.$t("The Page Name field is required.");
|
|
778
|
+
}
|
|
779
|
+
const pageNames = this.config
|
|
780
|
+
.map((config) => config.name)
|
|
781
|
+
.filter((name) => name !== this.originalPageName);
|
|
782
|
+
return pageNames.includes(value) ? this.$t("Must be unique.") : "";
|
|
783
|
+
},
|
|
778
784
|
getGroupOrder(groupName) {
|
|
779
785
|
let order = _.get(this.groupOrder, groupName, Number.POSITIVE_INFINITY);
|
|
780
786
|
return order;
|
|
@@ -878,6 +884,10 @@ export default {
|
|
|
878
884
|
config.forEach((page) =>
|
|
879
885
|
this.removeDataVariableFromNestedScreens(page.items)
|
|
880
886
|
);
|
|
887
|
+
// add order attribute
|
|
888
|
+
config.forEach((page, index) => {
|
|
889
|
+
page.order = page.order || index + 1;
|
|
890
|
+
});
|
|
881
891
|
},
|
|
882
892
|
updateFieldNameValidation(items) {
|
|
883
893
|
items.forEach((item) => {
|
|
@@ -1043,23 +1053,25 @@ export default {
|
|
|
1043
1053
|
currentPage: this.currentPage
|
|
1044
1054
|
});
|
|
1045
1055
|
},
|
|
1046
|
-
undo() {
|
|
1056
|
+
async undo() {
|
|
1047
1057
|
this.inspect();
|
|
1048
1058
|
this.$store.dispatch("undoRedoModule/undo");
|
|
1049
1059
|
this.config = JSON.parse(
|
|
1050
1060
|
this.$store.getters["undoRedoModule/currentState"].config
|
|
1051
1061
|
);
|
|
1052
|
-
this
|
|
1062
|
+
await this.$nextTick();
|
|
1063
|
+
this.$refs.tabsBar.openPageByIndex(
|
|
1053
1064
|
this.$store.getters["undoRedoModule/currentState"].currentPage
|
|
1054
1065
|
);
|
|
1055
1066
|
},
|
|
1056
|
-
redo() {
|
|
1067
|
+
async redo() {
|
|
1057
1068
|
this.inspect();
|
|
1058
1069
|
this.$store.dispatch("undoRedoModule/redo");
|
|
1059
1070
|
this.config = JSON.parse(
|
|
1060
1071
|
this.$store.getters["undoRedoModule/currentState"].config
|
|
1061
1072
|
);
|
|
1062
|
-
this
|
|
1073
|
+
await this.$nextTick();
|
|
1074
|
+
this.$refs.tabsBar.openPageByIndex(
|
|
1063
1075
|
this.$store.getters["undoRedoModule/currentState"].currentPage
|
|
1064
1076
|
);
|
|
1065
1077
|
},
|
|
@@ -1072,7 +1084,7 @@ export default {
|
|
|
1072
1084
|
},
|
|
1073
1085
|
focusInspector(validation) {
|
|
1074
1086
|
this.showConfiguration = true;
|
|
1075
|
-
this.
|
|
1087
|
+
this.$refs.tabsBar.openPageByIndex(this.config.indexOf(validation.page));
|
|
1076
1088
|
this.$nextTick(() => {
|
|
1077
1089
|
this.inspect(validation.item);
|
|
1078
1090
|
this.$nextTick(() => {
|
|
@@ -1091,12 +1103,17 @@ export default {
|
|
|
1091
1103
|
});
|
|
1092
1104
|
});
|
|
1093
1105
|
},
|
|
1094
|
-
confirmDelete() {
|
|
1106
|
+
confirmDelete(item = this.config[this.currentPage]) {
|
|
1095
1107
|
this.confirmMessage = this.$t(
|
|
1096
1108
|
"Are you sure you want to delete {{item}}?",
|
|
1097
|
-
{ item:
|
|
1109
|
+
{ item: item.name }
|
|
1098
1110
|
);
|
|
1099
|
-
|
|
1111
|
+
const isLastPage = this.config.length === 1;
|
|
1112
|
+
if (isLastPage) {
|
|
1113
|
+
// can not delete the last page
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
this.pageDelete = this.config.indexOf(item);
|
|
1100
1117
|
this.$refs.confirm.show();
|
|
1101
1118
|
},
|
|
1102
1119
|
hideConfirmModal() {
|
|
@@ -1131,18 +1148,85 @@ export default {
|
|
|
1131
1148
|
this.updateState();
|
|
1132
1149
|
},
|
|
1133
1150
|
addPage(e) {
|
|
1134
|
-
|
|
1151
|
+
this.showAddPageValidations = true;
|
|
1152
|
+
const error = this.checkPageName(this.addPageName, true);
|
|
1153
|
+
if (error) {
|
|
1135
1154
|
e.preventDefault();
|
|
1136
1155
|
return;
|
|
1137
1156
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1157
|
+
|
|
1158
|
+
const maxOrder = this.config.reduce((max, page) => {
|
|
1159
|
+
return page.order > max ? page.order : max;
|
|
1160
|
+
}, 0);
|
|
1161
|
+
|
|
1162
|
+
this.config.push({
|
|
1163
|
+
name: this.addPageName,
|
|
1164
|
+
order: maxOrder + 1,
|
|
1165
|
+
items: []
|
|
1166
|
+
});
|
|
1140
1167
|
this.addPageName = "";
|
|
1168
|
+
this.currentPage = this.config.length - 1;
|
|
1141
1169
|
this.updateState();
|
|
1170
|
+
|
|
1171
|
+
// open new page
|
|
1172
|
+
this.$refs.tabsBar.openPageByIndex(this.config.length - 1);
|
|
1173
|
+
},
|
|
1174
|
+
// This function is used to calculate the new index of the references
|
|
1175
|
+
calcNewIndexFor(index, referencedBy) {
|
|
1176
|
+
if (index === this.pageDelete) {
|
|
1177
|
+
throw new Error(
|
|
1178
|
+
`${this.$t(
|
|
1179
|
+
"Can not delete this page, it is referenced by"
|
|
1180
|
+
)}: ${referencedBy}`
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
return index > this.pageDelete ? index - 1 : index;
|
|
1184
|
+
},
|
|
1185
|
+
// Update Record list references
|
|
1186
|
+
updateRecordListReferences() {
|
|
1187
|
+
this.config.forEach((page) => {
|
|
1188
|
+
page.items.forEach((item) => {
|
|
1189
|
+
if (item.component === "FormRecordList") {
|
|
1190
|
+
// eslint-disable-next-line no-param-reassign
|
|
1191
|
+
item.config.form = this.calcNewIndexFor(
|
|
1192
|
+
item.config.form * 1,
|
|
1193
|
+
item.config.label
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
});
|
|
1197
|
+
});
|
|
1198
|
+
},
|
|
1199
|
+
// Update navigation buttons references
|
|
1200
|
+
updateNavigationButtonsReferences() {
|
|
1201
|
+
this.config.forEach((page) => {
|
|
1202
|
+
page.items.forEach((item) => {
|
|
1203
|
+
if (
|
|
1204
|
+
item.component === "FormButton" &&
|
|
1205
|
+
item.config.event === "pageNavigate"
|
|
1206
|
+
) {
|
|
1207
|
+
// eslint-disable-next-line no-param-reassign
|
|
1208
|
+
item.config.eventData = this.calcNewIndexFor(
|
|
1209
|
+
item.config.eventData * 1,
|
|
1210
|
+
item.config.label
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
});
|
|
1214
|
+
});
|
|
1142
1215
|
},
|
|
1143
|
-
deletePage() {
|
|
1144
|
-
|
|
1145
|
-
|
|
1216
|
+
async deletePage() {
|
|
1217
|
+
const back = _.cloneDeep(this.config);
|
|
1218
|
+
try {
|
|
1219
|
+
this.updateRecordListReferences();
|
|
1220
|
+
this.updateNavigationButtonsReferences();
|
|
1221
|
+
this.$refs.tabsBar.closePageByIndex(this.pageDelete);
|
|
1222
|
+
this.$refs.tabsBar.updateTabsReferences(this.pageDelete);
|
|
1223
|
+
await this.$nextTick();
|
|
1224
|
+
this.config.splice(this.pageDelete, 1);
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
this.config = back;
|
|
1227
|
+
globalObject.ProcessMaker.alert(error.message, "danger");
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1146
1230
|
this.$store.dispatch("undoRedoModule/pushState", {
|
|
1147
1231
|
config: JSON.stringify(this.config),
|
|
1148
1232
|
currentPage: this.currentPage,
|
|
@@ -1282,12 +1366,13 @@ export default {
|
|
|
1282
1366
|
this.config[this.currentPage].items.push(clone);
|
|
1283
1367
|
this.updateState();
|
|
1284
1368
|
this.inspect(clone);
|
|
1285
|
-
}
|
|
1369
|
+
},
|
|
1370
|
+
|
|
1286
1371
|
}
|
|
1287
1372
|
};
|
|
1288
1373
|
</script>
|
|
1289
1374
|
|
|
1290
|
-
<style
|
|
1375
|
+
<style>
|
|
1291
1376
|
.custom-popover {
|
|
1292
1377
|
margin-right: -400px;
|
|
1293
1378
|
padding: 16px;
|
|
@@ -1445,4 +1530,8 @@ $side-bar-font-size: 0.875rem;
|
|
|
1445
1530
|
box-shadow: 0 0 0 13px rgba(0, 0, 0, 0);
|
|
1446
1531
|
}
|
|
1447
1532
|
}
|
|
1533
|
+
.modal-subtitle {
|
|
1534
|
+
font-size: 15px;
|
|
1535
|
+
font-weight: normal;
|
|
1536
|
+
}
|
|
1448
1537
|
</style>
|