UNPKG

@silexlabs/silex

Version:

Free and easy website builder for everyone.

215 lines (189 loc) 6.64 kB
import { ClientConfig } from '../../config' import { CMS_SETTINGS_SECTION_ID, EleventyPluginOptions, Silex11tyPluginWebsiteSettings } from './index' import { Editor } from 'grapesjs' import { html, render } from 'lit-html' import { COMMAND_PREVIEW_REFRESH, COMMAND_REFRESH, DATA_SOURCE_DATA_LOAD_END, getState, getValue, toExpression, setPreviewIndex, Property } from '@silexlabs/grapesjs-data-source' import { TemplateResult } from 'lit-html' import { ClientEvent } from '../../events' import { cmdOpenSettings } from '../settings' import { updatePaginationStates } from './states' import { debounce } from '../../utils' // Add CSS for collection pages document.querySelector('head')?.insertAdjacentHTML('beforeend', ` <style> .pages__empty { padding: 16px; text-align: center; color: #888; font-size: 12px; font-style: italic; } .pages__page { cursor: pointer; } .pages__page:hover { background-color: rgba(255, 255, 255, 0.1); } </style> `) let currentPage = 0 export const EVENT_UPDATE_PAGE_LIST = 'update:collection:pages:list' export default function (editor: Editor, opts: EleventyPluginOptions): void { let done = false editor.once(` ${ ClientEvent.STARTUP_END } storage:end:load `, (...args) => { if (done) throw new Error('FIXME: this should never happen') done = true if (!opts.enable11ty) return // Do not add the settings if 11ty is disabled const pagesContainer = editor.Panels.getPanel('project-bar-container') ?.view ?.el ?.querySelector('.page-panel-container') const container = document.createElement('div') pagesContainer?.appendChild(container) // Listen for data changes and page selection editor.on(` ${ DATA_SOURCE_DATA_LOAD_END } storage:load:end page `, debounce<() => void>(() => { currentPage = 0 renderCollectionPageList(editor, container) })) editor.on(` ${ EVENT_UPDATE_PAGE_LIST } `, debounce<() => void>(() => { renderCollectionPageList(editor, container) editor.runCommand(COMMAND_PREVIEW_REFRESH) })) // Initial render renderCollectionPageList(editor, container) }) } function renderCollectionPageList(editor: Editor, container: HTMLElement) { // Guard: Ensure Pages exist, there are pages, and a selected page has a main component const pages = editor.Pages if ( !pages || pages.getAll().length === 0 || !pages.getSelected()?.getMainComponent() ) { return } render(getHtml(editor), container) } function getHtml(editor: Editor): TemplateResult { const groups = getCollectionData(editor) const result = html` <header class="project-bar__panel-header"> <h3 class="project-bar__panel-header-title">Collection Pages</h3> </header> <div class="pages__wrapper"> <section class="pages"> <main class="pages__main"> <div class="pages__list"> ${groups.length === 0 ? html`<div class="pages__empty"> No collection items found.&nbsp; <a href="#" @click=${(event: MouseEvent) => { event.preventDefault() editor.runCommand(cmdOpenSettings, { page: editor.Pages.getSelected(), sectionId: CMS_SETTINGS_SECTION_ID, }) }} > Add pagination data in the page settings </a> </div>` : groups.map((items, index) => { // Temporary pagination to this particular page updatePaginationStates(editor, index, true) return html` <div class="pages__page ${index === currentPage ? 'pages__page-selected' : ''}" data-item-index="${index}" @click=${() => handleItemClick(editor, index)} > <div class="pages__page-name"> ${getItemDisplayName(editor, index)} </div> ${index === currentPage ? html`<i class="pages__icon pages__remove-btn"></i>` : ''} </div> ` }) } </div> </main> </section> </div> ` if (groups.length > 0) { // Reset to current page updatePaginationStates(editor, currentPage, true) } return result } function getCollectionData(editor: Editor): unknown[][] { const page = editor.Pages.getSelected() const body = page?.getMainComponent() if (!body) return const settings = page?.get('settings') as Silex11tyPluginWebsiteSettings | undefined const pageData = toExpression(settings?.eleventyPageData) as (Property[] | null) const pageSize = parseInt(settings?.eleventyPageSize || '1') if (pageData && pageData.length > 0) { const rawData = getValue(pageData, body as never, false) if (Array.isArray(rawData) && rawData.length > 0) { // Group rawData into chunks of size groupBy const grouped: unknown[][] = [] for (let i = 0; i < rawData.length; i += pageSize) { grouped.push(rawData.slice(i, i + pageSize)) } return grouped } } return [] } function getItemDisplayName(editor: Editor, index: number): string { try { const page = editor.Pages.getSelected() const settings = page?.get('settings') as Silex11tyPluginWebsiteSettings | undefined const body = page?.getMainComponent() if (!body) return `Page ${index + 1}` // Try SEO title first if (settings?.eleventySeoTitle) { const titleExpression = toExpression(settings.eleventySeoTitle) if (Array.isArray(titleExpression) && titleExpression.length > 0) { const title = getValue(titleExpression, body, false) if (typeof title === 'string' && title.trim()) return title } } // Try permalink second if (settings?.eleventyPermalink) { const permalinkExpression = toExpression(settings.eleventyPermalink) if (Array.isArray(permalinkExpression) && permalinkExpression.length > 0) { const permalink = getValue(permalinkExpression, body, false) if (typeof permalink === 'string' && permalink.trim()) return permalink } } // Final fallback to index-based name (1-indexed) return `Page ${index + 1}` } catch (e) { console.error('Error generating display name for item:', e) // Final fallback to index-based name (1-indexed) return `Page ${index + 1}` } } function handleItemClick(editor: Editor, index: number) { const page = editor.Pages.getSelected() const body = page?.getMainComponent() currentPage = index if (!body) return // Trigger the canvas refresh editor.trigger(EVENT_UPDATE_PAGE_LIST) // editor.Canvas.refresh() }