Add option to save page layout as copy with or without references
This commit is contained in:
parent
c89df1c846
commit
d64ed2b456
@ -47,6 +47,8 @@
|
|||||||
>
|
>
|
||||||
{{ $t('label.delete') }}
|
{{ $t('label.delete') }}
|
||||||
</c-input-confirm>
|
</c-input-confirm>
|
||||||
|
|
||||||
|
<slot name="saveAsCopy" />
|
||||||
<b-button
|
<b-button
|
||||||
v-if="!hideClone"
|
v-if="!hideClone"
|
||||||
data-test-id="button-clone"
|
data-test-id="button-clone"
|
||||||
@ -59,6 +61,7 @@
|
|||||||
>
|
>
|
||||||
{{ $t('label.saveAsCopy') }}
|
{{ $t('label.saveAsCopy') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
<b-button
|
<b-button
|
||||||
v-if="!hideSave"
|
v-if="!hideSave"
|
||||||
data-test-id="button-save-and-close"
|
data-test-id="button-save-and-close"
|
||||||
@ -70,6 +73,7 @@
|
|||||||
>
|
>
|
||||||
{{ $t('label.saveAndClose') }}
|
{{ $t('label.saveAndClose') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
<b-button
|
<b-button
|
||||||
v-if="!hideSave"
|
v-if="!hideSave"
|
||||||
data-test-id="button-save"
|
data-test-id="button-save"
|
||||||
|
|||||||
@ -152,12 +152,9 @@ export default {
|
|||||||
if (this.record.valueErrors.set) {
|
if (this.record.valueErrors.set) {
|
||||||
this.toastWarning(this.$t('notification:record.validationWarnings'))
|
this.toastWarning(this.$t('notification:record.validationWarnings'))
|
||||||
} else {
|
} else {
|
||||||
if (isNew) {
|
this.inCreating = false
|
||||||
this.inCreating = false
|
this.inEditing = false
|
||||||
this.inEditing = false
|
this.record = record
|
||||||
} else {
|
|
||||||
this.record = record
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.showRecordModal) {
|
if (this.showRecordModal) {
|
||||||
this.$emit('handle-record-redirect', { recordID: record.recordID, recordPageID: this.page.pageID })
|
this.$emit('handle-record-redirect', { recordID: record.recordID, recordPageID: this.page.pageID })
|
||||||
|
|||||||
@ -256,10 +256,10 @@
|
|||||||
<editor-toolbar
|
<editor-toolbar
|
||||||
:hide-save="!page.canUpdatePage"
|
:hide-save="!page.canUpdatePage"
|
||||||
:processing="processing"
|
:processing="processing"
|
||||||
|
hide-clone
|
||||||
@save="handleSaveLayout()"
|
@save="handleSaveLayout()"
|
||||||
@delete="handleDeleteLayout()"
|
@delete="handleDeleteLayout()"
|
||||||
@saveAndClose="handleSaveLayout({ closeOnSuccess: true })"
|
@saveAndClose="handleSaveLayout({ closeOnSuccess: true })"
|
||||||
@clone="handleCloneLayout()"
|
|
||||||
@back="$router.push(previousPage || { name: 'admin.pages' })"
|
@back="$router.push(previousPage || { name: 'admin.pages' })"
|
||||||
>
|
>
|
||||||
<b-button
|
<b-button
|
||||||
@ -272,6 +272,31 @@
|
|||||||
>
|
>
|
||||||
+ {{ $t('build.addBlock') }}
|
+ {{ $t('build.addBlock') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
|
<template #saveAsCopy>
|
||||||
|
<b-dropdown
|
||||||
|
v-if="page.canUpdatePage"
|
||||||
|
data-test-id="dropdown-saveAsCopy"
|
||||||
|
:text="$t('general:label.saveAsCopy')"
|
||||||
|
:disabled="processing"
|
||||||
|
size="lg"
|
||||||
|
variant="light"
|
||||||
|
class="ml-2"
|
||||||
|
>
|
||||||
|
<b-dropdown-item
|
||||||
|
data-test-id="dropdown-item-saveAsCopy-ref"
|
||||||
|
@click="handleCloneLayout({ ref: true })"
|
||||||
|
>
|
||||||
|
{{ $t('build.saveAsCopy.ref') }}
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item
|
||||||
|
data-test-id="dropdown-item-saveAsCopy-noRef"
|
||||||
|
@click="handleCloneLayout({ ref: false })"
|
||||||
|
>
|
||||||
|
{{ $t('build.saveAsCopy.noRef') }}
|
||||||
|
</b-dropdown-item>
|
||||||
|
</b-dropdown>
|
||||||
|
</template>
|
||||||
</editor-toolbar>
|
</editor-toolbar>
|
||||||
</portal>
|
</portal>
|
||||||
|
|
||||||
@ -676,7 +701,7 @@ export default {
|
|||||||
appendBlock (block, msg) {
|
appendBlock (block, msg) {
|
||||||
this.calculateNewBlockPosition(block)
|
this.calculateNewBlockPosition(block)
|
||||||
|
|
||||||
this.editor = { index: undefined, block: compose.PageBlockMaker(block) }
|
this.editor = { index: undefined, block }
|
||||||
this.updateBlocks()
|
this.updateBlocks()
|
||||||
|
|
||||||
if (!this.editor) {
|
if (!this.editor) {
|
||||||
@ -735,7 +760,7 @@ export default {
|
|||||||
return !req.size
|
return !req.size
|
||||||
},
|
},
|
||||||
|
|
||||||
async handleSaveLayout ({ closeOnSuccess = false, previewOnSuccess = false } = {}) {
|
async handleSaveLayout ({ closeOnSuccess = false, previewOnSuccess = false, alert = true } = {}) {
|
||||||
const { namespaceID } = this.namespace
|
const { namespaceID } = this.namespace
|
||||||
|
|
||||||
// Record blocks
|
// Record blocks
|
||||||
@ -788,26 +813,27 @@ export default {
|
|||||||
layout = await this.updatePageLayout({ ...layout, blocks })
|
layout = await this.updatePageLayout({ ...layout, blocks })
|
||||||
return { page, layout }
|
return { page, layout }
|
||||||
})
|
})
|
||||||
}).then(({ page, layout }) => {
|
}).then(async ({ 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'))
|
|
||||||
|
|
||||||
if (closeOnSuccess) {
|
if (closeOnSuccess) {
|
||||||
this.$router.push(this.previousPage || { name: 'admin.pages' })
|
this.$router.push(this.previousPage || { name: 'admin.pages' })
|
||||||
return
|
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(() => {
|
}).finally(() => {
|
||||||
this.processing = false
|
this.processing = false
|
||||||
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.save.failed')))
|
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.save.failed')))
|
||||||
},
|
},
|
||||||
|
|
||||||
handleCloneLayout () {
|
async handleCloneLayout ({ ref = false }) {
|
||||||
this.processing = true
|
this.processing = true
|
||||||
|
this.processingLayout = true
|
||||||
|
|
||||||
const layout = {
|
const layout = {
|
||||||
...this.layout.clone(),
|
...this.layout.clone(),
|
||||||
@ -817,13 +843,46 @@ export default {
|
|||||||
|
|
||||||
layout.meta.title = `${this.$t('copyOf')}${layout.meta.title}`
|
layout.meta.title = `${this.$t('copyOf')}${layout.meta.title}`
|
||||||
|
|
||||||
this.createPageLayout(layout).then(({ pageLayoutID }) => {
|
// If we are cloning a layout with references, we need to clone the blocks
|
||||||
return this.fetchPageLayouts().then(() => {
|
if (!ref) {
|
||||||
this.setLayout(pageLayoutID)
|
const oldBlockIDs = {}
|
||||||
this.toastSuccess(this.$t('notification:page.page-layout.clone.success'))
|
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(() => {
|
}).finally(() => {
|
||||||
this.processing = false
|
this.processing = false
|
||||||
|
this.processingLayout = false
|
||||||
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.clone.failed')))
|
}).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')
|
const paste = (event.clipboardData || window.clipboardData).getData('text')
|
||||||
// Doing this to handle JSON parse error
|
// Doing this to handle JSON parse error
|
||||||
try {
|
try {
|
||||||
const block = JSON.parse(paste)
|
const block = compose.pageBlockMaker(JSON.parse(paste))
|
||||||
const valid = this.isValid(block)
|
const valid = this.isValid(block)
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { merge } from 'lodash'
|
import { merge } from 'lodash'
|
||||||
import { Apply, NoID } from '../../../cast'
|
import { Apply, NoID } from '../../../cast'
|
||||||
import { generateUID } from '../../helpers/idgen'
|
import { generateUID } from '../../helpers/idgen'
|
||||||
|
import { PageBlockMaker } from '.'
|
||||||
|
|
||||||
interface PageBlockStyleVariants {
|
interface PageBlockStyleVariants {
|
||||||
[_: string]: string;
|
[_: string]: string;
|
||||||
@ -105,7 +106,7 @@ export class PageBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clone (): PageBlockInput {
|
clone (): PageBlockInput {
|
||||||
return { ...JSON.parse(JSON.stringify(this)), blockID: NoID, meta: { tempID: '' } }
|
return PageBlockMaker({ ...JSON.parse(JSON.stringify(this)), blockID: NoID, meta: { tempID: generateUID() } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,9 @@ build:
|
|||||||
addBlock: Add block
|
addBlock: Add block
|
||||||
selectBlockTitle: Select type of the new block
|
selectBlockTitle: Select type of the new block
|
||||||
unsavedChanges: Unsaved changes will be lost. Do you wish to leave the page?
|
unsavedChanges: Unsaved changes will be lost. Do you wish to leave the page?
|
||||||
|
saveAsCopy:
|
||||||
|
ref: With references
|
||||||
|
noRef: Without references
|
||||||
createLabel: Create page
|
createLabel: Create page
|
||||||
edit:
|
edit:
|
||||||
create: Create page
|
create: Create page
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user