diff --git a/client/web/compose/src/components/Admin/EditorToolbar.vue b/client/web/compose/src/components/Admin/EditorToolbar.vue
index 7244746d1..ab201f31c 100644
--- a/client/web/compose/src/components/Admin/EditorToolbar.vue
+++ b/client/web/compose/src/components/Admin/EditorToolbar.vue
@@ -47,6 +47,8 @@
>
{{ $t('label.delete') }}
+
+
{{ $t('label.saveAsCopy') }}
+
{{ $t('label.saveAndClose') }}
+
+ {{ $t('build.addBlock') }}
+
+
+
+
+ {{ $t('build.saveAsCopy.ref') }}
+
+
+ {{ $t('build.saveAsCopy.noRef') }}
+
+
+
@@ -676,7 +701,7 @@ export default {
appendBlock (block, msg) {
this.calculateNewBlockPosition(block)
- this.editor = { index: undefined, block: compose.PageBlockMaker(block) }
+ this.editor = { index: undefined, block }
this.updateBlocks()
if (!this.editor) {
@@ -735,7 +760,7 @@ export default {
return !req.size
},
- async handleSaveLayout ({ closeOnSuccess = false, previewOnSuccess = false } = {}) {
+ async handleSaveLayout ({ closeOnSuccess = false, previewOnSuccess = false, alert = true } = {}) {
const { namespaceID } = this.namespace
// Record blocks
@@ -788,26 +813,27 @@ export default {
layout = await this.updatePageLayout({ ...layout, blocks })
return { page, layout }
})
- }).then(({ page, layout }) => {
- this.page = new compose.Page(page)
- this.layout = new compose.PageLayout(layout)
- this.unsavedBlocks.clear()
-
- this.toastSuccess(this.$t('notification:page.page-layout.save.success'))
-
+ }).then(async ({ page, layout }) => {
if (closeOnSuccess) {
this.$router.push(this.previousPage || { name: 'admin.pages' })
return
}
- return this.fetchPageLayouts()
+ if (alert) {
+ this.toastSuccess(this.$t('notification:page.page-layout.save.success'))
+ }
+
+ this.page = new compose.Page(page)
+ await this.fetchPageLayouts()
+ this.setLayout(layout.pageLayoutID)
}).finally(() => {
this.processing = false
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.save.failed')))
},
- handleCloneLayout () {
+ async handleCloneLayout ({ ref = false }) {
this.processing = true
+ this.processingLayout = true
const layout = {
...this.layout.clone(),
@@ -817,13 +843,46 @@ export default {
layout.meta.title = `${this.$t('copyOf')}${layout.meta.title}`
- this.createPageLayout(layout).then(({ pageLayoutID }) => {
- return this.fetchPageLayouts().then(() => {
- this.setLayout(pageLayoutID)
- this.toastSuccess(this.$t('notification:page.page-layout.clone.success'))
+ // If we are cloning a layout with references, we need to clone the blocks
+ if (!ref) {
+ const oldBlockIDs = {}
+ layout.blocks = []
+
+ // Sort based on if tab or not
+ this.blocks = this.blocks.toSorted((a, b) => {
+ if (a.kind === 'Tabs' && b.kind !== 'Tabs') {
+ return 1 // Move 'Tabs' to the end
+ } else if (a.kind !== 'Tabs' && b.kind === 'Tabs') {
+ return -1 // Keep 'Tabs' before other elements
+ } else {
+ return 0 // No change in order
+ }
+ }).map(block => {
+ const oldBlockID = block.blockID
+
+ if (block.kind === 'Tabs') {
+ block.options.tabs = block.options.tabs.map(tab => {
+ tab.blockID = oldBlockIDs[tab.blockID]
+ return tab
+ })
+ }
+
+ block = block.clone()
+ oldBlockIDs[oldBlockID] = block.meta.tempID
+
+ return block
})
+ }
+
+ this.createPageLayout(layout).then(layout => {
+ this.layout = layout
+ this.layouts.push({ ...layout, label: layout.meta.title || layout.handle || layout.pageLayoutID })
+ return this.handleSaveLayout({ alert: false })
+ }).then(() => {
+ this.toastSuccess(this.$t('notification:page.page-layout.clone.success'))
}).finally(() => {
this.processing = false
+ this.processingLayout = false
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.clone.failed')))
},
@@ -884,7 +943,7 @@ export default {
const paste = (event.clipboardData || window.clipboardData).getData('text')
// Doing this to handle JSON parse error
try {
- const block = JSON.parse(paste)
+ const block = compose.pageBlockMaker(JSON.parse(paste))
const valid = this.isValid(block)
if (valid) {
diff --git a/lib/js/src/compose/types/page-block/base.ts b/lib/js/src/compose/types/page-block/base.ts
index 5b2cf9ad8..0ac584f34 100644
--- a/lib/js/src/compose/types/page-block/base.ts
+++ b/lib/js/src/compose/types/page-block/base.ts
@@ -1,6 +1,7 @@
import { merge } from 'lodash'
import { Apply, NoID } from '../../../cast'
import { generateUID } from '../../helpers/idgen'
+import { PageBlockMaker } from '.'
interface PageBlockStyleVariants {
[_: string]: string;
@@ -105,7 +106,7 @@ export class PageBlock {
}
clone (): PageBlockInput {
- return { ...JSON.parse(JSON.stringify(this)), blockID: NoID, meta: { tempID: '' } }
+ return PageBlockMaker({ ...JSON.parse(JSON.stringify(this)), blockID: NoID, meta: { tempID: generateUID() } })
}
}
diff --git a/locale/en/corteza-webapp-compose/page.yaml b/locale/en/corteza-webapp-compose/page.yaml
index c00f0296a..97ce32b02 100644
--- a/locale/en/corteza-webapp-compose/page.yaml
+++ b/locale/en/corteza-webapp-compose/page.yaml
@@ -61,6 +61,9 @@ build:
addBlock: Add block
selectBlockTitle: Select type of the new block
unsavedChanges: Unsaved changes will be lost. Do you wish to leave the page?
+ saveAsCopy:
+ ref: With references
+ noRef: Without references
createLabel: Create page
edit:
create: Create page