From 43250ecb2c813de38e9ce08ee3f63c5ecf374889 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 1 Mar 2024 07:35:17 -0400 Subject: [PATCH 01/13] Improve and validate page name edit --- .../sortable/sortableList/SortableList.vue | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/components/sortable/sortableList/SortableList.vue b/src/components/sortable/sortableList/SortableList.vue index 4548edcb3..e712ab005 100644 --- a/src/components/sortable/sortableList/SortableList.vue +++ b/src/components/sortable/sortableList/SortableList.vue @@ -27,12 +27,20 @@ v-model="item.name" type="text" autofocus - @blur.stop="onBlur()" + required + :state="validateState(item.name, item)" + :error="validateError(item.name, item)" + @blur.stop="onBlur(item.name, item)" + @keydown.enter.stop="onBlur(item.name, item)" + @focus="onFocus(item.name, item)" /> {{ item.name }}
- +
@@ -55,6 +63,7 @@ export default { }, data() { return { + originalName: '', draggedItem: 0, draggedOverItem: 0, editRowIndex: null, @@ -69,14 +78,40 @@ export default { } }, methods: { - onBlur() { - this.editRowIndex = -1; + validateState(name, item) { + const isEmpty = !name; + const isDuplicated = this.items + .filter((i) => i !== item) + .find((i) => i.name === name); + return isEmpty || isDuplicated ? false : null; }, - onClick(item, index) { - if (this.editRowIndex === -1 || this.editRowIndex === index) { - this.editRowIndex = null; - return; + validateError(name, item) { + const isEmpty = !name; + if (!isEmpty) { + return this.$t("The Page Name field is required."); + } + const isDuplicated = this.items + .filter((i) => i !== item) + .find((i) => i.name === name); + if (isDuplicated) { + return this.$t('Must be unique.'); + } + return ''; + }, + onFocus(name, item) { + this.originalName = name; + }, + async onBlur(name, item) { + if (this.validateState(name, item) === false) { + // eslint-disable-next-line no-param-reassign + item.name = this.originalName; } + await this.$nextTick(); + setTimeout(() => { + this.editRowIndex = null; + }, 250); + }, + onClick(item, index) { this.editRowIndex = index; this.$emit("item-edit", item); }, From 37c0edf3faa1ebf016d4f2f87a4de658f0c5e936 Mon Sep 17 00:00:00 2001 From: Ryan Cooley Date: Mon, 4 Mar 2024 19:05:12 -0800 Subject: [PATCH 02/13] 2.84.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0d6e8599..52ada7f1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@processmaker/screen-builder", - "version": "2.84.1", + "version": "2.84.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@processmaker/screen-builder", - "version": "2.84.1", + "version": "2.84.2", "dependencies": { "@chantouchsek/validatorjs": "1.2.3", "@storybook/addon-docs": "^7.6.13", diff --git a/package.json b/package.json index eee7d4c45..7ae36be40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@processmaker/screen-builder", - "version": "2.84.1", + "version": "2.84.2", "scripts": { "dev": "VITE_COVERAGE=true vite", "build": "vite build", From a925c9a0d42ddf64caadf386c3c92e1b6c7bfa32 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 5 Mar 2024 18:27:41 -0400 Subject: [PATCH 03/13] Add scroll to dropdown pages --- src/assets/css/custom.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/assets/css/custom.css b/src/assets/css/custom.css index 38ec225ce..09fecf462 100644 --- a/src/assets/css/custom.css +++ b/src/assets/css/custom.css @@ -8,4 +8,7 @@ } .page-dropdown-menu { min-width: 333px; + max-height: 26rem; + overflow-y: auto; + scrollbar-width: thin; } \ No newline at end of file From dd4ee6ed737a08dbd6310a747e085446ccbf82a4 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 5 Mar 2024 18:27:55 -0400 Subject: [PATCH 04/13] Test scroll in dropdown pages --- src/stories/DropdownAndPages.stories.js | 35 ++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/stories/DropdownAndPages.stories.js b/src/stories/DropdownAndPages.stories.js index 5db2901b6..8de866df5 100644 --- a/src/stories/DropdownAndPages.stories.js +++ b/src/stories/DropdownAndPages.stories.js @@ -80,7 +80,6 @@ export const OpenPageUsingDropdown = { "[data-test=page-dropdown] button" ); let selectorAddPage = canvasElement.querySelector("[data-test=page-Page3]"); - console.log(selectorAddPage); await selector.click(selector); await selectorAddPage.click(selectorAddPage); // Open Page 3 (index=2) @@ -111,3 +110,37 @@ export const OpenPageUsingDropdown = { }); } }; + +// Open a page using the PageDropdown(index) +export const ScrollWithMoreThanTenPages = { + args: { + pages: [ + { name: "Page1" }, + { name: "Page2" }, + { name: "Page3" }, + { name: "Page4" }, + { name: "Page5" }, + { name: "Page6" }, + { name: "Page7" }, + { name: "Page8" }, + { name: "Page9" }, + { name: "Page10" }, + { name: "Page11" }, + { name: "Page12" } + ], + initialOpenedPages: [0] + }, + play: async ({ canvasElement }) => { + const selector = canvasElement.querySelector( + "[data-test=page-dropdown] button" + ); + await selector.click(selector); + // Test .page-dropdown-menu has scroll (scrollHeight > clientHeight) + await waitFor(() => { + const dropdownMenu = canvasElement.querySelector(".page-dropdown-menu"); + expect(dropdownMenu.scrollHeight).toBeGreaterThan( + dropdownMenu.clientHeight + ); + }); + } +}; From 4f491d3b3737dc1524207f359f0193860a3f8e14 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 5 Mar 2024 18:54:09 -0400 Subject: [PATCH 05/13] Fix flash of required --- src/components/vue-form-builder.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/vue-form-builder.vue b/src/components/vue-form-builder.vue index 964efb35c..3c1083586 100644 --- a/src/components/vue-form-builder.vue +++ b/src/components/vue-form-builder.vue @@ -1148,9 +1148,9 @@ export default { this.updateState(); }, addPage(e) { - this.showAddPageValidations = true; const error = this.checkPageName(this.addPageName, true); if (error) { + this.showAddPageValidations = true; e.preventDefault(); return; } From 49dac5a4817db7651abf7129694449ed9652edad Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 5 Mar 2024 19:31:07 -0400 Subject: [PATCH 06/13] Update order property --- .../sortable/sortableList/SortableList.vue | 12 ++++++++++-- src/components/vue-form-builder.vue | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/components/sortable/sortableList/SortableList.vue b/src/components/sortable/sortableList/SortableList.vue index e712ab005..eaea40b75 100644 --- a/src/components/sortable/sortableList/SortableList.vue +++ b/src/components/sortable/sortableList/SortableList.vue @@ -79,14 +79,14 @@ export default { }, methods: { validateState(name, item) { - const isEmpty = !name; + const isEmpty = !name?.trim(); const isDuplicated = this.items .filter((i) => i !== item) .find((i) => i.name === name); return isEmpty || isDuplicated ? false : null; }, validateError(name, item) { - const isEmpty = !name; + const isEmpty = !name?.trim(); if (!isEmpty) { return this.$t("The Page Name field is required."); } @@ -162,6 +162,14 @@ export default { itemsSortedClone[draggedItemIndex].order = tempOrder; } + + // Update order of the items + const clone = [...itemsSortedClone]; + clone.sort((a, b) => a.order - b.order); + clone.forEach((item, index) => { + // eslint-disable-next-line no-param-reassign + item.order = index + 1; + }); } this.$emit('ordered', itemsSortedClone); diff --git a/src/components/vue-form-builder.vue b/src/components/vue-form-builder.vue index 3c1083586..d8926f559 100644 --- a/src/components/vue-form-builder.vue +++ b/src/components/vue-form-builder.vue @@ -881,6 +881,7 @@ export default { config.forEach((page) => this.replaceFormText(page.items)); config.forEach((page) => this.migrateFormSubmit(page.items)); config.forEach((page) => this.updateFieldNameValidation(page.items)); + this.updatePageOrder(config); config.forEach((page) => this.removeDataVariableFromNestedScreens(page.items) ); @@ -889,6 +890,18 @@ export default { page.order = page.order || index + 1; }); }, + updatePageOrder(pages) { + const clone = [...pages]; + clone.sort((a, b) => { + const aOrder = a.order || pages.indexOf(a) + 1; + const bOrder = b.order || pages.indexOf(b) + 1; + return aOrder - bOrder; + }); + clone.forEach((item, index) => { + // eslint-disable-next-line no-param-reassign + item.order = index + 1; + }); + }, updateFieldNameValidation(items) { items.forEach((item) => { if (item.inspector) { @@ -1227,6 +1240,7 @@ export default { globalObject.ProcessMaker.alert(error.message, "danger"); return; } + this.updatePageOrder(this.config); this.$store.dispatch("undoRedoModule/pushState", { config: JSON.stringify(this.config), currentPage: this.currentPage, From da096b8fbe71c8268a31d396cbbd78c416099114 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 07:17:54 -0400 Subject: [PATCH 07/13] Test tab close --- src/stories/PageTabs.stories.js | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/stories/PageTabs.stories.js b/src/stories/PageTabs.stories.js index 49c9b2449..15833dd82 100644 --- a/src/stories/PageTabs.stories.js +++ b/src/stories/PageTabs.stories.js @@ -336,3 +336,60 @@ export const WithoutAnyPageOpened = { ); } }; + +// User can close tabs +export const UserCanCloseTabs = { + args: { + pages: [ + { name: "Page 1" }, + { name: "Page 2" }, + { name: "Page 3" }, + { name: "Page 4" }, + { name: "Page 5" } + ], + initialOpenedPages: [0, 1, 2, 3, 4] + }, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + // Close Tab #1 = Page 1 (tab index=0) + await step("Close Page 1 (tab index=0)", async () => { + canvas.getByTestId("close-tab-0").click(); + await waitFor( + () => { + expect(canvas.getByTestId("tab-content")).toContainHTML( + "Here comes content of Page 2 (#1)" + ); + }, + { timeout: 1000 } + ); + }); + + // Close Tab #1 = Page 2 (tab index=0) + await step("Close Page 2 (tab index=0)", async () => { + canvas.getByTestId("close-tab-0").click(); + await waitFor( + () => { + expect(canvas.getByTestId("tab-content")).toContainHTML( + "Here comes content of Page 3 (#2)" + ); + }, + { timeout: 1000 } + ); + }); + + // Close Tab #2 = Page 4 (tab index=1) + await step("Close Page 4 (tab index=1)", async () => { + canvas.getByTestId("close-tab-1").click(); + await waitFor( + () => { + // keep focus in the tab #1 + expect(canvas.getByTestId("tab-content")).toContainHTML( + "Here comes content of Page 3 (#2)" + ); + }, + { timeout: 1000 } + ); + }); + } +}; From 3bcb5ef005f88d614af9d5b48b2bc28d0a2f385f Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 07:18:05 -0400 Subject: [PATCH 08/13] Fix tab close --- src/components/TabsBar.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/TabsBar.vue b/src/components/TabsBar.vue index bfbd9cd51..ce4359648 100644 --- a/src/components/TabsBar.vue +++ b/src/components/TabsBar.vue @@ -196,9 +196,10 @@ export default { }, visualThreshold); }); }, - closeTab(pageId) { - this.localOpenedPages.splice(this.localOpenedPages.indexOf(pageId), 1); - this.$emit("tab-closed", this.pages[pageId], this.localOpenedPages); + closeTab(tabIndex) { + const pageIndex = this.localOpenedPages[tabIndex]; + this.localOpenedPages.splice(tabIndex, 1); + this.$emit("tab-closed", this.pages[pageIndex], this.localOpenedPages); }, updateTabsReferences(pageDelete) { this.localOpenedPages = this.localOpenedPages.map((page) => From 3c550bf912578300a9e487207f757b51b38bcba9 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 07:31:03 -0400 Subject: [PATCH 09/13] Improve page renaming --- .../sortable/sortableList/SortableList.vue | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/components/sortable/sortableList/SortableList.vue b/src/components/sortable/sortableList/SortableList.vue index eaea40b75..460e04a7f 100644 --- a/src/components/sortable/sortableList/SortableList.vue +++ b/src/components/sortable/sortableList/SortableList.vue @@ -24,15 +24,16 @@
{{ item.name }}
@@ -63,7 +64,7 @@ export default { }, data() { return { - originalName: '', + newName: '', draggedItem: 0, draggedOverItem: 0, editRowIndex: null, @@ -98,19 +99,24 @@ export default { } return ''; }, - onFocus(name, item) { - this.originalName = name; + onFocus(item) { + this.newName = item.name; }, async onBlur(name, item) { if (this.validateState(name, item) === false) { - // eslint-disable-next-line no-param-reassign - item.name = this.originalName; + this.newName = item.name; } + // eslint-disable-next-line no-param-reassign + item.name = name; await this.$nextTick(); setTimeout(() => { this.editRowIndex = null; }, 250); }, + async onCancel(item) { + this.newName = item.name; + this.editRowIndex = null; + }, onClick(item, index) { this.editRowIndex = index; this.$emit("item-edit", item); From 3965b621096729b157089fe21882a8e70f704830 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 08:36:10 -0400 Subject: [PATCH 10/13] Exclude CPD CC from stories tests --- sonar-project.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonar-project.properties b/sonar-project.properties index 37fec5778..34446f8a6 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,3 +3,5 @@ sonar.javascript.lcov.reportPaths=./coverage/lcov.info sonar.exclusions=node_modules/**, dist/**, public/**, home/**, storybook-static/** sonar.sources=src sonar.tests=tests +sonar.cpd.exclusions=src/stories/** +sonar.coverage.exclusions=src/stories/** From 56abd5e89ee3cb3132857a9fff55c365ed1f438a Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 09:08:33 -0400 Subject: [PATCH 11/13] Add specific class for nav no wrap --- src/assets/css/tabs.css | 4 +++- src/components/TabsBar.vue | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/assets/css/tabs.css b/src/assets/css/tabs.css index 3c15ade72..52908505f 100644 --- a/src/assets/css/tabs.css +++ b/src/assets/css/tabs.css @@ -10,10 +10,12 @@ /* Override Bootstrap default tab styles */ .nav-tabs { border-bottom: 1px solid var(--tabs-border) !important; + } + .nav-tabs-nowrap { flex-wrap: nowrap !important; overflow: hidden !important; } - + .nav-tabs .nav-item .nav-link { display: flex; align-items: center; diff --git a/src/components/TabsBar.vue b/src/components/TabsBar.vue index bfbd9cd51..f71563c4c 100644 --- a/src/components/TabsBar.vue +++ b/src/components/TabsBar.vue @@ -4,6 +4,7 @@ v-model="activeTab" class="h-100 w-100 flat-tabs" content-class="h-tab" + nav-class="nav-tabs-nowrap" lazy @changed="tabsUpdated" @input="tabOpened" From 04afb6490c44f7adee3110a3cb5dcae09beb24a2 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 6 Mar 2024 10:27:14 -0400 Subject: [PATCH 12/13] Fix page edit name validation rollback --- src/components/sortable/sortableList/SortableList.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/sortable/sortableList/SortableList.vue b/src/components/sortable/sortableList/SortableList.vue index 460e04a7f..18e044df7 100644 --- a/src/components/sortable/sortableList/SortableList.vue +++ b/src/components/sortable/sortableList/SortableList.vue @@ -105,9 +105,10 @@ export default { async onBlur(name, item) { if (this.validateState(name, item) === false) { this.newName = item.name; + } else { + // eslint-disable-next-line no-param-reassign + item.name = name; } - // eslint-disable-next-line no-param-reassign - item.name = name; await this.$nextTick(); setTimeout(() => { this.editRowIndex = null; From 4db483b2bbc20024b591c43aa0c33ad7e2db5fec Mon Sep 17 00:00:00 2001 From: Ryan Cooley Date: Wed, 6 Mar 2024 17:44:18 -0800 Subject: [PATCH 13/13] 2.84.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 52ada7f1d..40348b8a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@processmaker/screen-builder", - "version": "2.84.2", + "version": "2.84.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@processmaker/screen-builder", - "version": "2.84.2", + "version": "2.84.3", "dependencies": { "@chantouchsek/validatorjs": "1.2.3", "@storybook/addon-docs": "^7.6.13", diff --git a/package.json b/package.json index 7ae36be40..fad4b27a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@processmaker/screen-builder", - "version": "2.84.2", + "version": "2.84.3", "scripts": { "dev": "VITE_COVERAGE=true vite", "build": "vite build",