@silexlabs/silex 3.0.0-alpha.39 → 3.0.0-alpha.41

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.
Files changed (110) hide show
  1. package/.silex.js +38 -8
  2. package/dist/client/client/config.d.ts +11 -41
  3. package/dist/client/client/grapesjs/LoginDialog.d.ts +13 -0
  4. package/dist/client/client/grapesjs/PublicationManager.d.ts +69 -0
  5. package/dist/client/client/grapesjs/PublicationUi.d.ts +58 -0
  6. package/dist/client/client/grapesjs/index.d.ts +18 -44
  7. package/dist/client/client/grapesjs/storage.d.ts +1 -0
  8. package/dist/client/client/services.d.ts +35 -0
  9. package/dist/client/constants.d.ts +17 -0
  10. package/dist/client/css/admin.css +86 -3
  11. package/dist/client/js/main.js +201 -90
  12. package/dist/client/js/main.js.LICENSE.txt +6 -0
  13. package/dist/client/types.d.ts +200 -29
  14. package/dist/constants.d.ts +21 -0
  15. package/dist/constants.js +38 -1
  16. package/dist/constants.js.map +1 -0
  17. package/dist/events.d.ts +2 -0
  18. package/dist/events.js +17 -0
  19. package/dist/events.js.map +1 -0
  20. package/dist/plugins/AuthPlugin.d.ts +1 -0
  21. package/dist/plugins/AuthPlugin.js +38 -0
  22. package/dist/plugins/AuthPlugin.js.map +1 -0
  23. package/dist/plugins/Cache.d.ts +2 -0
  24. package/dist/plugins/Cache.js +32 -0
  25. package/dist/plugins/Cache.js.map +1 -0
  26. package/dist/plugins/FtpBackend.d.ts +92 -0
  27. package/dist/plugins/FtpBackend.js +604 -0
  28. package/dist/plugins/FtpBackend.js.map +1 -0
  29. package/dist/plugins/HooksPlugin.d.ts +7 -0
  30. package/dist/plugins/HooksPlugin.js +76 -0
  31. package/dist/plugins/HooksPlugin.js.map +1 -0
  32. package/dist/plugins/PublicationPlugin.d.ts +17 -0
  33. package/dist/plugins/PublicationPlugin.js +170 -0
  34. package/dist/plugins/PublicationPlugin.js.map +1 -0
  35. package/dist/plugins/SslPlugin.d.ts +1 -0
  36. package/dist/plugins/SslPlugin.js +86 -0
  37. package/dist/plugins/SslPlugin.js.map +1 -0
  38. package/dist/plugins/StaticPlugin.d.ts +1 -0
  39. package/dist/plugins/StaticPlugin.js +66 -0
  40. package/dist/plugins/StaticPlugin.js.map +1 -0
  41. package/dist/plugins/WebsitePlugin.d.ts +14 -0
  42. package/dist/plugins/WebsitePlugin.js +302 -0
  43. package/dist/plugins/WebsitePlugin.js.map +1 -0
  44. package/dist/server/backends/FsBackend.d.ts +42 -0
  45. package/dist/server/backends/FsBackend.js +269 -0
  46. package/dist/server/backends/FsBackend.js.map +1 -0
  47. package/dist/server/backends/index.d.ts +95 -0
  48. package/dist/server/backends/index.js +255 -0
  49. package/dist/server/backends/index.js.map +1 -0
  50. package/dist/server/cli.js +0 -1
  51. package/dist/server/config.d.ts +58 -0
  52. package/dist/server/config.js +128 -24
  53. package/dist/server/config.js.map +1 -0
  54. package/dist/server/express.js +31 -3
  55. package/dist/server/index.js +9 -20
  56. package/dist/server/jobs.d.ts +6 -0
  57. package/dist/server/jobs.js +75 -0
  58. package/dist/server/jobs.js.map +1 -0
  59. package/dist/server/utils/validation.d.ts +7 -0
  60. package/dist/server/utils/validation.js +37 -0
  61. package/dist/server/utils/validation.js.map +1 -0
  62. package/dist/types.d.ts +270 -0
  63. package/dist/types.js +35 -28
  64. package/dist/types.js.map +1 -0
  65. package/package.json +19 -8
  66. package/public/silex.js +17 -0
  67. package/src/css/dialog.scss +9 -2
  68. package/src/css/grapesjs.scss +79 -0
  69. package/src/css/project-bar.scss +2 -2
  70. package/src/example-client-config.js +17 -0
  71. package/src/html/templates/includes.pug +0 -1
  72. package/src/ts/client/config.ts +7 -6
  73. package/src/ts/client/grapesjs/LoginDialog.ts +190 -0
  74. package/src/ts/client/grapesjs/PublicationManager.ts +333 -0
  75. package/src/ts/client/grapesjs/PublicationUi.ts +320 -0
  76. package/src/ts/client/grapesjs/index.ts +88 -85
  77. package/src/ts/client/grapesjs/storage.ts +110 -0
  78. package/src/ts/client/index.ts +5 -7
  79. package/src/ts/client/services.ts +129 -0
  80. package/src/ts/constants.ts +21 -0
  81. package/src/ts/plugins/AuthPlugin.ts +38 -0
  82. package/src/ts/plugins/Cache.ts +28 -0
  83. package/src/ts/plugins/FtpBackend.ts +689 -0
  84. package/src/ts/plugins/HooksPlugin.ts +79 -0
  85. package/src/ts/plugins/PublicationPlugin.ts +170 -0
  86. package/src/{plugins/SslPlugin.js → ts/plugins/SslPlugin.ts} +24 -6
  87. package/src/ts/plugins/StaticPlugin.ts +68 -0
  88. package/src/ts/plugins/WebsitePlugin.ts +318 -0
  89. package/src/ts/server/backends/FsBackend.ts +266 -0
  90. package/src/ts/server/backends/index.ts +309 -0
  91. package/src/ts/server/cli.ts +0 -2
  92. package/src/ts/server/config.ts +103 -33
  93. package/src/ts/server/express.ts +37 -3
  94. package/src/ts/server/index.ts +24 -14
  95. package/src/ts/server/jobs.test.ts +74 -0
  96. package/src/ts/server/jobs.ts +77 -0
  97. package/src/ts/server/utils/validation.ts +33 -0
  98. package/src/ts/types.ts +167 -59
  99. package/dist/client/client/grapesjs/publish.d.ts +0 -18
  100. package/dist/page.js +0 -15
  101. package/src/plugins/AuthPlugin.js +0 -21
  102. package/src/plugins/Cache.js +0 -11
  103. package/src/plugins/DefaultBackend.js +0 -149
  104. package/src/plugins/ExpressPlugin.js +0 -39
  105. package/src/plugins/HooksPlugin.js +0 -58
  106. package/src/plugins/PublishPlugin.js +0 -69
  107. package/src/plugins/StaticPlugin.js +0 -48
  108. package/src/plugins/WebsitePlugin.js +0 -207
  109. package/src/ts/client/grapesjs/publish.ts +0 -403
  110. /package/.silex/default/{.silex.data.json → website.json} +0 -0
