diff --git a/src/App.vue b/src/App.vue index ccfeeaccf..25912e399 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,10 +2,10 @@ - + - - + + - {{ pages[index].name }} + {{ pages[index]?.name }} -
- -
+ + @@ -90,6 +99,13 @@ export default { initialOpenedPages: { type: Array, default: () => [0] + }, + /** + * Icon to open a new tab, displayed when there are no pages opened. + */ + buttonIcon: { + type: String, + default: () => "fa fa-file" } }, data() { @@ -167,8 +183,11 @@ export default { this.localOpenedPages.splice(this.localOpenedPages.indexOf(pageId), 1); this.$emit("tab-closed", this.pages[pageId], this.localOpenedPages); }, + updateTabsReferences(pageDelete) { + this.localOpenedPages = this.localOpenedPages.map((page) => page > pageDelete ? page - 1 : page); + }, async openPageByIndex(index) { - const n = this.localOpenedPages.indexOf(index); + const n = this.localOpenedPages.indexOf(index * 1); if (n === -1) { this.localOpenedPages.push(index); await this.waitUpdates(this.updates + 2, 1000); @@ -177,6 +196,12 @@ export default { this.activeTab = n; } }, + closePageByIndex(index) { + const n = this.localOpenedPages.indexOf(index); + if (n !== -1) { + this.localOpenedPages.splice(n, 1); + } + }, checkTabsOverflow() { const tablist = this.$refs.tabs.$el.querySelector(".nav-tabs"); this.tabsListOverflow = tablist.scrollWidth > tablist.clientWidth; diff --git a/src/components/vue-form-builder.vue b/src/components/vue-form-builder.vue index 01ae0ddeb..73eddfa2f 100644 --- a/src/components/vue-form-builder.vue +++ b/src/components/vue-form-builder.vue @@ -101,56 +101,6 @@ ref="screen-container" class="overflow-auto mh-100 p-0 d-flex flex-column position-relative" > - - - - - -
- - - - - - - - - - - -
-
- { this.inspect(validation.item); this.$nextTick(() => { @@ -1190,8 +1143,62 @@ export default { this.addPageName = ""; this.updateState(); }, - deletePage() { - this.config.splice(this.pageDelete, 1); + // This function is used to calculate the new index of the references + calcNewIndexFor(index, referencedBy) { + if (index === this.pageDelete) { + throw new Error( + `${this.$t( + "Can not delete this page, it is referenced by" + )}: ${referencedBy}` + ); + } + return index > this.pageDelete ? index - 1 : index; + }, + // Update Record list references + updateRecordListReferences() { + this.config.forEach((page) => { + page.items.forEach((item) => { + if (item.component === "FormRecordList") { + // eslint-disable-next-line no-param-reassign + item.config.form = this.calcNewIndexFor( + item.config.form * 1, + item.config.label + ); + } + }); + }); + }, + // Update navigation buttons references + updateNavigationButtonsReferences() { + this.config.forEach((page) => { + page.items.forEach((item) => { + if ( + item.component === "FormButton" && + item.config.event === "pageNavigate" + ) { + // eslint-disable-next-line no-param-reassign + item.config.eventData = this.calcNewIndexFor( + item.config.eventData * 1, + item.config.label + ); + } + }); + }); + }, + async deletePage() { + const back = _.cloneDeep(this.config); + try { + this.updateRecordListReferences(); + this.updateNavigationButtonsReferences(); + this.$refs.tabsBar.closePageByIndex(this.pageDelete); + this.$refs.tabsBar.updateTabsReferences(this.pageDelete); + await this.$nextTick(); + this.config.splice(this.pageDelete, 1); + } catch (error) { + this.config = back; + globalObject.ProcessMaker.alert(error.message, "danger"); + return; + } this.$store.dispatch("undoRedoModule/pushState", { config: JSON.stringify(this.config), currentPage: this.currentPage, diff --git a/src/main.js b/src/main.js index 054840fe0..f63e8f8a8 100644 --- a/src/main.js +++ b/src/main.js @@ -225,8 +225,7 @@ window.ProcessMaker = { } }, alert(message, variant) { - variant; - message; + console.log(`${variant}: ${message}`); }, screen: { cacheEnabled: cacheEnabled ? cacheEnabled.content === "true" : false, diff --git a/src/stories/Configure.mdx b/src/stories/Configure.mdx index 33a1559ba..6bf5f3a41 100644 --- a/src/stories/Configure.mdx +++ b/src/stories/Configure.mdx @@ -25,9 +25,8 @@ export const RightArrow = () => ## Introduction -

- Welcome to the ProcessMaker ScreenBuilder Storybook! This interactive library is designed to showcase the components used to render screens within ProcessMaker processes. Built with Vue2, our components provide a versatile and intuitive way to build dynamic forms and interfaces for your business processes. -

+ + Welcome to the ProcessMaker ScreenBuilder Storybook! This interactive library is designed to showcase the components used to render screens within ProcessMaker processes. Built with Vue2, our components provide a versatile and intuitive way to build dynamic forms and interfaces for your business processes.
## Key Features @@ -42,11 +41,9 @@ export const RightArrow = () => ## Getting Started
-

- To start using the ScreenBuilder components in your ProcessMaker processes, follow these steps: -

-

+ To start using the ScreenBuilder components in your ProcessMaker processes, follow these steps: + Clone the repository and `cd` into the `screen-builder` directory: ```bash @@ -60,13 +57,10 @@ cd screen-builder npm i npm run serve ``` -

## Explore Components
-

- Start exploring the components by selecting them from the sidebar. Each entry provides detailed information about the component, including usage examples and customization options. -

+ Start exploring the components by selecting them from the sidebar. Each entry provides detailed information about the component, including usage examples and customization options.