From cc100bd0c1047d2a9fc54fcc22848af133c995bc Mon Sep 17 00:00:00 2001
From: Alex Hoyau
Date: Fri, 11 Oct 2024 11:51:52 +0300
Subject: [PATCH] more events for plugins
---
src/ts/client/events.ts | 11 +-
src/ts/client/grapesjs/PublicationManager.ts | 35 ++++--
src/ts/client/grapesjs/PublicationUi.ts | 120 ++++++++++---------
src/ts/client/grapesjs/index.ts | 2 +-
src/ts/client/grapesjs/storage.ts | 2 +-
5 files changed, 97 insertions(+), 73 deletions(-)
diff --git a/src/ts/client/events.ts b/src/ts/client/events.ts
index 88f8c43b8..104c131fd 100644
--- a/src/ts/client/events.ts
+++ b/src/ts/client/events.ts
@@ -23,12 +23,15 @@ export enum ClientEvent {
GRAPESJS_END = 'silex:grapesjs:end', /* GrapesJS is ready to be used, `editor` is passed as an argument */
// Sent on GrapesJs editor object (returned by silex.getEditor())
- PUBLISH_START = 'silex:publish:start', /* Publication starts, you can read+write {projectData, siteSettings} */
- PUBLISH_PAGE = 'silex:publish:page', /* Publication of a page, read+write { siteSettings, pageSettings, page } */
- PUBLISH_DATA = 'silex:publish:data', /* Just before we send the published data to the server, read+write all publication data, check PublicationData type in types.ts */
+ PUBLICATION_UI_OPEN = 'silex:publication-ui:open', /* The publication UI is opened, you can access it with { publicationUi } */
+ PUBLICATION_UI_CLOSE = 'silex:publication-ui:close', /* The publication UI is closed, you can access it with { publicationUi } */
+ PUBLISH_BEFORE = 'silex:publish:before', /* Publication is about to start, you can read+write {projectData, siteSettings} */
+ PUBLISH_START = 'silex:publish:start', /* Publication starts, you can read+write project data/settings, use publication manager/ui, prevent publication {projectData, siteSettings, publicationManager, prenventDefault} */
+ PUBLISH_PAGE = 'silex:publish:page', /* Publication of a page, read+write settings and page data, use publication manager and prevent publication { siteSettings, pageSettings, page, publicationManager, preventDefault } */
+ PUBLISH_DATA = 'silex:publish:data', /* Just before we send the published data to the server, read+write all publication data, check PublicationData type in types.ts { data, publicationManager } */
PUBLISH_END = 'silex:publish:end', /* Publication is over, the argument is the publication result with {success: boolean, message: string} */
PUBLISH_ERROR = 'silex:publish:error', /* Publication failed, the argument is the publication result with {success: boolean, message: string} */
- PUBLISH_LOGIN_START = 'silex:publish:login:start',
+ PUBLISH_LOGIN_START = 'silex:publish:login:start', /* The user is about to login before publication, you can read+write connector data and use publication manager and prevent publication {connector, publicationManager, preventDefault} */
PUBLISH_LOGIN_END = 'silex:publish:login:end',
ASSET_WRITE_END = 'silex:asset:write:end',
WRITE_END = 'silex:write:end',
diff --git a/src/ts/client/grapesjs/PublicationManager.ts b/src/ts/client/grapesjs/PublicationManager.ts
index 2ea399018..ccc3ab086 100644
--- a/src/ts/client/grapesjs/PublicationManager.ts
+++ b/src/ts/client/grapesjs/PublicationManager.ts
@@ -152,6 +152,13 @@ export class PublicationManager {
}
async goLogin(connector: ConnectorData) {
+ let preventDefault = false
+ this.editor.trigger(ClientEvent.PUBLISH_LOGIN_START, { connector, publicationManager: this, preventDefault: () => preventDefault = true })
+ if(preventDefault) {
+ this.status = PublicationStatus.STATUS_NONE
+ this.dialog && this.dialog.displayPending(this.job, this.status)
+ return
+ }
// Check if the user is already logged in
if(connector.isLoggedIn) {
this.settings = {
@@ -216,12 +223,12 @@ export class PublicationManager {
}
}
- async getPublicationData(projectData, siteSettings): Promise {
+ async getPublicationData(projectData, siteSettings, preventDefault: () => void): Promise {
// Data to publish
// See assetUrl.ts which is a default transformer, always present
this.setPublicationTransformers()
// Build the files structure
- const files: ClientSideFile[] = (await this.getHtmlFiles(siteSettings))
+ const files: ClientSideFile[] = (await this.getHtmlFiles(siteSettings, preventDefault))
.flatMap(file => ([{
path: file.htmlPath, // Already "transformed" in getHtmlFiles
content: file.html,
@@ -267,7 +274,7 @@ export class PublicationManager {
this.resetPublicationTransformers()
// Let plugins transform the data
transformFiles(this.editor, data)
- this.editor.trigger(ClientEvent.PUBLISH_DATA, data)
+ this.editor.trigger(ClientEvent.PUBLISH_DATA, { data, preventDefault, publicationManager: this })
// Return the data
return data
}
@@ -285,15 +292,27 @@ export class PublicationManager {
// Get the data to publish, clone the objects because plugins can change it
const projectData = { ...this.editor.getProjectData() as WebsiteData }
const siteSettings = { ...this.editor.getModel().get('settings') as WebsiteSettings }
- this.editor.trigger(ClientEvent.PUBLISH_START, {projectData, siteSettings})
+ let preventDefaultStart = false
+ this.editor.trigger(ClientEvent.PUBLISH_START, {projectData, siteSettings, preventDefault: () => preventDefaultStart = true, publicationManager: this })
+ if(preventDefaultStart) {
+ this.status = PublicationStatus.STATUS_NONE
+ this.dialog && this.dialog.displayPending(this.job, this.status)
+ return
+ }
+ // Get the data to publish
+ let preventDefaultData = false
+ const data = await this.getPublicationData(projectData, siteSettings, () => preventDefaultData = true)
+ if(preventDefaultData) {
+ this.status = PublicationStatus.STATUS_NONE
+ this.dialog && this.dialog.displayPending(this.job, this.status)
+ return
+ }
// User and where to publish
const storageUser = this.editor.getModel().get('user') as ConnectorUser
if(!storageUser) throw new Error('User not logged in to a storage connector')
if(!this.settings.connector?.connectorId) throw new Error('User not logged in to a hosting connector')
const websiteId = this.options.websiteId
const storageId = storageUser.storage.connectorId
- // Get the data to publish
- const data = await this.getPublicationData(projectData, siteSettings)
// Use the publication API
const [url, job] = await publish({
websiteId,
@@ -326,7 +345,7 @@ export class PublicationManager {
}
}
- async getHtmlFiles(siteSettings: WebsiteSettings): Promise {
+ async getHtmlFiles(siteSettings: WebsiteSettings, preventDefault): Promise {
return Promise.all(this.editor.Pages.getAll().map(async page => {
// Clone the settings because plugins can change them
siteSettings = { ...siteSettings }
@@ -352,7 +371,7 @@ export class PublicationManager {
const htmlPath = transformPath(this.editor, htmlInitialPath, ClientSideFileType.HTML)
// Let plugins transform the data
- this.editor.trigger(ClientEvent.PUBLISH_PAGE, { page, siteSettings, pageSettings })
+ this.editor.trigger(ClientEvent.PUBLISH_PAGE, { page, siteSettings, pageSettings, preventDefault, publicationManager: this })
// Useful data for HTML result
const title = getSetting('title')
diff --git a/src/ts/client/grapesjs/PublicationUi.ts b/src/ts/client/grapesjs/PublicationUi.ts
index a3c7e859d..29a7308af 100644
--- a/src/ts/client/grapesjs/PublicationUi.ts
+++ b/src/ts/client/grapesjs/PublicationUi.ts
@@ -23,6 +23,7 @@ import { ConnectorData, ConnectorType, PublicationJobData, PublicationSettings }
import { connectorList } from '../api'
import { defaultKms } from './keymaps'
import { titleCase } from '../utils'
+import { ClientEvent } from '../events'
/**
* @fileoverview define the publication dialog
@@ -120,12 +121,9 @@ export class PublicationUi {
// **
// Functions to open and close the dialog
- getDialogElements(): { el: HTMLElement, primary: HTMLElement, secondary: HTMLElement } {
- const el = document.querySelector('#publish-dialog') as HTMLElement
- const primary = el?.querySelector('#publish-button--primary') as HTMLElement
- const secondary = el?.querySelector('#publish-button--secondary') as HTMLElement
- if(!el || !primary || !secondary) throw new Error('Publication dialog elements not found')
- return { el, primary, secondary }
+ userContent: TemplateResult | null = null
+ setUserContent(content: TemplateResult) {
+ this.userContent = content
}
createDialogElements(): HTMLElement {
// Create the dialog element
@@ -182,59 +180,61 @@ export class PublicationUi {
`}
- ${this.isPending(status) ? html`
- Publication in progress...
- ` : ''}
- ${this.isReady(status) ? html`
- Click on the button below to publish your website.
- ${this.settings.options && Object.entries(this.settings.options).length && html`Publication options:
${ Object.entries(this.settings.options).map(([key, value]) => html`- ${key}: ${value}
`) }
`}
- ` : ''}
- ${this.isSuccess(status) ? html`
- Publication success ${unsafeHTML(svgSuccess)}
- ${this.settings.options?.websiteUrl ? html`Click here to view the published website
` : ''}
- ` : ''}
- ${this.isError(status) || this.isLoggedOut(status) ? html`
- Publication error ${unsafeHTML(svgError)}
-
- Details
- ${unsafeHTML(this.errorMessage)}
-
- ` : ''}
- ${job?.message ? html`
-
- Details
- ${unsafeHTML(job.message)}
-
- ` : ''}
- ${this.isPending(status) ? html`
-
- ` : ''}
- ${job?.logs?.length && job.logs[0].length ? html`
-
- Logs
- ${unsafeHTML(cleanupLogEntry(job.logs))}
-
- ` : ''}
- ${job?.errors?.length && job.errors[0].length ? html`
-
- Errors
- ${unsafeHTML(cleanupLogEntry(job.errors))}
-
-
- ` : ''}
- ${this.isPending(status) || this.isLoggedOut(status) ? '' : html`
-
+ ${this.userContent || html`
+ ${this.isPending(status) ? html`
+ Publication in progress...
+ ` : ''}
+ ${this.isReady(status) ? html`
+ Click on the button below to publish your website.
+ ${this.settings.options && Object.entries(this.settings.options).length && html`Publication options:
${ Object.entries(this.settings.options).map(([key, value]) => html`- ${key}: ${value}
`) }
`}
+ ` : ''}
+ ${this.isSuccess(status) ? html`
+ Publication success ${unsafeHTML(svgSuccess)}
+ ${this.settings.options?.websiteUrl ? html`Click here to view the published website
` : ''}
+ ` : ''}
+ ${this.isError(status) || this.isLoggedOut(status) ? html`
+ Publication error ${unsafeHTML(svgError)}
+
+ Details
+ ${unsafeHTML(this.errorMessage)}
+
+ ` : ''}
+ ${job?.message ? html`
+
+ Details
+ ${unsafeHTML(job.message)}
+
+ ` : ''}
+ ${this.isPending(status) ? html`
+
+ ` : ''}
+ ${job?.logs?.length && job.logs[0].length ? html`
+
+ Logs
+ ${unsafeHTML(cleanupLogEntry(job.logs))}
+
+ ` : ''}
+ ${job?.errors?.length && job.errors[0].length ? html`
+
+ Errors
+ ${unsafeHTML(cleanupLogEntry(job.errors))}
+
+
+ ` : ''}
+ ${this.isPending(status) || this.isLoggedOut(status) ? '' : html`
+
+ `}
`}