@silexlabs/silex 3.0.1-alpha.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.default +20 -0
- package/.silex.js +67 -8
- package/LICENSE +661 -203
- package/README.md +37 -35
- package/dist/client/client/api.d.ts +90 -0
- package/dist/client/client/assetUrl.d.ts +54 -0
- package/dist/client/client/config.d.ts +102 -0
- package/dist/client/client/events.d.ts +23 -0
- package/dist/client/client/expose.d.ts +8 -0
- package/dist/client/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/client/client/grapesjs/PublicationManager.d.ts +73 -0
- package/dist/client/client/grapesjs/PublicationUi.d.ts +59 -0
- package/dist/client/client/grapesjs/blocks.d.ts +1 -0
- package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/client/grapesjs/img.d.ts +6 -0
- package/dist/client/client/grapesjs/index.d.ts +9 -0
- package/dist/client/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/client/client/grapesjs/openImport.d.ts +9 -0
- package/dist/client/client/grapesjs/page-panel.d.ts +9 -0
- package/dist/client/client/grapesjs/project-bar.d.ts +21 -0
- package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/client/grapesjs/rich-text.d.ts +4 -0
- package/dist/client/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/client/grapesjs/settings.d.ts +4 -0
- package/dist/client/client/grapesjs/storage.d.ts +2 -0
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/client/index.d.ts +10 -0
- package/dist/client/client/publication-transformers.d.ts +42 -0
- package/dist/client/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/client/publish-fonts.d.ts +4 -0
- package/dist/client/client/utils.d.ts +22 -0
- package/dist/client/constants.d.ts +32 -0
- package/dist/client/css/admin.css +1114 -328
- package/dist/client/css/admin.css.map +1 -0
- package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
- package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
- package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
- package/dist/client/index.html +3 -2
- package/dist/client/js/main.js +356 -131
- package/dist/client/js/main.js.LICENSE.txt +15 -1
- package/dist/client/page.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
- package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
- package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
- package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
- package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
- package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
- package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
- package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
- package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
- package/dist/client/types.d.ts +339 -0
- package/dist/plugins/client/client/events.d.ts +23 -0
- package/dist/plugins/client/client/events.js +43 -0
- package/dist/plugins/client/client/events.js.map +1 -0
- package/dist/plugins/client/plugins/client/template.d.ts +2 -0
- package/dist/plugins/client/plugins/client/template.js +234 -0
- package/dist/plugins/client/plugins/client/template.js.map +1 -0
- package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
- package/dist/plugins/client/plugins/client/website-info.js +72 -0
- package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
- package/dist/plugins/client/types.d.ts +339 -0
- package/dist/plugins/client/types.js +80 -0
- package/dist/plugins/client/types.js.map +1 -0
- package/dist/plugins/server/constants.d.ts +32 -0
- package/dist/plugins/server/constants.js +76 -0
- package/dist/plugins/server/constants.js.map +1 -0
- package/dist/plugins/server/plugins/server/Cache.d.ts +2 -0
- package/dist/plugins/server/plugins/server/Cache.js +36 -0
- package/dist/plugins/server/plugins/server/Cache.js.map +1 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/FtpConnector.d.ts +86 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js +536 -0
- package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +135 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +649 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.d.ts +0 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.js +14 -0
- package/dist/plugins/server/plugins/server/PublicationOptimizer.js.map +1 -0
- package/dist/plugins/server/plugins/server/SslPlugin.d.ts +1 -0
- package/dist/plugins/server/plugins/server/SslPlugin.js +86 -0
- package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js +45 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -0
- package/dist/plugins/server/server/config.d.ts +59 -0
- package/dist/plugins/server/server/config.js +181 -0
- package/dist/plugins/server/server/config.js.map +1 -0
- package/dist/plugins/server/server/connectors/FsHosting.d.ts +14 -0
- package/dist/plugins/server/server/connectors/FsHosting.js +66 -0
- package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -0
- package/dist/plugins/server/server/connectors/FsStorage.d.ts +44 -0
- package/dist/plugins/server/server/connectors/FsStorage.js +261 -0
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -0
- package/dist/plugins/server/server/connectors/connectors.d.ts +86 -0
- package/dist/plugins/server/server/connectors/connectors.js +126 -0
- package/dist/plugins/server/server/connectors/connectors.js.map +1 -0
- package/dist/plugins/server/server/events.d.ts +26 -0
- package/dist/plugins/server/server/events.js +31 -0
- package/dist/plugins/server/server/events.js.map +1 -0
- package/dist/plugins/server/server/jobs.d.ts +12 -0
- package/dist/plugins/server/server/jobs.js +79 -0
- package/dist/plugins/server/server/jobs.js.map +1 -0
- package/dist/plugins/server/server/utils/validation.d.ts +7 -0
- package/dist/plugins/server/server/utils/validation.js +37 -0
- package/dist/plugins/server/server/utils/validation.js.map +1 -0
- package/dist/plugins/server/types.d.ts +339 -0
- package/dist/plugins/server/types.js +84 -0
- package/dist/plugins/server/types.js.map +1 -0
- package/dist/server/constants.js +55 -0
- package/dist/server/plugins/server/Cache.js +19 -0
- package/dist/server/server/api/api.js +20 -0
- package/dist/server/server/api/connectorApi.js +334 -0
- package/dist/server/server/api/publicationApi.js +106 -0
- package/dist/server/server/api/websiteApi.js +315 -0
- package/dist/server/server/cli.js +71 -0
- package/dist/server/server/config.js +120 -0
- package/dist/server/server/connectors/FsHosting.js +47 -0
- package/dist/server/server/connectors/FsStorage.js +228 -0
- package/dist/server/server/connectors/connectors.js +88 -0
- package/dist/server/server/events.js +14 -0
- package/dist/server/server/expose.js +27 -0
- package/dist/server/server/express.js +46 -0
- package/dist/server/server/index.js +94 -0
- package/dist/server/server/jobs.js +50 -0
- package/dist/server/server/utils/validation.js +14 -0
- package/dist/server/types.js +40 -0
- package/package.json +99 -49
- package/public/assets/download.png +0 -0
- package/public/assets/favicon.ico +0 -0
- package/public/assets/favicon.png +0 -0
- package/public/assets/ftp.png +0 -0
- package/public/assets/gitlab.png +0 -0
- package/public/assets/gitlab2.png +0 -0
- package/public/assets/laptop.png +0 -0
- package/public/assets/logo-silex-small.png +0 -0
- package/public/silex.js +22 -23
- package/src/css/_variables.scss +24 -20
- package/src/css/dialog.scss +35 -2
- package/src/css/fonts.scss +31 -0
- package/src/css/footer.scss +12 -0
- package/src/css/grapesjs-light.scss +180 -0
- package/src/css/grapesjs-plugins.scss +227 -0
- package/src/css/grapesjs.scss +159 -1
- package/src/css/index.scss +12 -1
- package/src/css/light.scss +7 -0
- package/src/css/loader.scss +2 -0
- package/src/css/project-bar.scss +32 -16
- package/src/css/silex.scss +79 -5
- package/src/css/website-info.scss +14 -0
- package/src/html/index.pug +3 -3
- package/src/html/templates/includes.pug +0 -1
- package/src/ts/client/api.ts +156 -0
- package/src/ts/client/assetUrl.test.ts +164 -0
- package/src/ts/client/assetUrl.ts +254 -0
- package/src/ts/client/config.ts +175 -13
- package/src/ts/client/events.ts +43 -0
- package/src/ts/client/expose.ts +27 -1
- package/src/ts/client/grapesjs/LoginDialog.ts +204 -0
- package/src/ts/client/grapesjs/PublicationManager.ts +433 -0
- package/src/ts/client/grapesjs/PublicationUi.ts +366 -0
- package/src/ts/client/grapesjs/blocks.ts +17 -0
- package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
- package/src/ts/client/grapesjs/css-props.ts +910 -0
- package/src/ts/client/grapesjs/eleventy.ts +30 -7
- package/src/ts/client/grapesjs/footer.ts +42 -0
- package/src/ts/client/grapesjs/img.ts +147 -0
- package/src/ts/client/grapesjs/index.ts +311 -122
- package/src/ts/client/grapesjs/internal-links.test.ts +19 -1
- package/src/ts/client/grapesjs/internal-links.ts +31 -7
- package/src/ts/client/grapesjs/keymaps.ts +207 -0
- package/src/ts/client/grapesjs/new-page-dialog.ts +19 -3
- package/src/ts/client/grapesjs/openImport.ts +22 -0
- package/src/ts/client/grapesjs/page-panel.ts +109 -7
- package/src/ts/client/grapesjs/project-bar.ts +133 -72
- package/src/ts/client/grapesjs/resize-panel.ts +20 -0
- package/src/ts/client/grapesjs/rich-text.ts +38 -13
- package/src/ts/client/grapesjs/semantic.ts +20 -3
- package/src/ts/client/grapesjs/settings-sections.ts +117 -0
- package/src/ts/client/grapesjs/settings.ts +191 -96
- package/src/ts/client/grapesjs/storage.ts +187 -0
- package/src/ts/client/grapesjs/symbolDialogs.ts +21 -5
- package/src/ts/client/grapesjs/view-buttons.ts +42 -0
- package/src/ts/client/index.ts +80 -21
- package/src/ts/client/publication-transformers.test.ts +207 -0
- package/src/ts/client/publication-transformers.ts +280 -0
- package/src/ts/client/publish-custom-code-block.ts +31 -0
- package/src/ts/client/publish-fonts.ts +36 -0
- package/src/ts/client/utils.ts +70 -1
- package/src/ts/constants.ts +78 -0
- package/src/ts/externs.ts +17 -0
- package/src/ts/page.ts +20 -3
- package/src/ts/plugins/client/template.ts +246 -0
- package/src/ts/plugins/client/website-info.ts +84 -0
- package/src/ts/plugins/server/Cache.ts +32 -0
- package/src/ts/plugins/server/DownloadConnector.ts +146 -0
- package/src/ts/plugins/server/FtpConnector.test.ts +82 -0
- package/src/ts/plugins/server/FtpConnector.ts +621 -0
- package/src/ts/plugins/server/GitlabConnector.ts +749 -0
- package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
- package/src/ts/plugins/server/PublicationOptimizer.ts +14 -0
- package/src/ts/plugins/server/SslPlugin.ts +84 -0
- package/src/ts/plugins/server/StaticPlugin.ts +45 -0
- package/src/ts/server/api/api.ts +19 -0
- package/src/ts/server/api/connectorApi.ts +464 -0
- package/src/ts/server/api/publicationApi.ts +159 -0
- package/src/ts/server/api/websiteApi.ts +462 -0
- package/src/ts/server/cli.ts +48 -14
- package/src/ts/server/config.ts +158 -60
- package/src/ts/server/connectors/FsHosting.ts +66 -0
- package/src/ts/server/connectors/FsStorage.test.ts +51 -0
- package/src/ts/server/connectors/FsStorage.ts +290 -0
- package/src/ts/server/connectors/connectors.ts +203 -0
- package/src/ts/server/events.ts +37 -0
- package/src/ts/server/expose.ts +19 -0
- package/src/ts/server/express.ts +57 -5
- package/src/ts/server/index.ts +79 -16
- package/src/ts/server/jobs.test.ts +75 -0
- package/src/ts/server/jobs.ts +89 -0
- package/src/ts/server/utils/BackwardCompat.ts +546 -528
- package/src/ts/server/utils/validation.ts +34 -0
- package/src/ts/types.ts +295 -85
- package/.dockerignore +0 -5
- package/.editorconfig +0 -14
- package/.eslintrc.json +0 -43
- package/.github/FUNDING.yml +0 -13
- package/.github/workflows/docker-hub-publish.yml +0 -36
- package/.github/workflows/npm-publish.yml +0 -19
- package/.github/workflows/test.yml +0 -26
- package/.nvmrc +0 -1
- package/.silex/default/.silex.data.json +0 -1
- package/CODE_OF_CONDUCT.md +0 -128
- package/CONTRIBUTING.md +0 -131
- package/Dockerfile +0 -15
- package/directus.silex.js +0 -7
- package/dist/constants.js +0 -4
- package/dist/events.js +0 -5
- package/dist/page.js +0 -15
- package/dist/server/cli.js +0 -43
- package/dist/server/config.js +0 -70
- package/dist/server/express.js +0 -18
- package/dist/server/index.js +0 -58
- package/dist/types.js +0 -34
- package/jest.config.js +0 -10
- package/logos/logo_by_ceubri/silex-icon-2018@200px.png +0 -0
- package/logos/logo_by_ceubri/silex-icon-2018@4x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white-transp.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@0.5x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@0.75x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@4x.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018-white@4x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.ai +5 -2521
- package/logos/logo_by_ceubri/silex-logo-2018.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.pdf +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@0.5x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@0.75x.png +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@4x.jpg +0 -0
- package/logos/logo_by_ceubri/silex-logo-2018@4x.png +0 -0
- package/logos/silexlabs.png +0 -0
- package/src/example-client-config.js +0 -47
- package/src/plugins/AuthPlugin.js +0 -21
- package/src/plugins/Cache.js +0 -11
- package/src/plugins/DefaultBackend.js +0 -149
- package/src/plugins/ExpressPlugin.js +0 -39
- package/src/plugins/HooksPlugin.js +0 -58
- package/src/plugins/PublishPlugin.js +0 -69
- package/src/plugins/SslPlugin.js +0 -66
- package/src/plugins/StaticPlugin.js +0 -48
- package/src/plugins/WebsitePlugin.js +0 -207
- package/src/ts/client/grapesjs/publish.ts +0 -386
- package/src/ts/client/grapesjs/template.ts +0 -166
- package/src/ts/events.ts +0 -2
- package/tsconfig-server-debug.json +0 -19
- package/tsconfig-server-release.json +0 -19
- package/tsconfig.jest.json +0 -9
- package/tsconfig.json +0 -26
- package/webpack.config.js +0 -28
- package/webpack.debug.config.js +0 -8
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import {html, render, TemplateResult} from 'lit-html'
|
|
19
|
+
import {defaultSections, idCodeWrapper, isSite, SettingsSection} from './settings-sections'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @fileoverview This file contains the settings dialog. The config API lets plugins add sections to the settings dialog.
|
|
23
|
+
*/
|
|
4
24
|
|
|
5
25
|
import { WebsiteSettings } from '../../types'
|
|
26
|
+
import { ClientEvent } from '../events'
|
|
27
|
+
import { SILEX_VERSION } from '../../constants'
|
|
28
|
+
|
|
29
|
+
const sectionsSite = [...defaultSections]
|
|
30
|
+
const sectionsPage = [...defaultSections]
|
|
6
31
|
|
|
7
|
-
const pluginName = 'settings-dialog'
|
|
8
32
|
const el = document.createElement('div')
|
|
9
33
|
let modal
|
|
10
34
|
|
|
11
|
-
// Get version from webpack (see plugin in webpack.config.js)
|
|
12
|
-
declare const VERSION: string
|
|
13
|
-
|
|
14
35
|
export const cmdOpenSettings = 'open-settings'
|
|
15
36
|
|
|
16
|
-
let
|
|
17
|
-
export const settingsDialog =
|
|
18
|
-
// Display Silex version from package.json
|
|
19
|
-
try {
|
|
20
|
-
version = VERSION
|
|
21
|
-
} catch (error) {
|
|
22
|
-
// Cannot get version from webpack (see plugin in webpack.config.js)
|
|
23
|
-
}
|
|
24
|
-
console.log('Silex version:', version)
|
|
37
|
+
let headEditor = null
|
|
38
|
+
export const settingsDialog = (editor, opts) => {
|
|
25
39
|
editor.Commands.add(cmdOpenSettings, {
|
|
26
40
|
run: (_, sender, {page}) => {
|
|
27
41
|
modal = editor.Modal.open({
|
|
@@ -30,6 +44,7 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
30
44
|
attributes: { class: 'settings-dialog' },
|
|
31
45
|
})
|
|
32
46
|
.onceClose(() => {
|
|
47
|
+
sender?.set && sender.set('active', 0) // Deactivate the button to make it ready to be clicked again, only in case of a grapesjs button (not in the pages panel)
|
|
33
48
|
editor.stopCommand(cmdOpenSettings) // apparently this is needed to be able to run the command several times
|
|
34
49
|
})
|
|
35
50
|
displaySettings(editor, opts, page)
|
|
@@ -37,14 +52,20 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
37
52
|
const form = el.querySelector('form')
|
|
38
53
|
form.onsubmit = event => {
|
|
39
54
|
event.preventDefault()
|
|
55
|
+
editor.trigger(ClientEvent.SETTINGS_SAVE_START, page)
|
|
40
56
|
saveSettings(editor, opts, page)
|
|
57
|
+
editor.trigger(ClientEvent.SETTINGS_SAVE_END, page)
|
|
41
58
|
editor.stopCommand(cmdOpenSettings)
|
|
42
59
|
}
|
|
43
60
|
form.querySelector('input')?.focus()
|
|
61
|
+
// Notify other plugins
|
|
62
|
+
editor.trigger(ClientEvent.SETTINGS_OPEN, page)
|
|
63
|
+
// Return the dialog
|
|
44
64
|
return modal
|
|
45
65
|
},
|
|
46
66
|
stop: () => {
|
|
47
67
|
modal.close()
|
|
68
|
+
editor.trigger(ClientEvent.SETTINGS_CLOSE)
|
|
48
69
|
},
|
|
49
70
|
})
|
|
50
71
|
// add settings to the website
|
|
@@ -56,93 +77,156 @@ export const settingsDialog = grapesjs.plugins.add(pluginName, (editor, opts) =>
|
|
|
56
77
|
const model = editor.getModel()
|
|
57
78
|
model.set('settings', data.settings || {})
|
|
58
79
|
model.set('name', data.name)
|
|
80
|
+
editor.once('canvas:frame:load', () => {
|
|
81
|
+
updateDom(editor)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
// Normal way to apply the head content to the DOM
|
|
85
|
+
// fix #1559 Custom <head> code must be reapplied
|
|
86
|
+
editor.on('canvas:frame:load', () => {
|
|
59
87
|
updateDom(editor)
|
|
60
88
|
})
|
|
89
|
+
// When the page changes, update the dom
|
|
61
90
|
editor.on('page', (e) => {
|
|
62
|
-
editor
|
|
63
|
-
|
|
64
|
-
|
|
91
|
+
updateDom(editor)
|
|
92
|
+
})
|
|
93
|
+
headEditor = editor.CodeManager.createViewer({
|
|
94
|
+
readOnly: false,
|
|
95
|
+
codeName: 'htmlmixed',
|
|
96
|
+
lineNumbers: true,
|
|
97
|
+
lineWrapping: true,
|
|
98
|
+
autoFormat: false,
|
|
65
99
|
})
|
|
66
|
-
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function showSection(item: SettingsSection) {
|
|
103
|
+
// **
|
|
104
|
+
// Handle the side bar
|
|
105
|
+
const aside = el.querySelector('aside.silex-bar') as HTMLElement
|
|
106
|
+
const ul = aside.querySelector('ul.silex-list--menu') as HTMLUListElement
|
|
107
|
+
const li = ul.querySelector('li#settings-sidebar-' + item.id) as HTMLLIElement
|
|
108
|
+
currentSection = item
|
|
109
|
+
if(!li) {
|
|
110
|
+
console.warn('Cannot find section', item.id, 'in the side bar, fallback to the first section')
|
|
111
|
+
if(!defaultSections[0] || defaultSections[0].id === item.id) {
|
|
112
|
+
console.error('Cannot find the default section in the side bar')
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
showSection(defaultSections[0]) // Fallback to the first section
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
// Update active
|
|
119
|
+
Array.from(ul.querySelectorAll('.active')).forEach(el => el.classList.remove('active'))
|
|
120
|
+
li.classList.add('active')
|
|
121
|
+
// **
|
|
122
|
+
// Handle the main section
|
|
123
|
+
const main = el.querySelector('main#settings__main') as HTMLElement
|
|
124
|
+
const mainItem = main.querySelector(`#settings-${item.id}`)
|
|
125
|
+
if(!mainItem) {
|
|
126
|
+
console.warn('Cannot find section', item.id, 'in the settings dialog, fallback to the first section')
|
|
127
|
+
if(!defaultSections[0] || defaultSections[0].id === item.id) {
|
|
128
|
+
console.error('Cannot find the default section in the settings dialog')
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
showSection(defaultSections[0]) // Fallback to the first section
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
// Update hidden
|
|
135
|
+
Array.from(main.querySelectorAll('.silex-hideable')).forEach(el => el.classList.add('silex-hidden'))
|
|
136
|
+
mainItem.classList.remove('silex-hidden')
|
|
137
|
+
// This messes up with the save / cancel mechanism
|
|
138
|
+
// displaySettings(editor, config, model)
|
|
139
|
+
// Refresh the code editor just in case it went from hidden to visible
|
|
140
|
+
// This makes it ready to be used when the user clicks on the tab
|
|
141
|
+
headEditor.refresh()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function addSection(section, siteOrPage: 'site' | 'page', position: 'first' | 'last' | number) {
|
|
145
|
+
const sections = siteOrPage === 'site' ? sectionsSite : sectionsPage
|
|
146
|
+
if (position === 'first') {
|
|
147
|
+
sections.unshift(section)
|
|
148
|
+
} else if (position === 'last') {
|
|
149
|
+
sections.push(section)
|
|
150
|
+
} else if (typeof position === 'number') {
|
|
151
|
+
sections.splice(position, 0, section)
|
|
152
|
+
} else {
|
|
153
|
+
throw new Error('Invalid position for settings section')
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function removeSection(id, siteOrPage: 'site' | 'page') {
|
|
158
|
+
const sections = siteOrPage === 'site' ? sectionsSite : sectionsPage
|
|
159
|
+
const index = sections.findIndex(section => section.id === id)
|
|
160
|
+
if(index === -1) throw new Error(`Cannot find section with id ${id}`)
|
|
161
|
+
sections.splice(index, 1)
|
|
162
|
+
}
|
|
67
163
|
|
|
68
|
-
// Is the model a site or a page?
|
|
69
|
-
function isSite(model) { return !!model.getHtml }
|
|
70
164
|
|
|
165
|
+
let currentSection
|
|
71
166
|
function displaySettings(editor, config, model = editor.getModel()) {
|
|
167
|
+
// Update the model with the current settings
|
|
72
168
|
const settings = model.get('settings') || {} as WebsiteSettings
|
|
73
169
|
model.set('settings', settings)
|
|
170
|
+
// Get the current sections for page or site
|
|
171
|
+
const menuItemsCurrent = isSite(model) ? sectionsSite : sectionsPage
|
|
172
|
+
// Init the current section selection
|
|
173
|
+
currentSection = currentSection || menuItemsCurrent[0]
|
|
174
|
+
const sections: TemplateResult[] = menuItemsCurrent.map(item => {
|
|
175
|
+
try {
|
|
176
|
+
return item.render(settings, model)
|
|
177
|
+
} catch (e) {
|
|
178
|
+
console.error('Error rendering settings section', item.id, e)
|
|
179
|
+
return html`<div class="silex-error">Error rendering settings section ${item.id}</div>`
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
// Render the settings dialog
|
|
74
183
|
render(html`
|
|
75
|
-
<p>The page settings will override site settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
76
184
|
<form class="silex-form">
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<h3>Website language</h3>
|
|
86
|
-
<p>This is the default language code for this website. Example: en, fr, es...</p>
|
|
87
|
-
<input type="text" name="lang" .value=${live(settings.lang || '')}/>
|
|
88
|
-
</label>
|
|
89
|
-
<label class="silex-form__element">
|
|
90
|
-
<h3>Title</h3>
|
|
91
|
-
<p>Title of the browser window, and title in the search engines results. It is used by search engines to find out what your site is talking about. The title should be a maximum of 70 characters long, including spaces.</p>
|
|
92
|
-
<input type="text" name="title" .value=${live(settings.title || '')}/>
|
|
93
|
-
</label>
|
|
94
|
-
<label class="silex-form__element">
|
|
95
|
-
<h3>Description</h3>
|
|
96
|
-
<p>Description displayed by the search engines in search results. It is used by search engines to find out what your site is talking about. It is best to keep meta descriptions between 150 and 160 characters.</p>
|
|
97
|
-
<input type="text" name="description" .value=${live(settings.description || '')}/>
|
|
98
|
-
</label>
|
|
99
|
-
<label class="silex-form__element">
|
|
100
|
-
<h3>Favicon</h3>
|
|
101
|
-
<p>Small image displayed in the browser's address bar and in tabs. The recommended size is 16×16 or 32×32 pixels. This can be a URL or a relative path.</p>
|
|
102
|
-
<input type="text" name="favicon" .value=${live(settings.favicon || '')}/>
|
|
103
|
-
</label>
|
|
104
|
-
</div>
|
|
105
|
-
<h2>Social networks sharing</h2>
|
|
106
|
-
<div>
|
|
107
|
-
<p>Once your website is live, you can use these tools to test sharing: <a target="_blank" href="https://developers.facebook.com/tools/debug/">Facebook</a>,
|
|
108
|
-
<a target="_blank" href="https://cards-dev.twitter.com/validator">Twitter</a>,
|
|
109
|
-
<a target="_blank" href="https://www.linkedin.com/post-inspector/inspect/">Linkedin</a></p>
|
|
110
|
-
</div>
|
|
111
|
-
<div class="silex-form__group col2">
|
|
112
|
-
<label class="silex-form__element">
|
|
113
|
-
<h3>Title</h3>
|
|
114
|
-
<p>The title of your website displayed when a user shares your website on a social network.
|
|
115
|
-
Do not include any branding in this title, just eye-catching phrase, e.g. "Learn everything about fishing".
|
|
116
|
-
Title should be between 60 and 90 characters long.</p>
|
|
117
|
-
<input type="text" name="og:title" .value=${live(settings['og:title'] || '')}/>
|
|
118
|
-
</label>
|
|
119
|
-
<label class="silex-form__element">
|
|
120
|
-
<h3>Description</h3>
|
|
121
|
-
<p>Description displayed when a user shares your website on a social network. Make it catchy, and invite readers to visit your website too, e.g. "Sam's website about fishing, check it out!" Title should be between 60 and 90 characters long.</p>
|
|
122
|
-
<input type="text" name="og:description" .value=${live(settings['og:description'] || '')}/>
|
|
123
|
-
</label>
|
|
124
|
-
<label class="silex-form__element">
|
|
125
|
-
<h3>Image</h3>
|
|
126
|
-
<p>Thumbnail image which is displayed when your website is shared on a social network. The optimal size is 1200×627 pixels. At this size, your thumbnail will be big and stand out from the crowd. But do not exceed the 5MB size limit. If you use an image that is smaller than 400 pixels x 209 pixels, it will render as a much smaller thumbnail.</p>
|
|
127
|
-
<p>Please enter the full URL here, e.g. "http://mysite.com/path/to/image.jpg"</p>
|
|
128
|
-
<input type="text" name="og:image" .value=${live(settings['og:image'] || '')}/>
|
|
129
|
-
</label>
|
|
130
|
-
</div>
|
|
131
|
-
<h2>Code</h2>
|
|
132
|
-
<div class="silex-form__group">
|
|
133
|
-
<label class="silex-form__element">
|
|
134
|
-
<h3>HTML head</h3>
|
|
135
|
-
<p>HTML code which will be inserted in the HEAD tag.</p>
|
|
136
|
-
<textarea name="head" .value=${live(settings.head || '')}></textarea>
|
|
137
|
-
</label>
|
|
185
|
+
<div class="silex-help">
|
|
186
|
+
${isSite(model) ? html`
|
|
187
|
+
<p>Here you can set the name of your website, SEO and social networks sharing data.</p>
|
|
188
|
+
<p>These settings are overriden by the page settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
189
|
+
` : html`
|
|
190
|
+
<p>Here you can set the name of your page, SEO and social networks sharing data.</p>
|
|
191
|
+
<p>These settings override the site settings, <a href="https://github.com/silexlabs/Silex/wiki/Settings" target="_blank">more info about settings here</a>.</p>
|
|
192
|
+
`}
|
|
138
193
|
</div>
|
|
194
|
+
<section class="silex-sidebar-dialog">
|
|
195
|
+
<aside class="silex-bar">
|
|
196
|
+
<ul class="silex-list silex-list--menu">
|
|
197
|
+
${menuItemsCurrent.map(item => html`
|
|
198
|
+
<li
|
|
199
|
+
id="settings-sidebar-${item.id}"
|
|
200
|
+
class=${item.id === currentSection.id ? 'active' : ''}
|
|
201
|
+
@click=${e => {
|
|
202
|
+
e.preventDefault()
|
|
203
|
+
// Show the new section
|
|
204
|
+
showSection(item)
|
|
205
|
+
// Notify other plugins
|
|
206
|
+
editor.trigger(ClientEvent.SETTINGS_SECTION_CHANGE, item.id)
|
|
207
|
+
}}
|
|
208
|
+
>
|
|
209
|
+
${item.label}
|
|
210
|
+
</li>
|
|
211
|
+
`)}
|
|
212
|
+
</ul>
|
|
213
|
+
</aside>
|
|
214
|
+
<main id="settings__main">
|
|
215
|
+
${ sections }
|
|
216
|
+
</main>
|
|
217
|
+
</section>
|
|
139
218
|
<footer>
|
|
140
|
-
<p class="silex-version">Silex ${
|
|
219
|
+
<p class="silex-version">Silex ${SILEX_VERSION}</p>
|
|
141
220
|
<input class="silex-button" type="button" @click=${e => editor.stopCommand(cmdOpenSettings)} value="Cancel">
|
|
142
|
-
<input class="silex-button" type="submit" value="
|
|
221
|
+
<input class="silex-button" type="submit" value="Apply">
|
|
143
222
|
</footer>
|
|
144
223
|
</form>
|
|
145
224
|
`, el)
|
|
225
|
+
// Display the current section
|
|
226
|
+
showSection(currentSection)
|
|
227
|
+
// Init the code editor
|
|
228
|
+
el.querySelector(`#${idCodeWrapper}`)?.appendChild(headEditor.getElement())
|
|
229
|
+
headEditor.setContent(settings.head || '')
|
|
146
230
|
}
|
|
147
231
|
|
|
148
232
|
function saveSettings(editor, config, model = editor.getModel()) {
|
|
@@ -150,13 +234,19 @@ function saveSettings(editor, config, model = editor.getModel()) {
|
|
|
150
234
|
const formData = new FormData(form)
|
|
151
235
|
const data = Array.from(formData as any)
|
|
152
236
|
.reduce((aggregate, [key, value]) => {
|
|
153
|
-
|
|
237
|
+
// Keep only the values that are set
|
|
238
|
+
if(value !== '') {
|
|
239
|
+
aggregate[key] = value
|
|
240
|
+
}
|
|
154
241
|
return aggregate
|
|
155
242
|
}, {}) as {[key: string]: any}
|
|
156
|
-
|
|
243
|
+
// take the name out to the main model (by design in grapesjs pages)
|
|
157
244
|
const { name, ...settings } = data
|
|
158
245
|
model.set({
|
|
159
|
-
settings
|
|
246
|
+
settings: {
|
|
247
|
+
...data,
|
|
248
|
+
head: headEditor.getContent(),
|
|
249
|
+
},
|
|
160
250
|
name,
|
|
161
251
|
})
|
|
162
252
|
// save if auto save is on
|
|
@@ -176,13 +266,18 @@ function getHeadContainer(doc, className) {
|
|
|
176
266
|
}
|
|
177
267
|
function updateDom(editor) {
|
|
178
268
|
const doc = editor.Canvas.getDocument()
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
269
|
+
const settings = editor.getModel().get('settings')
|
|
270
|
+
const pageSettings = editor.Pages.getSelected().get('settings')
|
|
271
|
+
if(doc && settings) {
|
|
272
|
+
// Delay the update to let the DOM be ready
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
// Site head
|
|
275
|
+
getHeadContainer(doc, 'site-head')
|
|
276
|
+
.innerHTML = settings.head || ''
|
|
277
|
+
// Pages head
|
|
278
|
+
getHeadContainer(doc, 'page-head')
|
|
279
|
+
.innerHTML = pageSettings?.head || ''
|
|
280
|
+
})
|
|
186
281
|
} else {
|
|
187
282
|
// No document??
|
|
188
283
|
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { ConnectorId, WebsiteId, WebsiteData, ConnectorUser, ConnectorType, ApiError } from '../../types'
|
|
19
|
+
import { websiteLoad, websiteSave } from '../api'
|
|
20
|
+
import { cmdLogin, eventLoggedIn, eventLoggedOut, getCurrentUser, updateUser } from './LoginDialog'
|
|
21
|
+
import { addTempDataToPages, addTempDataToAssetUrl, addTempDataToStyles, removeTempDataFromAssetUrl, removeTempDataFromPages, removeTempDataFromStyles } from '../assetUrl'
|
|
22
|
+
import { PublicationStatus } from './PublicationManager'
|
|
23
|
+
import { ClientEvent } from '../events'
|
|
24
|
+
|
|
25
|
+
export const cmdPauseAutoSave = 'pause-auto-save'
|
|
26
|
+
|
|
27
|
+
// Mechanism to keep only the last save during publication
|
|
28
|
+
let lastPendingSaving: WebsiteData = null
|
|
29
|
+
|
|
30
|
+
// Mechanism to avoid concurrent saving
|
|
31
|
+
// Note: there is already such a mechanism in grapesjs but it fails when the save is delayed by the publication
|
|
32
|
+
let isSaving = false
|
|
33
|
+
|
|
34
|
+
export const storagePlugin = (editor) => {
|
|
35
|
+
// Add useful commands
|
|
36
|
+
editor.Commands.add(cmdPauseAutoSave, {
|
|
37
|
+
run: () => {
|
|
38
|
+
if(!editor.StorageManager.isAutosave()) throw new Error('Autosave is not enabled')
|
|
39
|
+
editor.StorageManager.setAutosave(false)
|
|
40
|
+
},
|
|
41
|
+
stop: () => {
|
|
42
|
+
editor.editor.set('changesCount', 0)
|
|
43
|
+
editor.UndoManager.clear()
|
|
44
|
+
editor.StorageManager.setAutosave(true)
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
// Add the storage connector
|
|
48
|
+
editor.Storage.add('connector', {
|
|
49
|
+
async load(options: { id: WebsiteId, connectorId: ConnectorId }): Promise<WebsiteData> {
|
|
50
|
+
try {
|
|
51
|
+
const user: ConnectorUser = await getCurrentUser(editor) ?? await updateUser(editor, ConnectorType.STORAGE, options.connectorId)
|
|
52
|
+
if (!user) throw new ApiError('Not logged in', 401)
|
|
53
|
+
const data = await websiteLoad({ websiteId: options.id, connectorId: user.storage.connectorId }) as WebsiteData
|
|
54
|
+
if (data.assets) data.assets = addTempDataToAssetUrl(data.assets, options.id, user.storage.connectorId)
|
|
55
|
+
if (data.pages) data.pages = addTempDataToPages(data.pages, options.id, user.storage.connectorId)
|
|
56
|
+
if (data.styles) data.styles = addTempDataToStyles(data.styles, options.id, user.storage.connectorId)
|
|
57
|
+
return data
|
|
58
|
+
|
|
59
|
+
} catch (err) {
|
|
60
|
+
editor.UndoManager.clear()
|
|
61
|
+
if (err.httpStatusCode === 401) {
|
|
62
|
+
editor.once(eventLoggedIn, async () => {
|
|
63
|
+
try {
|
|
64
|
+
editor.runCommand(cmdPauseAutoSave)
|
|
65
|
+
const data = await editor.Storage.load(options)
|
|
66
|
+
editor.once('canvas:frame:load', () => editor.stopCommand(cmdPauseAutoSave))
|
|
67
|
+
editor.loadProjectData(data)
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error('connectorPlugin load error', err)
|
|
70
|
+
throw err
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
editor.Commands.run(cmdLogin)
|
|
74
|
+
}
|
|
75
|
+
console.error('connectorPlugin load error', err)
|
|
76
|
+
throw err
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
async store(data: WebsiteData, options: { id: WebsiteId, connectorId: ConnectorId }) {
|
|
81
|
+
// Be sure that it is immutable
|
|
82
|
+
const myData = { ...data }
|
|
83
|
+
return await this.addToQueue(myData, options)
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
async addToQueue(data: WebsiteData, options) {
|
|
87
|
+
// Handle concurrent saving
|
|
88
|
+
if (lastPendingSaving && lastPendingSaving !== data) {
|
|
89
|
+
// Cancel previous saving
|
|
90
|
+
}
|
|
91
|
+
lastPendingSaving = data
|
|
92
|
+
// Go ahaed and save
|
|
93
|
+
return this.doStore(lastPendingSaving, options)
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
async doStore(data, options) {
|
|
97
|
+
if (editor.PublicationManager?.status === PublicationStatus.STATUS_PENDING) {
|
|
98
|
+
// Publication is pending, save is delayed
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
editor.once(ClientEvent.PUBLISH_END, () => {
|
|
101
|
+
resolve(this.doStore(data, options))
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
if (isSaving) {
|
|
107
|
+
// Concurrent saving, save is delayed
|
|
108
|
+
editor.once('storage:start:store', () => {
|
|
109
|
+
this.doStore(data, options)
|
|
110
|
+
})
|
|
111
|
+
} else {
|
|
112
|
+
if (lastPendingSaving === data) {
|
|
113
|
+
lastPendingSaving = null
|
|
114
|
+
isSaving = true
|
|
115
|
+
const user = await getCurrentUser(editor)
|
|
116
|
+
if (user) {
|
|
117
|
+
data.assets = removeTempDataFromAssetUrl(data.assets)
|
|
118
|
+
data.pages = removeTempDataFromPages(data.pages)
|
|
119
|
+
data.styles = removeTempDataFromStyles(data.styles)
|
|
120
|
+
await websiteSave({ websiteId: options.id, connectorId: user.storage.connectorId, data })
|
|
121
|
+
isSaving = false
|
|
122
|
+
} else {
|
|
123
|
+
// Not logged in save is delayed
|
|
124
|
+
editor.once(eventLoggedIn, () => {
|
|
125
|
+
isSaving = false
|
|
126
|
+
return editor.Storage.store()
|
|
127
|
+
})
|
|
128
|
+
editor.Commands.run(cmdLogin)
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
// Canceled saving
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('connectorPlugin store error', err)
|
|
136
|
+
isSaving = false
|
|
137
|
+
throw err
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
// Handle errors
|
|
142
|
+
editor.on('storage:error:load', (err: Error) => {
|
|
143
|
+
handleError(err)
|
|
144
|
+
})
|
|
145
|
+
editor.on('storage:error:store', (err: Error) => {
|
|
146
|
+
handleError(err)
|
|
147
|
+
})
|
|
148
|
+
editor.on('asset:upload:end', (err: Error) => {
|
|
149
|
+
editor.store()
|
|
150
|
+
})
|
|
151
|
+
editor.on('asset:upload:error', (err: Error) => {
|
|
152
|
+
handleError(err)
|
|
153
|
+
})
|
|
154
|
+
function handleError(_err: Error | string) {
|
|
155
|
+
const err: Error = typeof _err === 'string' ? JSON.parse(_err) : _err
|
|
156
|
+
console.error('Error with loading or saving website or uploading asset', err, err instanceof ApiError)
|
|
157
|
+
if (err instanceof ApiError) {
|
|
158
|
+
console.error('ApiError', err.httpStatusCode, err.message)
|
|
159
|
+
switch (err.httpStatusCode) {
|
|
160
|
+
case 404:
|
|
161
|
+
return editor.Modal.open({
|
|
162
|
+
title: 'Website not found',
|
|
163
|
+
|
|
164
|
+
content: `This website could not be found.<br><hr>${err.message}`,
|
|
165
|
+
})
|
|
166
|
+
case 403:
|
|
167
|
+
return editor.Modal.open({
|
|
168
|
+
title: 'Access denied',
|
|
169
|
+
content: `You are not allowed to access this website.<br><hr>${err.message}`,
|
|
170
|
+
})
|
|
171
|
+
case 401:
|
|
172
|
+
editor.trigger(eventLoggedOut)
|
|
173
|
+
return
|
|
174
|
+
default:
|
|
175
|
+
return editor.Modal.open({
|
|
176
|
+
title: 'Error',
|
|
177
|
+
content: `An error occured.<br>${err.message}`,
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
return editor.Modal.open({
|
|
182
|
+
title: 'Error',
|
|
183
|
+
content: `An error occured.<br>${err.message}`,
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { cmdAddSymbol } from '@silexlabs/grapesjs-symbols'
|
|
3
19
|
|
|
4
20
|
export const cmdPromptAddSymbol = 'symbol-prompt-add'
|
|
5
21
|
|
|
6
|
-
export default
|
|
22
|
+
export default (editor, opts) => {
|
|
7
23
|
function getNext(prefix) {
|
|
8
24
|
let idx = 1
|
|
9
25
|
while(editor.Symbols.find(s => s.get('label') === prefix + idx)) {
|
|
@@ -14,8 +30,8 @@ export default grapesjs.plugins.add(name, (editor, opts) => {
|
|
|
14
30
|
editor.Commands.add(cmdPromptAddSymbol, {
|
|
15
31
|
run: (_, sender) => {
|
|
16
32
|
const label = prompt('Label', getNext('Symbol '))
|
|
17
|
-
const icon =
|
|
33
|
+
const icon = 'fa-gem'
|
|
18
34
|
editor.runCommand(cmdAddSymbol, { label, icon })
|
|
19
35
|
}
|
|
20
36
|
})
|
|
21
|
-
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const pasteBtnClass = 'fa fa-fw fa-paste silex-button'
|
|
20
|
+
const disabledClass = ' disabled'
|
|
21
|
+
|
|
22
|
+
export default function(editor) {
|
|
23
|
+
// Add copy/paste buttons in the top bar
|
|
24
|
+
const [copyBtn, pasteBtn] = editor.Panels.addButton('options', [{
|
|
25
|
+
id: 'copy',
|
|
26
|
+
className: 'fa fa-fw fa-copy',
|
|
27
|
+
command: 'core:copy',
|
|
28
|
+
attributes: { title: 'Copy (Ctrl+C)' },
|
|
29
|
+
}, {
|
|
30
|
+
id: 'paste',
|
|
31
|
+
className: pasteBtnClass + disabledClass,
|
|
32
|
+
command: 'core:paste',
|
|
33
|
+
attributes: { title: 'Paste (Ctrl+V)' },
|
|
34
|
+
active: false,
|
|
35
|
+
}])
|
|
36
|
+
|
|
37
|
+
// Disable paste button if clipboard is empty
|
|
38
|
+
editor.EditorModel.on('change:clipboard', (model, value) => {
|
|
39
|
+
const hasClipboard = value && value.length > 0
|
|
40
|
+
pasteBtn.set('className', pasteBtnClass + (hasClipboard ? '' : disabledClass))
|
|
41
|
+
})
|
|
42
|
+
}
|