Update multi page layout interaction with tabs block
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
<vue-select
|
||||
v-model="selectedExistingBlock"
|
||||
:get-option-label="getBlockLabel"
|
||||
:get-option-key="b => b.blockID"
|
||||
:options="existingBlocks"
|
||||
:calculate-position="calculateDropdownPosition"
|
||||
placeholder="Blocks from other layouts"
|
||||
|
||||
@@ -109,7 +109,7 @@ export default {
|
||||
},
|
||||
|
||||
drillDownOptions () {
|
||||
return this.page.blocks.filter(({ blockID, kind, options = {} }) => kind === 'RecordList' && blockID !== NoID && options.moduleID === this.selectedChartModuleID)
|
||||
return this.blocks.filter(({ blockID, kind, options = {} }) => kind === 'RecordList' && blockID !== NoID && options.moduleID === this.selectedChartModuleID)
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -836,8 +836,8 @@ export default {
|
||||
disableInlineEditor () {
|
||||
const thisModuleID = this.options.moduleID
|
||||
|
||||
// Finds another inline editor block with the same recordListModulea as this one
|
||||
const otherInlineWithSameModule = !!this.page.blocks.find(({ kind, options }, index) => {
|
||||
// Finds another inline editor block with the same recordListModule as this one
|
||||
const otherInlineWithSameModule = this.blocks.some(({ kind, options }, index) => {
|
||||
if (this.blockIndex !== index) {
|
||||
return kind === 'RecordList' && options.editable && options.moduleID === thisModuleID
|
||||
}
|
||||
|
||||
@@ -82,16 +82,16 @@ export default {
|
||||
computed: {
|
||||
tabbedBlocks () {
|
||||
return this.block.options.tabs.map(({ blockID, title }) => {
|
||||
let block = this.page.blocks.find(b => fetchID(b) === blockID)
|
||||
block = block ? compose.PageBlockMaker(block) : undefined
|
||||
let block = this.blocks.find(b => fetchID(b) === blockID)
|
||||
|
||||
// Blocks should display as Plain, to avoid card shadow/border
|
||||
if (block) {
|
||||
block.style.wrap.kind = 'Plain'
|
||||
block = compose.PageBlockMaker(block)
|
||||
}
|
||||
|
||||
return {
|
||||
block: block ? compose.PageBlockMaker(block) : undefined,
|
||||
block,
|
||||
title,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -168,8 +168,7 @@
|
||||
id="popover-edit"
|
||||
size="sm"
|
||||
variant="light"
|
||||
:title="blockEditDisabled ? $t('tabs.tooltip.editDisabled') : $t('tabs.tooltip.edit')"
|
||||
:disabled="blockEditDisabled"
|
||||
:title="$t('tabs.tooltip.edit')"
|
||||
class="d-flex align-items-center justify-content-center"
|
||||
style="width: 40px;"
|
||||
@click="editBlock(tab.blockID)"
|
||||
@@ -300,11 +299,10 @@ export default {
|
||||
|
||||
computed: {
|
||||
blockOptions () {
|
||||
return this.page.blocks.filter(b => b.kind !== 'Tabs').map(b => ({ ...b, value: fetchID(b) }))
|
||||
},
|
||||
|
||||
blockEditDisabled () {
|
||||
return this.page.blocks.find(b => fetchID(b) === fetchID(this.block)) === undefined
|
||||
return [
|
||||
...this.page.blocks.filter(({ blockID, kind }) => kind !== 'Tabs' && !this.blocks.some(b => b.blockID === blockID)),
|
||||
...this.blocks.filter(b => b.kind !== 'Tabs'),
|
||||
].map(b => ({ ...b, value: fetchID(b) }))
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
|
||||
blocks: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
block: {
|
||||
type: compose.PageBlock,
|
||||
required: true,
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
slot-scope="{ boundingRect, block, index }"
|
||||
>
|
||||
<page-block
|
||||
v-bind="{ ...$attrs, block, page, boundingRect, blockIndex: index }"
|
||||
v-bind="{ ...$attrs }"
|
||||
:page="page"
|
||||
:blocks="page.blocks"
|
||||
:block="block"
|
||||
:bounding-rect="boundingRect"
|
||||
:block-index="index"
|
||||
class="p-2"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
|
||||
@@ -67,17 +67,16 @@ export default function (ComposeAPI) {
|
||||
})
|
||||
},
|
||||
|
||||
async findByID ({ commit, getters }, { namespaceID, pageLayoutID, force = false } = {}) {
|
||||
async findByID ({ commit, getters }, { namespaceID, pageID, pageLayoutID, force = false } = {}) {
|
||||
if (!force) {
|
||||
const oldItem = getters.getByID(pageLayoutID)
|
||||
if (oldItem) {
|
||||
return new Promise((resolve) => resolve(oldItem))
|
||||
}
|
||||
return new Promise((resolve) => resolve(oldItem))
|
||||
}
|
||||
|
||||
commit(types.pending)
|
||||
return ComposeAPI.pageLayoutRead({ namespaceID, pageLayoutID }).then(pl => {
|
||||
return ComposeAPI.pageLayoutRead({ namespaceID, pageID, pageLayoutID }).then(pl => {
|
||||
const pageLayout = new compose.PageLayout(pl)
|
||||
|
||||
commit(types.updateSet, [pageLayout])
|
||||
return pageLayout
|
||||
}).finally(() => {
|
||||
@@ -122,7 +121,7 @@ export default function (ComposeAPI) {
|
||||
})
|
||||
},
|
||||
|
||||
async delete ({ commit, dispatch }, item) {
|
||||
async delete ({ commit }, item) {
|
||||
commit(types.pending)
|
||||
return ComposeAPI.pageLayoutDelete(item).then(() => {
|
||||
commit(types.removeFromSet, [item])
|
||||
|
||||
@@ -136,10 +136,11 @@
|
||||
...$props
|
||||
}"
|
||||
:page="page"
|
||||
:module="module"
|
||||
:record="record"
|
||||
:blocks="usedBlocks"
|
||||
:block-index="index"
|
||||
:block="block"
|
||||
:module="module"
|
||||
:record="record"
|
||||
:bounding-rect="boundingRect"
|
||||
editable
|
||||
class="p-2"
|
||||
@@ -183,6 +184,7 @@
|
||||
:namespace="namespace"
|
||||
:module="module"
|
||||
:page="page"
|
||||
:blocks="usedBlocks"
|
||||
:block.sync="editor.block"
|
||||
:record="record"
|
||||
/>
|
||||
@@ -202,10 +204,12 @@
|
||||
:namespace="namespace"
|
||||
:module="module"
|
||||
:page="page"
|
||||
:blocks="usedBlocks"
|
||||
:block.sync="editor.block"
|
||||
:block-index="editor.index"
|
||||
:record="record"
|
||||
/>
|
||||
|
||||
<template #modal-footer="{ cancel }">
|
||||
<c-input-confirm
|
||||
size="md"
|
||||
@@ -242,14 +246,13 @@
|
||||
<portal to="admin-toolbar">
|
||||
<editor-toolbar
|
||||
:back-link="{name: 'admin.pages'}"
|
||||
:hide-delete="hideDelete"
|
||||
:hide-save="!page.canUpdatePage"
|
||||
:disable-clone="disableClone"
|
||||
:disable-save="processing"
|
||||
:clone-tooltip="cloneTooltip"
|
||||
@save="handleSave()"
|
||||
@delete="handleDeletePage"
|
||||
@saveAndClose="handleSave({ closeOnSuccess: true })"
|
||||
@save="handleSaveLayout()"
|
||||
@delete="handleDeleteLayout"
|
||||
@saveAndClose="handleSaveLayout({ closeOnSuccess: true })"
|
||||
@clone="handleClone()"
|
||||
>
|
||||
<b-button
|
||||
@@ -262,29 +265,6 @@
|
||||
>
|
||||
+ {{ $t('build.addBlock') }}
|
||||
</b-button>
|
||||
|
||||
<template #delete>
|
||||
<b-dropdown
|
||||
v-if="showDeleteDropdown"
|
||||
data-test-id="dropdown-delete"
|
||||
size="lg"
|
||||
variant="danger"
|
||||
:text="$t('general:label.delete')"
|
||||
>
|
||||
<b-dropdown-item
|
||||
data-test-id="dropdown-item-delete-update-parent-of-sub-pages"
|
||||
@click="handleDeletePage('rebase')"
|
||||
>
|
||||
{{ $t('delete.rebase') }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
data-test-id="dropdown-item-delete-sub-pages"
|
||||
@click="handleDeletePage('cascade')"
|
||||
>
|
||||
{{ $t('delete.cascade') }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</template>
|
||||
</editor-toolbar>
|
||||
</portal>
|
||||
|
||||
@@ -426,10 +406,6 @@ export default {
|
||||
return this.hasChildren || !this.page.canDeletePage || !!this.page.deletedAt
|
||||
},
|
||||
|
||||
showDeleteDropdown () {
|
||||
return this.hasChildren && this.page.canDeletePage && !this.page.deletedAt
|
||||
},
|
||||
|
||||
disableClone () {
|
||||
return !!this.module
|
||||
},
|
||||
@@ -439,7 +415,30 @@ export default {
|
||||
},
|
||||
|
||||
selectableExistingBlocks () {
|
||||
return this.page.blocks.filter(({ blockID }) => !this.blocks.some(b => b.blockID === blockID))
|
||||
return this.page.blocks.filter(({ blockID }) => !this.usedBlocks.some(b => b.blockID === blockID))
|
||||
},
|
||||
|
||||
// Blocks used on page or tabbed
|
||||
usedBlocks () {
|
||||
const tabbedIDs = new Set()
|
||||
|
||||
// If tab is not on layout include it
|
||||
this.blocks.forEach(block => {
|
||||
if (block.kind !== 'Tabs') return
|
||||
|
||||
const { tabs = [] } = block.options
|
||||
tabs.forEach(tab => {
|
||||
const { blockID } = this.page.blocks.find(({ blockID }) => blockID === tab.blockID) || {}
|
||||
if (blockID) {
|
||||
tabbedIDs.add(blockID)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return [
|
||||
...this.page.blocks.filter(({ blockID }) => tabbedIDs.has(blockID)),
|
||||
...this.blocks.filter(({ blockID }) => !tabbedIDs.has(blockID)),
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
@@ -501,13 +500,18 @@ export default {
|
||||
findLayoutByID: 'pageLayout/findByID',
|
||||
findLayoutsByPageID: 'pageLayout/findByPageID',
|
||||
updatePageLayout: 'pageLayout/update',
|
||||
deletePageLayout: 'pageLayout/delete',
|
||||
}),
|
||||
|
||||
fulfilEditRequest (blockID) {
|
||||
// this ensures whatever changes in tabs is not lost before we lose its configurator
|
||||
// because we are reusing that modal component
|
||||
this.updateBlocks()
|
||||
this.blocks.find((block, i) => fetchID(block) === blockID && this.editBlock(i))
|
||||
|
||||
const blockIndex = this.blocks.findIndex(block => fetchID(block) === blockID)
|
||||
if (blockIndex > -1) {
|
||||
this.editBlock(blockIndex)
|
||||
}
|
||||
},
|
||||
|
||||
fulfilCreateRequest (block) {
|
||||
@@ -542,7 +546,9 @@ export default {
|
||||
},
|
||||
|
||||
editBlock (index = undefined) {
|
||||
this.editor = { index, block: compose.PageBlockMaker(this.blocks[index]) }
|
||||
this.$nextTick(() => {
|
||||
this.editor = { index, block: compose.PageBlockMaker(this.blocks[index]) }
|
||||
})
|
||||
},
|
||||
|
||||
deleteBlock (index) {
|
||||
@@ -586,7 +592,16 @@ export default {
|
||||
updateBlocks (block = this.editor.block) {
|
||||
block = compose.PageBlockMaker(block)
|
||||
|
||||
if (this.editor.index !== undefined) {
|
||||
const creatingTabbedBlock = this.editor.block.kind !== block.kind
|
||||
|
||||
if (creatingTabbedBlock) {
|
||||
this.$root.$emit('builder-createRequestFulfilled', {
|
||||
blockID: fetchID(block),
|
||||
title: block.title,
|
||||
})
|
||||
}
|
||||
|
||||
if (this.editor.index !== undefined && !creatingTabbedBlock) {
|
||||
const oldBlock = this.blocks[this.editor.index]
|
||||
|
||||
if (oldBlock.meta.hidden === true && this.editor.block.meta.hidden === false) {
|
||||
@@ -594,16 +609,8 @@ export default {
|
||||
this.calculateNewBlockPosition(block)
|
||||
}
|
||||
|
||||
if (this.editor.block.kind !== block.kind) {
|
||||
this.blocks.push(block)
|
||||
this.$root.$emit('builder-createRequestFulfilled', {
|
||||
blockID: fetchID(block),
|
||||
title: block.title,
|
||||
})
|
||||
} else {
|
||||
this.blocks.splice(this.editor.index, 1, block)
|
||||
this.unsavedBlocks.add(this.editor.index)
|
||||
}
|
||||
this.blocks.splice(this.editor.index, 1, block)
|
||||
this.unsavedBlocks.add(this.editor.index)
|
||||
} else {
|
||||
this.blocks.push(block)
|
||||
this.unsavedBlocks.add(this.blocks.length - 1)
|
||||
@@ -612,7 +619,14 @@ export default {
|
||||
if (block.kind === 'Tabs') {
|
||||
block.options.tabs.forEach((tab) => {
|
||||
if (!tab.blockID) return
|
||||
this.blocks.find(b => fetchID(b) === tab.blockID).meta.hidden = true
|
||||
let tabbedBlock = this.blocks.find(b => fetchID(b) === tab.blockID)
|
||||
|
||||
if (!tabbedBlock) {
|
||||
tabbedBlock = this.page.blocks.find(({ blockID }) => blockID === tab.blockID)
|
||||
this.blocks.push(tabbedBlock)
|
||||
}
|
||||
|
||||
tabbedBlock.meta.hidden = true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -663,7 +677,7 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
async handleSave ({ closeOnSuccess = false, previewOnSuccess = false } = {}) {
|
||||
async handleSaveLayout ({ closeOnSuccess = false, previewOnSuccess = false } = {}) {
|
||||
const { namespaceID } = this.namespace
|
||||
|
||||
// Record blocks
|
||||
@@ -674,7 +688,7 @@ export default {
|
||||
|
||||
// Inline record lists
|
||||
const queue = []
|
||||
this.blocks.forEach((b, index) => {
|
||||
this.usedBlocks.forEach((b, index) => {
|
||||
if (b.kind === 'RecordList' && b.options.editable) {
|
||||
const p = new Promise((resolve) => {
|
||||
const recordListUniqueID = [this.page.pageID, (this.record || {}).recordID || NoID, b.blockID].map(v => v || NoID).join('-')
|
||||
@@ -699,12 +713,8 @@ export default {
|
||||
]).then(([page, layout]) => {
|
||||
const blocks = [
|
||||
...page.blocks.filter(({ blockID }) => {
|
||||
if (this.blocks.some(b => b.blockID === blockID)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if block exists in any other layout, if not delete it permanently
|
||||
return this.layouts.some(({ blocks }) => blocks.some(b => b.blockID === blockID))
|
||||
return !this.blocks.some(b => b.blockID === blockID) && this.layouts.some(({ pageLayoutID, blocks }) => pageLayoutID !== layout.pageLayoutID && blocks.some(b => b.blockID === blockID))
|
||||
}),
|
||||
...this.blocks,
|
||||
]
|
||||
@@ -717,7 +727,7 @@ export default {
|
||||
blockID = (page.blocks.find(block => block.meta.tempID === meta.tempID) || {}).blockID
|
||||
}
|
||||
|
||||
return { blockID, xywh }
|
||||
return { blockID, xywh, meta }
|
||||
})
|
||||
layout = await this.updatePageLayout({ ...layout, blocks })
|
||||
return { page, layout }
|
||||
@@ -728,7 +738,7 @@ export default {
|
||||
this.fetchPageLayouts()
|
||||
this.$route.query.layoutID = layout.pageLayoutID
|
||||
this.unsavedBlocks.clear()
|
||||
this.toastSuccess(this.$t('notification:page.saved'))
|
||||
this.toastSuccess(this.$t('notification:page.page-layout.save.success'))
|
||||
|
||||
if (closeOnSuccess) {
|
||||
this.$router.push({ name: 'admin.pages' })
|
||||
@@ -737,7 +747,7 @@ export default {
|
||||
}
|
||||
}).finally(() => {
|
||||
this.processing = false
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:page.saveFailed')))
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.save.failed')))
|
||||
},
|
||||
|
||||
validateModuleFieldSelection (module, page) {
|
||||
@@ -764,10 +774,15 @@ export default {
|
||||
return !req.size
|
||||
},
|
||||
|
||||
handleDeletePage (strategy = 'abort') {
|
||||
this.deletePage({ ...this.page, strategy }).then(() => {
|
||||
this.$router.push({ name: 'admin.pages' })
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:page.deleteFailed')))
|
||||
handleDeleteLayout () {
|
||||
this.processing = true
|
||||
|
||||
this.deletePageLayout({ ...this.layout }).then(() => {
|
||||
this.setLayout()
|
||||
this.toastSuccess(this.$t('notification:page.page-layout.delete.success'))
|
||||
}).finally(() => {
|
||||
this.processing = false
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:page.page-layout.delete.failed')))
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -835,24 +850,44 @@ export default {
|
||||
async setLayout () {
|
||||
if (this.$route.query.layoutID) {
|
||||
const { namespaceID } = this.namespace
|
||||
this.layout = await this.findLayoutByID({ namespaceID, pageLayoutID: this.$route.query.layoutID })
|
||||
} else {
|
||||
this.layout = this.layouts[0]
|
||||
if (!this.layout) {
|
||||
this.toastWarning('No layout, create one to edit it')
|
||||
return this.$router.push(this.pageEditor)
|
||||
}
|
||||
this.layout = await this.findLayoutByID({ namespaceID, pageID: this.pageID, pageLayoutID: this.$route.query.layoutID })
|
||||
}
|
||||
|
||||
this.layout = this.layout || this.layouts[0]
|
||||
if (!this.layout) {
|
||||
this.toastWarning('No layout, create one to edit it')
|
||||
return this.$router.push(this.pageEditor)
|
||||
}
|
||||
|
||||
if (this.$route.query.layoutID !== this.layout.pageLayoutID) {
|
||||
this.$router.replace({ ...this.$route, query: { ...this.$route.query, layoutID: this.layout.pageLayoutID } })
|
||||
}
|
||||
|
||||
this.unsavedBlocks.clear()
|
||||
|
||||
const tempBlocks = []
|
||||
const { blocks = [] } = this.layout || {}
|
||||
this.blocks = blocks.map(({ blockID, xywh }) => {
|
||||
const block = this.page.blocks.find(b => fetchID(b) === blockID)
|
||||
|
||||
blocks.forEach(({ blockID, xywh }) => {
|
||||
let block = this.page.blocks.find(b => b.blockID === blockID)
|
||||
block.xywh = xywh
|
||||
return block
|
||||
tempBlocks.push(block)
|
||||
|
||||
if (block.kind === 'Tabs') {
|
||||
const { tabs = [] } = block.options
|
||||
tabs.forEach(tab => {
|
||||
if (blocks.some(b => b.blockID === tab.blockID)) return
|
||||
|
||||
block = this.page.blocks.find(b => b.blockID === tab.blockID)
|
||||
|
||||
if (block) {
|
||||
tempBlocks.push(block)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.blocks = tempBlocks
|
||||
},
|
||||
|
||||
switchLayout (layoutID) {
|
||||
|
||||
@@ -258,6 +258,7 @@
|
||||
|
||||
<b-button
|
||||
variant="primary"
|
||||
:disabled="layout.pageLayoutID === '0'"
|
||||
class="d-flex align-items-center"
|
||||
:to="{ name: 'admin.pages.builder', query: { layoutID: layout.pageLayoutID} }"
|
||||
>
|
||||
@@ -639,7 +640,7 @@ export default {
|
||||
return this.fetchAttachments()
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:page.loadFailed')))
|
||||
|
||||
this.fetchLayouts({ namespaceID, pageID }).catch(this.toastErrorHandler(this.$t('notification:page.loadFailed')))
|
||||
this.fetchLayouts().catch(this.toastErrorHandler(this.$t('notification:page.loadFailed')))
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -662,8 +663,9 @@ export default {
|
||||
deletePageLayout: 'pageLayout/delete',
|
||||
}),
|
||||
|
||||
async fetchLayouts (payload) {
|
||||
return this.findLayoutsByPageID(payload).then(layouts => {
|
||||
async fetchLayouts () {
|
||||
const { namespaceID } = this.namespace
|
||||
return this.findLayoutsByPageID({ namespaceID, pageID: this.pageID }).then(layouts => {
|
||||
this.layouts = layouts.map(layout => new compose.PageLayout(layout))
|
||||
})
|
||||
},
|
||||
@@ -704,16 +706,16 @@ export default {
|
||||
},
|
||||
|
||||
async handleSaveLayouts () {
|
||||
return Promise.all([
|
||||
...[...this.deletedLayouts].map(this.deletePageLayout),
|
||||
...this.layouts.map(layout => {
|
||||
// Delete first so old deleted handles don't interfere with new identical ones
|
||||
return Promise.all([...this.deletedLayouts].map(this.deletePageLayout)).then(() => {
|
||||
return Promise.all(this.layouts.map(layout => {
|
||||
if (layout.pageLayoutID === NoID) {
|
||||
return this.createPageLayout(layout)
|
||||
} else if (layout.meta.updated) {
|
||||
return this.updatePageLayout(layout)
|
||||
}
|
||||
}),
|
||||
])
|
||||
}))
|
||||
})
|
||||
},
|
||||
|
||||
handleSave ({ closeOnSuccess = false } = {}) {
|
||||
@@ -727,7 +729,7 @@ export default {
|
||||
this.page.config.navItem.icon = icon
|
||||
return this.updatePage({ namespaceID, ...this.page, resourceTranslationLanguage }).then((page) => {
|
||||
this.page = page.clone()
|
||||
return this.handleSaveLayouts()
|
||||
return this.handleSaveLayouts().then(this.fetchLayouts)
|
||||
})
|
||||
}).then(() => {
|
||||
this.deletedLayouts = new Set()
|
||||
|
||||
@@ -149,7 +149,7 @@ export default {
|
||||
const { namespaceID } = this.namespace
|
||||
this.page.weight = this.tree.length
|
||||
this.createPage({ ...this.page, namespaceID }).then(({ pageID }) => {
|
||||
const pageLayout = new compose.PageLayout({ namespaceID, pageID })
|
||||
const pageLayout = new compose.PageLayout({ namespaceID, pageID, meta: { title: 'Primary' } })
|
||||
return this.createPageLayout(pageLayout).then(() => {
|
||||
this.$router.push({ name: 'admin.pages.edit', params: { pageID } })
|
||||
})
|
||||
|
||||
@@ -68,7 +68,7 @@ export class PageLayout {
|
||||
Apply(this, pl, String, 'handle')
|
||||
Apply(this, pl, ISO8601Date, 'createdAt', 'updatedAt', 'deletedAt')
|
||||
|
||||
this.blocks = (pl.blocks || []).map(({ blockID, xywh }) => ({ blockID, xywh }))
|
||||
this.blocks = (pl.blocks || []).map(({ blockID, xywh, meta }) => ({ blockID, xywh, meta }))
|
||||
|
||||
if (pl.meta) {
|
||||
this.meta = { ...this.meta, ...pl.meta }
|
||||
|
||||
@@ -98,6 +98,13 @@ page:
|
||||
blockWaiting: There is a page-block awaiting
|
||||
copyFailed: Could not copy block {{reason}}
|
||||
invalidBlock: Not a valid page-block
|
||||
page-layout:
|
||||
save:
|
||||
success: Layout saved
|
||||
failed: Failed to save layout
|
||||
delete:
|
||||
success: Layout deleted
|
||||
failed: Failed to delete layout
|
||||
record:
|
||||
createFailed: Could not create record
|
||||
deleteFailed: Could not delete record
|
||||
|
||||
Reference in New Issue
Block a user