3
0

Add option to save page layout as copy with or without references

This commit is contained in:
Jože Fortun 2023-09-18 13:16:00 +02:00
parent c89df1c846
commit d64ed2b456
5 changed files with 88 additions and 24 deletions

View File

@ -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"

View File

@ -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 })

View File

@ -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) {

View File

@ -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() } })
} }
} }

View File

@ -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