diff --git a/client/web/compose/src/mixins/pages.js b/client/web/compose/src/mixins/pages.js new file mode 100644 index 000000000..3da495032 --- /dev/null +++ b/client/web/compose/src/mixins/pages.js @@ -0,0 +1,66 @@ +import { NoID } from '@cortezaproject/corteza-js' + +export default { + methods: { + countDuplicateTitles (pages, pattern) { + let substrTitle = this.page.title + + // if the old page begins with 'copy of' and it does not end with a number in brackets, remove copy of prefix + if (this.page.title.includes(this.$t('copyOf')) && !pattern.test(this.page.title)) { + substrTitle = this.page.title.substring(this.$t('copyOf').length, this.page.title.length) + // if the old page begins with 'copy of' and it ends with a number in brackets, remove them + } else if (this.page.title.includes(this.$t('copyOf')) && pattern.test(this.page.title)) { + substrTitle = this.page.title.substring(this.$t('copyOf').length, this.page.title.lastIndexOf('(') - 1) + } + + return pages.filter(p => p.title.includes(substrTitle)).length + }, + + handleClone () { + const { namespaceID = NoID } = this.namespace + const pattern = /\([0-9]+\)/ + + let page = this.page.clone() + + this.loadPages({ namespaceID, force: true }) + .then(pages => { + let newPageTitle = this.$t('copyOf', { title: this.page.title }) + const countDuplicates = this.countDuplicateTitles(pages, pattern) + + // if page with the same name already exists two times, add a number (2) sufix + if (countDuplicates === 2) { + newPageTitle = this.page.title.includes(this.$t('copyOf')) + ? `${this.page.title} (${countDuplicates})` + : `${this.$t('copyOf')} ${this.page.title} (${countDuplicates})` + } else if (countDuplicates > 2 && this.page.title.includes(this.$t('copyOf'))) { + /** + * if page with the same name exists more than two times and it has "copy of" prefix, check old page's sufix + * If page ends with a number inside parenthesis, replace it with the new number + * If page does not have a number, add it + */ + newPageTitle = pattern.test(page.title) + ? `${this.page.title.substr(0, this.page.title.lastIndexOf('('))}(${countDuplicates})` + : `${this.page.title} (${countDuplicates})` + } else if (countDuplicates > 2 && !this.page.title.includes(this.$t('copyOf'))) { + // if page with the same name exists more than two times and it does not have "copy of" prefix, append the prefix and the new number + newPageTitle = `${this.$t('copyOf')}${this.page.title} (${countDuplicates})` + } + + page = { + ...page, + pageID: NoID, + title: newPageTitle, + handle: '', + } + + return this.createPage({ namespaceID, ...page }) + }) + .then(({ pageID }) => { + this.$router.push({ name: this.$route.name, params: { pageID } }) + }) + .catch(this.toastErrorHandler(this.$t('notification:page.cloneFailed'))) + }, + + }, + +} diff --git a/client/web/compose/src/views/Admin/Pages/Builder.vue b/client/web/compose/src/views/Admin/Pages/Builder.vue index fee3c23ce..2e433ac1a 100644 --- a/client/web/compose/src/views/Admin/Pages/Builder.vue +++ b/client/web/compose/src/views/Admin/Pages/Builder.vue @@ -223,6 +223,7 @@ diff --git a/client/web/compose/src/views/Admin/Pages/Edit.vue b/client/web/compose/src/views/Admin/Pages/Edit.vue index 7cd2281a4..94f9074fe 100644 --- a/client/web/compose/src/views/Admin/Pages/Edit.vue +++ b/client/web/compose/src/views/Admin/Pages/Edit.vue @@ -170,6 +170,7 @@ import { mapGetters, mapActions } from 'vuex' import EditorToolbar from 'corteza-webapp-compose/src/components/Admin/EditorToolbar' import PageTranslator from 'corteza-webapp-compose/src/components/Admin/Page/PageTranslator' +import pages from 'corteza-webapp-compose/src/mixins/pages' import { compose, NoID } from '@cortezaproject/corteza-js' import { handle } from '@cortezaproject/corteza-vue' @@ -185,6 +186,10 @@ export default { PageTranslator, }, + mixins: [ + pages, + ], + props: { namespace: { type: compose.Namespace, @@ -244,13 +249,21 @@ export default { showDeleteDropdown () { return this.hasChildren && this.page.canDeletePage && !this.page.deletedAt }, + }, - created () { - const { namespaceID } = this.namespace - this.findPageByID({ namespaceID, pageID: this.pageID }).then((page) => { - this.page = new compose.Page(page) - }).catch(this.toastErrorHandler(this.$t('notification:page.loadFailed'))) + watch: { + pageID: { + immediate: true, + handler (pageID) { + if (pageID) { + const { namespaceID } = this.namespace + this.findPageByID({ namespaceID, pageID }).then((page) => { + this.page = page.clone() + }).catch(this.toastErrorHandler(this.$t('notification:page.loadFailed'))) + } + }, + }, }, methods: { @@ -259,6 +272,7 @@ export default { updatePage: 'page/update', deletePage: 'page/delete', createPage: 'page/create', + loadPages: 'page/load', }), handleSave ({ closeOnSuccess = false } = {}) { @@ -282,25 +296,6 @@ export default { this.$router.push({ name: 'admin.pages' }) }).catch(this.toastErrorHandler(this.$t('notification:page.deleteFailed'))) }, - - handleClone () { - let page = this.page.clone() - page = { - ...page, - pageID: NoID, - title: this.$t('copyOf', { title: this.page.title }), - handle: '', - } - - const { namespaceID = NoID } = this.namespace - this.createPage({ namespaceID, ...page }) - .then(page => { - this.page = new compose.Page(page) - const { pageID = '' } = page - this.$router.push({ name: 'admin.pages.edit', params: { pageID } }) - }) - .catch(this.toastErrorHandler(this.$t('notification:page.cloneFailed'))) - }, }, }