@silexlabs/silex
Version:
Free and easy website builder for everyone.
127 lines (116 loc) • 4.63 kB
text/typescript
import { removeState, setState, COMPONENT_NAME_PREFIX, Property, toExpression, StoredFilter, State, StoredState, StoredToken, Expression } from '@silexlabs/grapesjs-data-source'
import { Silex11tyPluginWebsiteSettings } from './index'
import { Component, Editor, Page } from 'grapesjs'
import { ClientEvent } from '../../events'
export default function(editor: Editor/*, opts: EleventyPluginOptions */): void {
editor.on('page:select page:update', () => updatePaginationStates(editor))
editor.on(ClientEvent.SETTINGS_SAVE_END, () => updatePaginationStates(editor))
}
/**
* Update pagination states for a page with the ability to control which page index to show
* @param editor - The GrapesJS editor instance
* @param pageIndex - The current page index (0-based) for pagination preview. Use 0 for publication.
*/
export function updatePaginationStates(editor: Editor, pageIndex = 0, preventTrigger = false) {
const page = editor.Pages.getSelected()
const body: Component = page?.getMainComponent() as Component
if (!body) return // This happens when the current page is deleted
// Do not show "Body's " prefix for states on the body
body.attributes.COMPONENT_NAME_PREFIX = ''
// Store pagination data in the body component
// This is for the GraphQL query to include it
const settings = page?.get('settings') as Silex11tyPluginWebsiteSettings | undefined
const pageData = toExpression(settings?.eleventyPageData) as (Property[] | null)
if (pageData && pageData.length > 0) {
try {
// Taken from the pagination object https://www.11ty.dev/docs/pagination/
// Apply pagination size limit using slice filter
const pageSize = parseInt(settings?.eleventyPageSize || '1')
const startIndex = pageIndex * pageSize
const endIndex = startIndex + pageSize
const slice = {
type: 'filter',
id: 'slice',
label: 'slice',
options: {
start: startIndex,
end: endIndex,
},
} as StoredFilter
const itemsExpression = [
...pageData,
slice,
]
if (preventTrigger) {
const itemsState: StoredState = body.attributes.publicStates.find((state: StoredFilter) => state.id === 'items')
if (!itemsState) {
if (!body.attributes.publicStates) body.attributes.publicStates = []
body.attributes.publicStates.push({
hidden: true,
label: 'Pagination items',
expression: itemsExpression,
})
} else {
itemsState.expression = itemsExpression
}
// Add or update pagination state in publicStates
const paginationState: StoredState = body.attributes.publicStates.find((state: StoredFilter) => state.id === 'pagination')
const paginationExpression = [{
label: 'Unused pagination label',
type: 'property',
propType: 'field',
fieldId: 'pagination',
dataSourceId: 'eleventy',
typeIds: ['pagination'],
kind: 'object',
}] as Expression
if (!paginationState) {
body.attributes.publicStates.push({
hidden: true,
label: 'pagination',
expression: paginationExpression,
})
} else {
paginationState.expression = paginationExpression
}
} else {
// FIXME: should we let UndoManager save?
editor.UndoManager.skip(() => {
setState(body, 'items', {
hidden: true,
label: 'Pagination items',
expression: itemsExpression,
}, true, 1)
// Update body states with the new settings
setState(body, 'pagination', {
hidden: true,
label: 'pagination',
expression: [{
label: 'Unused pagination label',
type: 'property' as const,
propType: 'field' as const,
fieldId: 'pagination',
dataSourceId: 'eleventy',
typeIds: ['pagination'],
kind: 'object' as const,
}]
}, true, 0)
})
}
} catch (e) {
console.error('Invalid JSON for eleventyPageData', e)
removeState(body, 'pagination', true)
removeState(body, 'items', true)
editor.runCommand('notifications:add', {
type: 'error',
message: 'Invalid JSON for eleventyPageData',
group: 'Errors in your settings',
componentId: body.id,
})
return
}
} else {
removeState(body, 'pagination', true)
removeState(body, 'items', true)
}
}