@@ -18,17 +18,24 @@
18
18
  background-color: variables.$primaryColor;
19
19
  z-index: variables.$z-dialog-inline;
20
20
  border-radius: 3px;
21
+ border: 2px solid rgba(0, 0, 0, 0.25);
21
22
  display: flex;
22
23
  flex-direction: column;
23
- padding: 10px;
24
+ header {
25
+ padding: 10px;
26
+ }
24
27
  main {
25
28
  flex-grow: 1;
29
+ padding: 10px;
26
30
  }
27
31
  footer {
28
- padding: 5px;
32
+ padding: 10px;
29
33
  text-align: right;
30
34
  }
31
35
  a {
32
36
  color: variables.$quaternaryColor;
33
37
  }
38
+ header > * {
39
+ margin: 0;
40
+ }
34
41
  }
@@ -42,3 +42,82 @@
42
42
  }
43
43
  }
44
44
 
45
+ /*
46
+ */
47
+ // Font awesome 5 fix
48
+ // https://github.com/GrapesJS/grapesjs/issues/644#issuecomment-833215677
49
+ .gjs-editor-cont .fa {
50
+ font-weight: 400;
51
+ }
52
+
53
+ .fa-square-o:before {
54
+ content: "\f0c8";
55
+ }
56
+
57
+ .fa-trash-o:before {
58
+ content: "\f1f8";
59
+ }
60
+
61
+ .fa-map-o:before {
62
+ content: "\f279";
63
+ }
64
+
65
+ .fa-youtube-play:before {
66
+ content: "\f04b";
67
+ }
68
+
69
+ /* Fix: open close chevrons: FA5 has the tags in different order ?!!? */
70
+ .fa-chevron-right:before {
71
+ content: "\f054";
72
+ }
73
+
74
+ .fa-chevron-down:before {
75
+ content: "\f078";
76
+ }
77
+
78
+ // Font awesome 6 fix
79
+ .fa-cog:before {
80
+ font-weight: 900;
81
+ }
82
+
83
+ .fa-paint-brush:before {
84
+ font-weight: 900;
85
+ }
86
+
87
+ .fa-arrows-alt:before {
88
+ content: "\f065";
89
+ font-weight: 900;
90
+ }
91
+
92
+ .fa-caret-down:before {
93
+ content: "\f0d7";
94
+ font-weight: 900;
95
+ }
96
+
97
+ .fa-caret-right:before {
98
+ content: "\f0da";
99
+ font-weight: 900;
100
+ }
101
+
102
+ .fa-trash:before {
103
+ content: "\f2ed";
104
+ font-weight: 900;
105
+ }
106
+
107
+ .fa-list:before {
108
+ content: "\f03a";
109
+ font-weight: 900;
110
+ }
111
+
112
+ /*
113
+ .fa-plus:before {
114
+ content: "+";
115
+ font-size: 35px;
116
+ }
117
+ .fa-diamond:before {
118
+ content: "\f3a5";
119
+ }
120
+ // .fa-plus {
121
+ // background-image: svg(<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H48c-17.7 0-32 14.3-32 32s14.3 32 32 32H192V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H400c17.7 0 32-14.3 32-32s-14.3-32-32-32H256V80z"/></svg>);
122
+ // }
123
+ */
@@ -85,8 +85,8 @@ iframe.enable-squeeze.silex-squeeze-left {
85
85
  font-weight: 400;
86
86
  span {
87
87
  position: relative;
88
- left: -6px;
89
- top: 6px;
88
+ left: -2px;
89
+ top: -11px;
90
90
  font-weight: bolder;
91
91
  background-color: #444;
92
92
  border-radius: 100%;
@@ -1,3 +1,20 @@
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
+
1
18
  import directusStorage from 'https://unpkg.com/@silexlabs/grapesjs-directus-storage'
2
19
  console.log('directusStorage', directusStorage, directusStorage?.default)
3
20
 
@@ -1,2 +1 @@
1
1
  link(rel='stylesheet', type='text/css', href='css/admin.css')
2
-
@@ -17,15 +17,16 @@
17
17
 
18
18
  import { Config, Plugin } from '@silexlabs/silex-plugins'
19
19
  import { getEditorConfig } from './grapesjs'
20
- import { CLIENT_CONFIG_FILE_NAME } from '../constants'
20
+ import { CLIENT_CONFIG_FILE_NAME, DEFAULT_BACKEND_ID, DEFAULT_LANGUAGE, DEFAULT_WEBSITE_ID } from '../constants'
21
21
 
22
22
  /**
23
23
  * @fileoverview Silex client side config
24
24
  */
25
25
 
26
- const id = new URL(location.href).searchParams.get('id') || 'default'
27
- const lang = new URL(location.href).searchParams.get('lang') || 'en'
28
- const rootUrl = `${location.protocol}//${location.host}${location.pathname}`
26
+ const id = new URL(location.href).searchParams.get('id') ?? DEFAULT_WEBSITE_ID
27
+ const backendId = new URL(location.href).searchParams.get('backendId') ?? DEFAULT_BACKEND_ID
28
+ const lang = new URL(location.href).searchParams.get('lang') ?? DEFAULT_LANGUAGE
29
+ const rootUrl = window.location.origin
29
30
 
30
31
  export class SilexConfig extends Config {
31
32
  /**
@@ -41,13 +42,13 @@ export class SilexConfig extends Config {
41
42
  /**
42
43
  * Grapesjs config
43
44
  */
44
- editor = getEditorConfig(id, rootUrl)
45
+ editor = getEditorConfig(id, backendId, rootUrl)
45
46
 
46
47
  /**
47
48
  * Client config url
48
49
  * This is the url of the config file which is a plugin
49
50
  */
50
- clientConfigUrl = `${rootUrl}${CLIENT_CONFIG_FILE_NAME}`
51
+ clientConfigUrl = `${rootUrl}/${CLIENT_CONFIG_FILE_NAME}`
51
52
 
52
53
  /**
53
54
  * GrapesJs plugins
@@ -0,0 +1,190 @@
1
+ import { html, render } from 'lit-html'
2
+ import { Editor } from 'grapesjs'
3
+ import { ApiBackendLoggedInPostMessage, BackendData, BackendId, BackendType } from '../../types'
4
+ import { LoginStatus, backendList, loginStatus, logout } from '../services'
5
+ import { WebsiteId } from '../../types'
6
+
7
+ export const cmdLogin = 'silex:auth:login'
8
+ export const eventLoggingIn = 'silex:auth:logging-in'
9
+ export const eventLoggedIn = 'silex:auth:logged-in'
10
+ export const eventLoginFailed = 'silex:auth:login-failed'
11
+ export const eventLoggedOut = 'silex:auth:logged-out'
12
+
13
+ export interface LoginDialogOptions {
14
+ id: WebsiteId,
15
+ }
16
+
17
+ export async function getCurrentLoginStatus(editor: Editor): Promise<LoginStatus> {
18
+ return editor.getModel().get('loginStatus') as LoginStatus // ?? { backend: null, user: null, websiteMeta: null }
19
+ }
20
+
21
+ let open = false
22
+ let body: HTMLElement | null = null
23
+ export default function loginDialogPlugin(editor, opts) {
24
+ // Options
25
+ const options: LoginDialogOptions = {
26
+ ...opts,
27
+ }
28
+
29
+ // Commands and events
30
+ editor.Commands.add(cmdLogin, {
31
+ async run(editor: Editor) { await openDialog() },
32
+ stop(editor: Editor) { closeDialog() },
33
+ })
34
+ editor.on(eventLoggedOut, async () => openDialog())
35
+
36
+ // Dialog API
37
+ function closeDialog() {
38
+ if (open) {
39
+ editor.Modal.close()
40
+ open = false
41
+ }
42
+ }
43
+ async function openDialog() {
44
+ editor.trigger(eventLoggingIn)
45
+ open = true
46
+ editor.Modal.open({
47
+ title: 'Login',
48
+ content: '<div id="LoginDialog__content"></div>',
49
+ }, {
50
+ closeOnConfirm: false,
51
+ closeOnEscape: false,
52
+ closeOnOverlayClick: false,
53
+ })
54
+ body = document.querySelector('#LoginDialog__content')
55
+ if (!body) {
56
+ throw new Error('Dialog creation failed')
57
+ }
58
+ render(html`Logging in...`, body)
59
+ return loadStorageList(async list => onStorageList(list))
60
+ }
61
+ async function onStorageList(list) {
62
+ const loggedIn = list.find(backend => backend.isLoggedIn)
63
+ if (loggedIn) {
64
+ try {
65
+ const status = await updateLoginStatus(loggedIn.backendId, loggedIn.type)
66
+ editor.trigger(eventLoggedIn, status)
67
+ return closeDialog()
68
+ } catch (err) {
69
+ console.error('Error with updating login status', err)
70
+ render(html`
71
+ <main>
72
+ <p>There was an error with updating the login status. ${err.message}</p>
73
+ </main>
74
+ <footer>
75
+ <button class="silex-button silex-button--primary" @click=${() => loadStorageList(async list => onStorageList(list))}>Retry</button>
76
+ <button class="silex-button" @click=${async () => {
77
+ await logout(loggedIn.backendId, loggedIn.type)
78
+ openDialog()
79
+ }}>Login with another backend</button>
80
+ </footer>
81
+ `, body)
82
+ }
83
+ return
84
+ }
85
+ // Display the list of storage and continue to login
86
+ render(html`
87
+ <main>
88
+ <p>Login and give Silex access to a file storage.</p>
89
+ ${list.map(backend => html`
90
+ <button
91
+ class="silex-button silex-button--primary"
92
+ id="publish-button--primary"
93
+ @click=${() => loginWithBackend(backend)}
94
+ >Login with ${backend.displayName}</button>
95
+ `)}
96
+ </main>
97
+ <footer>
98
+ </footer>
99
+ `, body)
100
+ }
101
+
102
+ // Auth management
103
+ async function loadStorageList(done: (list: BackendData[]) => Promise<void>) {
104
+ try {
105
+ const storageProviders = await backendList(BackendType.STORAGE)
106
+ await done(storageProviders)
107
+ } catch (err) {
108
+ console.error('Error with loading storage providers', err)
109
+ render(html`
110
+ <main>
111
+ An error occured while loading the storage providers: ${err.message}
112
+ </main>
113
+ <footer>
114
+ <button type="button" class="gjs-btn-prim" @click=${() => loadStorageList(done)}>Retry</button>
115
+ </footer>
116
+ `, body)
117
+ }
118
+ }
119
+ async function loginWithBackend(provider: BackendData) {
120
+ window.open(provider.authUrl, '_blank')
121
+ return new Promise(resolve => {
122
+ render(html`
123
+ <main>
124
+ <p>Waiting for your authorization in popup window...</p>
125
+ </main>
126
+ <footer>
127
+ <button type="button" class="gjs-btn-prim" @click=${() => openDialog()}>Cancel</button>
128
+ </footer>
129
+ `, body)
130
+ const onMessage = async (event) => {
131
+ if (event.data?.type === 'login') {
132
+ window.removeEventListener('message', onMessage)
133
+ const data = event.data as ApiBackendLoggedInPostMessage
134
+ const { backendId, error, message } = data
135
+ if (error) {
136
+ // Error, start over
137
+ console.error('login error', message)
138
+ render(html`
139
+ <main>
140
+ <p>Login failed with error: ${message}</p>
141
+ <footer>
142
+ <button type="button" class="gjs-btn-prim" @click=${() => openDialog()}>Retry</button>
143
+ ${ backendId ? html`<button class="silex-button" @click=${async () => {
144
+ await logout(backendId, provider.type)
145
+ openDialog()
146
+ }}>Login with another backend</button>` : '' }
147
+
148
+ </footer>
149
+ `, body)
150
+ editor.trigger(eventLoginFailed)
151
+ } else {
152
+ try {
153
+ render(html`
154
+ <main>
155
+ <p>Loging in...</p>
156
+ </main>
157
+ <footer>
158
+ </footer>
159
+ `, body)
160
+ const status = await updateLoginStatus(backendId, provider.type)
161
+ editor.trigger(eventLoggedIn, status)
162
+ closeDialog()
163
+ } catch (err) {
164
+ console.error('Error with loading login status', err)
165
+ render(html`
166
+ <main>
167
+ An error occured, could not get your data.
168
+ ${err.message}
169
+ </main>
170
+ <footer>
171
+ <button type="button" class="gjs-btn-prim" @click=${() => openDialog()}>Retry</button>
172
+ <button class="silex-button" @click=${async () => {
173
+ await logout(backendId, provider.type)
174
+ openDialog()
175
+ }}>Login with another backend</button>
176
+ </footer>
177
+ `, body)
178
+ }
179
+ }
180
+ }
181
+ }
182
+ window.addEventListener('message', onMessage, false)
183
+ })
184
+ }
185
+ async function updateLoginStatus(backendId: BackendId, type: BackendType): Promise<LoginStatus> {
186
+ const status = await loginStatus(backendId, type, options.id)
187
+ editor.getModel().set('loginStatus', status)
188
+ return status
189
+ }
190
+ }