From 864711658c0104321f37469dae0cf3620f7b7588 Mon Sep 17 00:00:00 2001 From: Sara Boutej <40363501+SaraBoutej@users.noreply.github.com> Date: Wed, 3 Jul 2024 08:53:19 +0100 Subject: [PATCH] feat: Review UX to add node page - MEED-6835 - Meeds-io/MIPs#137 (#139) This PR allows to review the ui/ux to add or edit node. --- .../portlet/SiteNavigation_en.properties | 5 + .../SiteNavigationElementDrawer.vue | 202 +++--------------- .../SiteNavigationExistingPageElement.vue | 29 +-- .../SiteNavigationNewPageElement.vue | 91 +++----- .../SiteNavigationNewPageElementItem.vue | 92 ++++++++ .../SiteNavigationNodeDrawer.vue | 198 +++++++++++++++-- .../SiteNavigationPageElement.vue | 21 +- .../SiteNavigationPageSuggester.vue | 2 +- .../SiteNavigationSiteSuggester.vue | 2 +- .../initComponents.js | 2 + 10 files changed, 346 insertions(+), 298 deletions(-) create mode 100644 layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElementItem.vue diff --git a/layout-webapp/src/main/resources/locale/portlet/SiteNavigation_en.properties b/layout-webapp/src/main/resources/locale/portlet/SiteNavigation_en.properties index b3c8e2ea1..90e64bf1f 100644 --- a/layout-webapp/src/main/resources/locale/portlet/SiteNavigation_en.properties +++ b/layout-webapp/src/main/resources/locale/portlet/SiteNavigation_en.properties @@ -68,7 +68,12 @@ siteNavigation.label.invalidLink=Invalid link siteNavigation.label.enterUrl=Enter URL siteNavigation.label.newTab=New tab siteNavigation.label.sameTab=Same tab +siteNavigation.label.choosePage=Choose a page +siteNavigation.label.chooseSite=From any site +siteNavigation.label.openSameTab=Open in same tab siteNavigation.label.pageTemplate=Select page template +siteNavigation.label.blankTemplate=Blank Templates +siteNavigation.label.defaultTemplate=Default Templates siteNavigation.label.selectExistingPage=Select an existing page from siteNavigation.label.sitesSuggester.searchPlaceholder=Enter a site name siteNavigation.label.sitesSuggester.noData=No data diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationElementDrawer.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationElementDrawer.vue index e5777c582..12e527b49 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationElementDrawer.vue +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationElementDrawer.vue @@ -40,44 +40,7 @@ - - - - + @@ -93,7 +56,7 @@ :loading="loading" :disabled="disabled" class="btn btn-primary ms-2" - @click="saveElement"> + @click="createElement"> {{ $t('siteNavigation.label.btn.save') }} @@ -108,9 +71,6 @@ export default { return { elementType: 'PAGE', target: 'SAME_TAB', - link: '', - linkRules: [url => !!(url?.match(/^((https?:\/\/)?(www\.)?[a-zA-Z0-9:._\\/+=-]+\.[^\s]{2,})|(javascript:)|(\/portal\/)/)) - || ( !url?.length && this.$t('siteNavigation.required.error.message') || this.$t('siteNavigation.label.invalidLink'))], navigationNode: null, elementName: null, elementTitle: null, @@ -118,48 +78,15 @@ export default { selectedPage: null, loading: false, resetDrawer: true, - editMode: false, - pageToEdit: false, isValidForm: true, }; }, computed: { - elementTypes() { - return [ - { - text: this.$t('siteNavigation.label.newPage'), - value: 'PAGE', - }, - { - text: this.$t('siteNavigation.label.existingPage'), - value: 'existingPage', - }, - { - text: this.$t('siteNavigation.label.link'), - value: 'LINK', - }, - ]; - }, - targetTypes() { - return [ - { - text: this.$t('siteNavigation.label.sameTab'), - value: 'SAME_TAB', - }, - { - text: this.$t('siteNavigation.label.newTab'), - value: 'NEW_TAB', - }, - ]; - }, - isLinkElement() { - return this.elementType === 'LINK'; - }, drawerTitle() { - return this.editMode && this.$t('siteNavigation.label.editElement') || this.$t('siteNavigation.addElementDrawer.title'); + return this.$t('siteNavigation.addElementDrawer.title'); }, disabled() { - return !this.isValidForm || this.isLinkElement && !this.link || this.elementType === 'existingPage' && !this.selectedPage || false; + return !this.isValidForm || !this.pageTemplate || false; }, }, created() { @@ -169,35 +96,12 @@ export default { this.$root.$on('existing-page-selected', this.changeSelectedPage); }, methods: { - open(elementName, elementTitle, navigationNode, editMode) { + open(elementName, elementTitle, navigationNode) { this.resetDrawer = true; this.elementName = elementName; this.elementTitle = elementTitle; this.navigationNode = navigationNode; - this.target = navigationNode?.target; - this.editMode = editMode; - if (editMode && this.navigationNode?.pageKey) { - const pageRef = this.navigationNode.pageKey.ref ||`${ this.navigationNode.pageKey.site.typeName}::${ this.navigationNode.pageKey.site.name}::${this.navigationNode.pageKey.name}`; - this.$pageLayoutService.getPage(pageRef) - .then((page) => { - this.selectedPage = { - pageRef, - displayName: page.state.displayName || page.key.name, - }; - this.pageToEdit = page; - this.elementType = page.state?.type === 'LINK' && 'LINK' || 'existingPage'; - this.link = page?.state?.link; - this.$nextTick().then(() => { - this.$refs.siteNavigationAddElementDrawer.open(); - this.$nextTick() - .then(() => { - this.$root.$emit('set-selected-page', page.state); - }); - }); - }); - } else { - this.$refs.siteNavigationAddElementDrawer.open(); - } + this.$refs.siteNavigationAddElementDrawer.open(); }, close() { if (this.resetDrawer) { @@ -211,10 +115,6 @@ export default { }, reset() { this.selectedPage = null; - this.pageToEdit = null; - this.elementType = 'PAGE'; - this.link = ''; - this.target = 'SAME_TAB'; this.$root.$emit('reset-element-drawer'); }, changePageTemplate(pageTemplate) { @@ -223,80 +123,32 @@ export default { changeSelectedPage(selectedPage) { this.selectedPage = selectedPage; }, - saveElement() { - if (this.editMode) { - this.updateElement(); - } else { - this.createElement(); - } - }, createElement() { - if (this.elementType === 'existingPage') { - const pageRef = this.selectedPage?.pageRef; - this.$root.$emit('save-node-with-page', { - 'pageRef': pageRef, - 'nodeTarget': this.target, - 'pageType': this.elementType - }); - this.loading = false; - } else { - this.loading = true; - this.$pageLayoutService.createPage( - this.elementName, - this.elementTitle, - this.navigationNode.siteKey.name, - this.navigationNode.siteKey.type, - this.elementType, this.elementType === 'LINK' && this.link || null, - this.elementType === 'PAGE' && this.pageTemplate?.id || null - ) - .then((createdPage) => { - const pageRef = createdPage?.key?.ref || `${createdPage?.key.site.typeName}::${createdPage?.key.site.name}::${createdPage?.pageContext?.key.name}`; - this.$root.$emit('save-node-with-page', { - 'pageRef': pageRef, - 'nodeTarget': this.target, - 'pageType': this.elementType, - 'createdPage': createdPage, - 'openEditLayout': this.elementType === 'PAGE', - }); - return createdPage; - }).then(page => { - this.$root.$emit('page-layout-created', page, this.pageTemplate); - }).catch(() => { - this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageCreation.error'), 'error'); - }).finally(() => this.loading = false); - } - }, - updateElement() { - if (this.elementType === 'LINK') { - if (this.pageToEdit?.type === 'LINK') { - this.updatePageLink(); - } else { - this.createElement(); - } - } else if (this.elementType === 'PAGE') { - this.createElement(); - } else if (this.elementType === 'existingPage') { - const pageRef = this.selectedPage?.pageRef; + this.loading = true; + this.$pageLayoutService.createPage( + this.elementName, + this.elementTitle, + this.navigationNode.siteKey.name, + this.navigationNode.siteKey.type, + this.elementType, + '', + this.pageTemplate?.id || null + ).then((createdPage) => { + const pageRef = createdPage?.key?.ref || `${createdPage?.key.site.typeName}::${createdPage?.key.site.name}::${createdPage?.pageContext?.key.name}`; this.$root.$emit('save-node-with-page', { 'pageRef': pageRef, 'nodeTarget': this.target, - 'pageType': this.elementType + 'pageType': this.elementType, + 'createdPage': createdPage, + 'openEditLayout': true, }); - } + return createdPage; + }).then(page => { + this.$root.$emit('page-layout-created', page, this.pageTemplate); + }).catch(() => { + this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageCreation.error'), 'error'); + }).finally(() => this.loading = false); }, - updatePageLink() { - const pageRef = this.pageToEdit?.key?.ref || `${this.pageToEdit?.key.site.typeName}::${this.pageToEdit?.key.site.name}::${this.pageToEdit?.key.name}`; - this.$pageLayoutService.updatePageLink(pageRef, this.link) - .then(() => { - this.$root.$emit('save-node-with-page', { - 'pageRef': pageRef, - 'nodeTarget': this.target, - 'pageType': this.elementType - }); - }).catch(() => { - this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageUpdate.error'), 'error'); - }); - } } }; - \ No newline at end of file + diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationExistingPageElement.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationExistingPageElement.vue index 364ec05f2..5521498d5 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationExistingPageElement.vue +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationExistingPageElement.vue @@ -17,24 +17,14 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElement.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElement.vue index f6850abe3..ad22f6186 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElement.vue +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElement.vue @@ -18,83 +18,42 @@ --> diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElementItem.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElementItem.vue new file mode 100644 index 000000000..802d70a68 --- /dev/null +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNewPageElementItem.vue @@ -0,0 +1,92 @@ + + + + diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNodeDrawer.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNodeDrawer.vue index 6f9d0e9aa..490fdbd37 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNodeDrawer.vue +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationNodeDrawer.vue @@ -100,9 +100,9 @@ -
+
+ + @@ -244,10 +276,17 @@ export default { isScheduled: false, disableNodeId: false, displayNodeName: false, - nodeType: 'Group', + elementType: 'Group', + allSites: true, + nodeTarget: true, parentNavigationNodeUrl: '', editMode: false, nodeIcon: null, + selectedPage: null, + pageToEdit: false, + link: '', + linkRules: [url => !!(url?.match(/^((https?:\/\/)?(www\.)?[a-zA-Z0-9:._\\/+=-]+\.[^\s]{2,})|(javascript:)|(\/portal\/)/)) + || ( !url?.length && this.$t('siteNavigation.required.error.message') || this.$t('siteNavigation.label.invalidLink'))], nodeLabelRules: { required: value => value == null || !!(value?.length) || this.$t('siteNavigation.required.error.message'), }, @@ -274,10 +313,16 @@ export default { return this.editMode ? this.$t('siteNavigation.drawer.editNode.title') : this.$t('siteNavigation.drawer.addNode.title'); }, disabled() { - return !(this.isValidInputs && this.nodeId && this.nodeLabel); + return !(this.isValidInputs && this.nodeId && this.nodeLabel) || this.isLinkElement && !this.link; }, displayNextBtn() { - return this.editMode ? this.nodeType === 'PAGE' && !this.navigationNode.pageKey : this.nodeType === 'PAGE'; + return this.editMode ? this.elementType === 'PAGE' && !this.navigationNode.pageKey : this.elementType === 'PAGE'; + }, + isLinkElement() { + return this.elementType === 'LINK'; + }, + isNewPageElement() { + return this.elementType === 'PAGE'; }, }, created() { @@ -290,6 +335,7 @@ export default { this.$root.$on('update-node-icon', (icon) => { this.nodeIcon = icon; }); + this.$root.$on('existing-page-selected', this.changeSelectedPage); }, methods: { updateDates(startDate, endDate, startTime, endTime) { @@ -310,7 +356,23 @@ export default { if (this.editMode) { this.nodeLabel = parentNavigationNode.label; this.nodeId = parentNavigationNode.name; - this.nodeType = parentNavigationNode.pageKey ? 'pageOrLink' : 'Group'; + if (this.navigationNode?.pageKey) { + const pageRef = this.navigationNode.pageKey.ref ||`${ this.navigationNode.pageKey.site.typeName}::${ this.navigationNode.pageKey.site.name}::${this.navigationNode.pageKey.name}`; + this.$pageLayoutService.getPage(pageRef) + .then((page) => { + this.selectedPage = { + pageRef, + displayName: page.state.displayName || page.key.name, + }; + this.pageToEdit = page; + this.elementType = page.state?.type === 'LINK' && 'LINK' || 'existingPage'; + this.link = page?.state?.link; + this.$root.$emit('set-selected-page', page.state); + }); + } else { + this.elementType = 'Group'; + } + this.elementType = parentNavigationNode.pageKey ? 'pageOrLink' : 'Group'; this.visible = parentNavigationNode.visibility !== 'HIDDEN'; this.nodeIcon = parentNavigationNode.icon; this.disableNodeId = true; @@ -330,9 +392,11 @@ export default { this.visible = true; this.isScheduled = false; this.displayNodeName = false; - this.nodeType = 'Group'; + this.elementType = 'Group'; + this.nodeTarget = true; this.disableNodeId = false; this.editMode= false; + this.pageToEdit = null; this.startScheduleDate = new Date().getTime(); this.endScheduleDate = new Date().getTime(); this.startScheduleTime = new Date(new Date().getTime() + 900000); @@ -371,8 +435,45 @@ export default { labels: this.labels }; if (this.editMode) { - const pageRef = pageData?.pageRef || (this.nodeType === 'pageOrLink' ? this.navigationNode.pageKey?.ref || `${ this.navigationNode.pageKey.site.typeName}::${ this.navigationNode.pageKey.site.name}::${this.navigationNode.pageKey?.name}` : ''); + const pageRef = pageData?.pageRef || (this.elementType !== 'Group' ? this.navigationNode.pageKey?.ref || `${ this.navigationNode.pageKey.site.typeName}::${ this.navigationNode.pageKey.site.name}::${this.navigationNode.pageKey?.name}` : ''); this.loading = true; + if (this.elementType === 'existingPage') { + const pageRef = this.selectedPage?.pageRef; + pageData = { + 'pageRef': pageRef, + 'nodeTarget': this.nodeTarget, + 'pageType': this.elementType + }; + this.updateNode(pageData,pageRef, startScheduleDate, endScheduleDate, nodeLabels); + } else if (this.elementType === 'LINK') { + if (this.pageToEdit.state?.type === 'LINK') { + this.updatePageLink(startScheduleDate, endScheduleDate, nodeLabels); + } else { + this.$pageLayoutService.createPage( + this.nodeId, + this.valuesPerLanguage['en'] || this.nodeLabel, + this.navigationNode.siteKey.name, + this.navigationNode.siteKey.type, + this.elementType, this.elementType === 'LINK' && this.link || null, + ).then((createdPage) => { + const pageRef = createdPage?.key?.ref || `${createdPage?.key.site.typeName}::${createdPage?.key.site.name}::${createdPage?.pageContext?.key.name}`; + pageData = { + 'pageRef': pageRef, + 'nodeTarget': this.target, + 'pageType': this.elementType, + 'createdPage': createdPage, + 'openEditLayout': true, + }; + this.updateNode(pageData,pageRef, startScheduleDate, endScheduleDate, nodeLabels); + }).then(page => { + this.$root.$emit('page-layout-created', page, this.pageTemplate); + }).catch(() => { + this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageCreation.error'), 'error'); + }); + } + } else { + this.updateNode(pageData,pageRef, startScheduleDate, endScheduleDate, nodeLabels); + } this.$navigationLayoutService.updateNode(this.navigationNode.id, this.nodeLabel, pageRef, this.visible, this.isScheduled, startScheduleDate, endScheduleDate, nodeLabels?.labels, pageData?.nodeTarget || this.navigationNode.target, this.nodeIcon) .then(() => { this.openTargetPage(pageData, this.navigationNode.id); @@ -384,23 +485,86 @@ export default { .finally(() => this.loading = false); } else { this.loading = true; - this.$navigationLayoutService.createNode(this.navigationNode.id, previousNodeId, this.nodeLabel, this.nodeId, this.nodeIcon, this.visible, this.isScheduled, startScheduleDate, endScheduleDate, nodeLabels?.labels, pageData?.pageRef, pageData?.pageRef && pageData?.nodeTarget || 'SAME_TAB') - .then(createdNode => { - this.openTargetPage(pageData, createdNode.id); - this.$root.$emit('refresh-navigation-nodes'); - this.$root.$emit('close-add-element-drawer'); - this.close(); - }) - .catch(() => this.$root.$emit('alert-message', this.$t('siteNavigation.errorCreatingNode'), 'error')) - .finally(() => this.loading = false); + if (this.elementType === 'existingPage') { + const pageRef = this.selectedPage?.pageRef; + pageData = { + 'pageRef': pageRef, + 'nodeTarget': this.nodeTarget ? 'SAME_TAB' : 'NEW_TAB', + 'pageType': this.elementType + }; + this.createNode(previousNodeId, pageData, startScheduleDate, endScheduleDate, nodeLabels); + } else if (this.elementType === 'LINK') { + this.$pageLayoutService.createPage( + this.nodeId, + this.valuesPerLanguage['en'] || this.nodeLabel, + this.navigationNode.siteKey.name, + this.navigationNode.siteKey.type, + this.elementType, this.elementType === 'LINK' && this.link || null, + ).then((createdPage) => { + const pageRef = createdPage?.key?.ref || `${createdPage?.key.site.typeName}::${createdPage?.key.site.name}::${createdPage?.pageContext?.key.name}`; + pageData = { + 'pageRef': pageRef, + 'nodeTarget': this.target, + 'pageType': this.elementType, + 'createdPage': createdPage, + 'openEditLayout': true, + }; + this.createNode(previousNodeId, pageData, startScheduleDate, endScheduleDate, nodeLabels); + }).then(page => { + this.$root.$emit('page-layout-created', page, this.pageTemplate); + }).catch(() => { + this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageCreation.error'), 'error'); + }); + } else { + this.createNode(previousNodeId, pageData, startScheduleDate, endScheduleDate, nodeLabels); + } } }, + createNode(previousNodeId, pageData, startScheduleDate, endScheduleDate, nodeLabels) { + this.$navigationLayoutService.createNode(this.navigationNode.id, previousNodeId, this.nodeLabel, this.nodeId, this.nodeIcon, this.visible, this.isScheduled, startScheduleDate, endScheduleDate, nodeLabels?.labels, pageData?.pageRef, pageData?.pageRef && pageData?.nodeTarget || 'SAME_TAB') + .then(createdNode => { + this.openTargetPage(pageData, createdNode.id); + this.$root.$emit('refresh-navigation-nodes'); + this.$root.$emit('close-add-element-drawer'); + this.close(); + }) + .catch(() => this.$root.$emit('alert-message', this.$t('siteNavigation.errorCreatingNode'), 'error')) + .finally(() => this.loading = false); + }, + updateNode(pageData, pageRef, startScheduleDate, endScheduleDate, nodeLabels) { + this.$navigationLayoutService.updateNode(this.navigationNode.id, this.nodeLabel, pageRef, this.visible, this.isScheduled, startScheduleDate, endScheduleDate, nodeLabels?.labels, pageData?.nodeTarget || this.navigationNode.target, this.nodeIcon) + .then(() => { + this.openTargetPage(pageData, this.navigationNode.id); + this.$root.$emit('refresh-navigation-nodes'); + this.$root.$emit('close-add-element-drawer'); + this.close(); + }) + .catch(() => this.$root.$emit('alert-message', this.$t('siteNavigation.errorUpdatingNode'), 'error')) + .finally(() => this.loading = false); + }, + updatePageLink(startScheduleDate, endScheduleDate, nodeLabels) { + const pageRef = this.pageToEdit?.key?.ref || `${this.pageToEdit?.key.site.typeName}::${this.pageToEdit?.key.site.name}::${this.pageToEdit?.key.name}`; + this.$pageLayoutService.updatePageLink(pageRef, this.link) + .then(() => { + const pageData = { + 'pageRef': pageRef, + 'nodeTarget': this.target, + 'pageType': this.elementType + }; + this.updateNode(pageData, pageRef, startScheduleDate, endScheduleDate, nodeLabels); + }).catch(() => { + this.$root.$emit('alert-message', this.$t('siteNavigation.label.pageUpdate.error'), 'error'); + }); + }, openAddElementDrawer() { this.$root.$emit('open-add-element-drawer', this.nodeId, this.valuesPerLanguage['en'] || this.nodeLabel, this.navigationNode, this.navigationNode?.pageKey && this.editMode || false); }, conversionRules() { return this.nodeLabel.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-zA-Z0-9_-]/g, '').replace(/\s+/g, '').toLowerCase(); }, + changeSelectedPage(selectedPage) { + this.selectedPage = selectedPage; + }, blurOnNodeLabel() { if (this.nodeId == null) { this.nodeId = this.conversionRules(); diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationPageElement.vue b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationPageElement.vue index edf11051e..1b5447850 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationPageElement.vue +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/components/site-navigation/SiteNavigationPageElement.vue @@ -17,31 +17,14 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -->