@processmaker/screen-builder 2.84.1 → 2.84.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.
- package/dist/vue-form-builder.css +1 -1
- package/dist/vue-form-builder.es.js +57 -25
- package/dist/vue-form-builder.es.js.map +1 -1
- package/dist/vue-form-builder.umd.js +2 -2
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/css/custom.css +3 -0
- package/src/assets/css/tabs.css +3 -1
- package/src/components/TabsBar.vue +5 -3
- package/src/components/sortable/sortableList/SortableList.vue +59 -9
- package/src/components/vue-form-builder.vue +15 -1
- package/src/stories/DropdownAndPages.stories.js +34 -1
- package/src/stories/PageTabs.stories.js +57 -0
package/package.json
CHANGED
package/src/assets/css/tabs.css
CHANGED
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
/* Override Bootstrap default tab styles */
|
|
11
11
|
.nav-tabs {
|
|
12
12
|
border-bottom: 1px solid var(--tabs-border) !important;
|
|
13
|
+
}
|
|
14
|
+
.nav-tabs-nowrap {
|
|
13
15
|
flex-wrap: nowrap !important;
|
|
14
16
|
overflow: hidden !important;
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
|
|
17
19
|
.nav-tabs .nav-item .nav-link {
|
|
18
20
|
display: flex;
|
|
19
21
|
align-items: center;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
v-model="activeTab"
|
|
5
5
|
class="h-100 w-100 flat-tabs"
|
|
6
6
|
content-class="h-tab"
|
|
7
|
+
nav-class="nav-tabs-nowrap"
|
|
7
8
|
lazy
|
|
8
9
|
@changed="tabsUpdated"
|
|
9
10
|
@input="tabOpened"
|
|
@@ -196,9 +197,10 @@ export default {
|
|
|
196
197
|
}, visualThreshold);
|
|
197
198
|
});
|
|
198
199
|
},
|
|
199
|
-
closeTab(
|
|
200
|
-
this.localOpenedPages
|
|
201
|
-
this
|
|
200
|
+
closeTab(tabIndex) {
|
|
201
|
+
const pageIndex = this.localOpenedPages[tabIndex];
|
|
202
|
+
this.localOpenedPages.splice(tabIndex, 1);
|
|
203
|
+
this.$emit("tab-closed", this.pages[pageIndex], this.localOpenedPages);
|
|
202
204
|
},
|
|
203
205
|
updateTabsReferences(pageDelete) {
|
|
204
206
|
this.localOpenedPages = this.localOpenedPages.map((page) =>
|
|
@@ -24,15 +24,24 @@
|
|
|
24
24
|
<div class="rounded sortable-item-name">
|
|
25
25
|
<b-form-input
|
|
26
26
|
v-if="editRowIndex === index"
|
|
27
|
-
v-model="
|
|
27
|
+
v-model="newName"
|
|
28
28
|
type="text"
|
|
29
29
|
autofocus
|
|
30
|
-
|
|
30
|
+
required
|
|
31
|
+
:state="validateState(newName, item)"
|
|
32
|
+
:error="validateError(newName, item)"
|
|
33
|
+
@blur.stop="onBlur(newName, item)"
|
|
34
|
+
@keydown.enter.stop="onBlur(newName, item)"
|
|
35
|
+
@keydown.esc.stop="onCancel(item)"
|
|
36
|
+
@focus="onFocus(item)"
|
|
31
37
|
/>
|
|
32
38
|
<span v-else>{{ item.name }}</span>
|
|
33
39
|
</div>
|
|
34
40
|
<div class="border rounded-lg sortable-item-action">
|
|
35
|
-
<button
|
|
41
|
+
<button v-if="editRowIndex === index" class="btn">
|
|
42
|
+
<i class="fas fa-check"></i>
|
|
43
|
+
</button>
|
|
44
|
+
<button v-else class="btn" @click.stop="onClick(item, index)">
|
|
36
45
|
<i class="fas fa-edit"></i>
|
|
37
46
|
</button>
|
|
38
47
|
<div class="sortable-item-vr"></div>
|
|
@@ -55,6 +64,7 @@ export default {
|
|
|
55
64
|
},
|
|
56
65
|
data() {
|
|
57
66
|
return {
|
|
67
|
+
newName: '',
|
|
58
68
|
draggedItem: 0,
|
|
59
69
|
draggedOverItem: 0,
|
|
60
70
|
editRowIndex: null,
|
|
@@ -69,14 +79,46 @@ export default {
|
|
|
69
79
|
}
|
|
70
80
|
},
|
|
71
81
|
methods: {
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
validateState(name, item) {
|
|
83
|
+
const isEmpty = !name?.trim();
|
|
84
|
+
const isDuplicated = this.items
|
|
85
|
+
.filter((i) => i !== item)
|
|
86
|
+
.find((i) => i.name === name);
|
|
87
|
+
return isEmpty || isDuplicated ? false : null;
|
|
74
88
|
},
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return;
|
|
89
|
+
validateError(name, item) {
|
|
90
|
+
const isEmpty = !name?.trim();
|
|
91
|
+
if (!isEmpty) {
|
|
92
|
+
return this.$t("The Page Name field is required.");
|
|
93
|
+
}
|
|
94
|
+
const isDuplicated = this.items
|
|
95
|
+
.filter((i) => i !== item)
|
|
96
|
+
.find((i) => i.name === name);
|
|
97
|
+
if (isDuplicated) {
|
|
98
|
+
return this.$t('Must be unique.');
|
|
99
|
+
}
|
|
100
|
+
return '';
|
|
101
|
+
},
|
|
102
|
+
onFocus(item) {
|
|
103
|
+
this.newName = item.name;
|
|
104
|
+
},
|
|
105
|
+
async onBlur(name, item) {
|
|
106
|
+
if (this.validateState(name, item) === false) {
|
|
107
|
+
this.newName = item.name;
|
|
108
|
+
} else {
|
|
109
|
+
// eslint-disable-next-line no-param-reassign
|
|
110
|
+
item.name = name;
|
|
79
111
|
}
|
|
112
|
+
await this.$nextTick();
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
this.editRowIndex = null;
|
|
115
|
+
}, 250);
|
|
116
|
+
},
|
|
117
|
+
async onCancel(item) {
|
|
118
|
+
this.newName = item.name;
|
|
119
|
+
this.editRowIndex = null;
|
|
120
|
+
},
|
|
121
|
+
onClick(item, index) {
|
|
80
122
|
this.editRowIndex = index;
|
|
81
123
|
this.$emit("item-edit", item);
|
|
82
124
|
},
|
|
@@ -127,6 +169,14 @@ export default {
|
|
|
127
169
|
|
|
128
170
|
itemsSortedClone[draggedItemIndex].order = tempOrder;
|
|
129
171
|
}
|
|
172
|
+
|
|
173
|
+
// Update order of the items
|
|
174
|
+
const clone = [...itemsSortedClone];
|
|
175
|
+
clone.sort((a, b) => a.order - b.order);
|
|
176
|
+
clone.forEach((item, index) => {
|
|
177
|
+
// eslint-disable-next-line no-param-reassign
|
|
178
|
+
item.order = index + 1;
|
|
179
|
+
});
|
|
130
180
|
}
|
|
131
181
|
|
|
132
182
|
this.$emit('ordered', itemsSortedClone);
|
|
@@ -881,6 +881,7 @@ export default {
|
|
|
881
881
|
config.forEach((page) => this.replaceFormText(page.items));
|
|
882
882
|
config.forEach((page) => this.migrateFormSubmit(page.items));
|
|
883
883
|
config.forEach((page) => this.updateFieldNameValidation(page.items));
|
|
884
|
+
this.updatePageOrder(config);
|
|
884
885
|
config.forEach((page) =>
|
|
885
886
|
this.removeDataVariableFromNestedScreens(page.items)
|
|
886
887
|
);
|
|
@@ -889,6 +890,18 @@ export default {
|
|
|
889
890
|
page.order = page.order || index + 1;
|
|
890
891
|
});
|
|
891
892
|
},
|
|
893
|
+
updatePageOrder(pages) {
|
|
894
|
+
const clone = [...pages];
|
|
895
|
+
clone.sort((a, b) => {
|
|
896
|
+
const aOrder = a.order || pages.indexOf(a) + 1;
|
|
897
|
+
const bOrder = b.order || pages.indexOf(b) + 1;
|
|
898
|
+
return aOrder - bOrder;
|
|
899
|
+
});
|
|
900
|
+
clone.forEach((item, index) => {
|
|
901
|
+
// eslint-disable-next-line no-param-reassign
|
|
902
|
+
item.order = index + 1;
|
|
903
|
+
});
|
|
904
|
+
},
|
|
892
905
|
updateFieldNameValidation(items) {
|
|
893
906
|
items.forEach((item) => {
|
|
894
907
|
if (item.inspector) {
|
|
@@ -1148,9 +1161,9 @@ export default {
|
|
|
1148
1161
|
this.updateState();
|
|
1149
1162
|
},
|
|
1150
1163
|
addPage(e) {
|
|
1151
|
-
this.showAddPageValidations = true;
|
|
1152
1164
|
const error = this.checkPageName(this.addPageName, true);
|
|
1153
1165
|
if (error) {
|
|
1166
|
+
this.showAddPageValidations = true;
|
|
1154
1167
|
e.preventDefault();
|
|
1155
1168
|
return;
|
|
1156
1169
|
}
|
|
@@ -1227,6 +1240,7 @@ export default {
|
|
|
1227
1240
|
globalObject.ProcessMaker.alert(error.message, "danger");
|
|
1228
1241
|
return;
|
|
1229
1242
|
}
|
|
1243
|
+
this.updatePageOrder(this.config);
|
|
1230
1244
|
this.$store.dispatch("undoRedoModule/pushState", {
|
|
1231
1245
|
config: JSON.stringify(this.config),
|
|
1232
1246
|
currentPage: this.currentPage,
|
|
@@ -80,7 +80,6 @@ export const OpenPageUsingDropdown = {
|
|
|
80
80
|
"[data-test=page-dropdown] button"
|
|
81
81
|
);
|
|
82
82
|
let selectorAddPage = canvasElement.querySelector("[data-test=page-Page3]");
|
|
83
|
-
console.log(selectorAddPage);
|
|
84
83
|
await selector.click(selector);
|
|
85
84
|
await selectorAddPage.click(selectorAddPage);
|
|
86
85
|
// Open Page 3 (index=2)
|
|
@@ -111,3 +110,37 @@ export const OpenPageUsingDropdown = {
|
|
|
111
110
|
});
|
|
112
111
|
}
|
|
113
112
|
};
|
|
113
|
+
|
|
114
|
+
// Open a page using the PageDropdown(index)
|
|
115
|
+
export const ScrollWithMoreThanTenPages = {
|
|
116
|
+
args: {
|
|
117
|
+
pages: [
|
|
118
|
+
{ name: "Page1" },
|
|
119
|
+
{ name: "Page2" },
|
|
120
|
+
{ name: "Page3" },
|
|
121
|
+
{ name: "Page4" },
|
|
122
|
+
{ name: "Page5" },
|
|
123
|
+
{ name: "Page6" },
|
|
124
|
+
{ name: "Page7" },
|
|
125
|
+
{ name: "Page8" },
|
|
126
|
+
{ name: "Page9" },
|
|
127
|
+
{ name: "Page10" },
|
|
128
|
+
{ name: "Page11" },
|
|
129
|
+
{ name: "Page12" }
|
|
130
|
+
],
|
|
131
|
+
initialOpenedPages: [0]
|
|
132
|
+
},
|
|
133
|
+
play: async ({ canvasElement }) => {
|
|
134
|
+
const selector = canvasElement.querySelector(
|
|
135
|
+
"[data-test=page-dropdown] button"
|
|
136
|
+
);
|
|
137
|
+
await selector.click(selector);
|
|
138
|
+
// Test .page-dropdown-menu has scroll (scrollHeight > clientHeight)
|
|
139
|
+
await waitFor(() => {
|
|
140
|
+
const dropdownMenu = canvasElement.querySelector(".page-dropdown-menu");
|
|
141
|
+
expect(dropdownMenu.scrollHeight).toBeGreaterThan(
|
|
142
|
+
dropdownMenu.clientHeight
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
@@ -336,3 +336,60 @@ export const WithoutAnyPageOpened = {
|
|
|
336
336
|
);
|
|
337
337
|
}
|
|
338
338
|
};
|
|
339
|
+
|
|
340
|
+
// User can close tabs
|
|
341
|
+
export const UserCanCloseTabs = {
|
|
342
|
+
args: {
|
|
343
|
+
pages: [
|
|
344
|
+
{ name: "Page 1" },
|
|
345
|
+
{ name: "Page 2" },
|
|
346
|
+
{ name: "Page 3" },
|
|
347
|
+
{ name: "Page 4" },
|
|
348
|
+
{ name: "Page 5" }
|
|
349
|
+
],
|
|
350
|
+
initialOpenedPages: [0, 1, 2, 3, 4]
|
|
351
|
+
},
|
|
352
|
+
play: async ({ canvasElement, step }) => {
|
|
353
|
+
const canvas = within(canvasElement);
|
|
354
|
+
|
|
355
|
+
// Close Tab #1 = Page 1 (tab index=0)
|
|
356
|
+
await step("Close Page 1 (tab index=0)", async () => {
|
|
357
|
+
canvas.getByTestId("close-tab-0").click();
|
|
358
|
+
await waitFor(
|
|
359
|
+
() => {
|
|
360
|
+
expect(canvas.getByTestId("tab-content")).toContainHTML(
|
|
361
|
+
"Here comes content of Page 2 (#1)"
|
|
362
|
+
);
|
|
363
|
+
},
|
|
364
|
+
{ timeout: 1000 }
|
|
365
|
+
);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Close Tab #1 = Page 2 (tab index=0)
|
|
369
|
+
await step("Close Page 2 (tab index=0)", async () => {
|
|
370
|
+
canvas.getByTestId("close-tab-0").click();
|
|
371
|
+
await waitFor(
|
|
372
|
+
() => {
|
|
373
|
+
expect(canvas.getByTestId("tab-content")).toContainHTML(
|
|
374
|
+
"Here comes content of Page 3 (#2)"
|
|
375
|
+
);
|
|
376
|
+
},
|
|
377
|
+
{ timeout: 1000 }
|
|
378
|
+
);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Close Tab #2 = Page 4 (tab index=1)
|
|
382
|
+
await step("Close Page 4 (tab index=1)", async () => {
|
|
383
|
+
canvas.getByTestId("close-tab-1").click();
|
|
384
|
+
await waitFor(
|
|
385
|
+
() => {
|
|
386
|
+
// keep focus in the tab #1
|
|
387
|
+
expect(canvas.getByTestId("tab-content")).toContainHTML(
|
|
388
|
+
"Here comes content of Page 3 (#2)"
|
|
389
|
+
);
|
|
390
|
+
},
|
|
391
|
+
{ timeout: 1000 }
|
|
392
|
+
);
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
};
|