@silexlabs/silex-dashboard 1.0.2 → 1.0.4

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.
@@ -0,0 +1,25 @@
1
+ import templatePlugin from '/node_modules/@silexlabs/silex/dist/plugins/client/plugins/client/template.js'
2
+ import publicationRenderer from '/node_modules/@silexlabs/silex/dist/plugins/client/plugins/client/publicationRenderer.js'
3
+
4
+ export default async function(config, options) {
5
+ // Defaults
6
+ const opts = {
7
+ ...options,
8
+ }
9
+ await config.addPlugin(templatePlugin)
10
+ await config.addPlugin(publicationRenderer, {
11
+ css: {
12
+ frontMatter: true,
13
+ ext: '.css.liquid',
14
+ path: '../../../pages'
15
+ },
16
+ html: {
17
+ frontMatter: false,
18
+ path: '../../../_includes'
19
+ },
20
+ assets: {
21
+ path: '../../../',
22
+ url: '/',
23
+ },
24
+ })
25
+ }
package/.silex.js ADDED
@@ -0,0 +1,78 @@
1
+ const fs = require('node:fs/promises')
2
+ const { join } = require('node:path')
3
+ const express = require('express')
4
+ const node_modules = require('node_modules-path')
5
+ const serveStatic = require('serve-static')
6
+ const locale = require('locale')
7
+ const { withCache } = require('@silexlabs/silex/dist/plugins/server/plugins/server/Cache')
8
+ const { ServerEvent } = require('@silexlabs/silex').events
9
+
10
+ const { ConnectorType } = require('@silexlabs/silex/dist/server/types')
11
+ const FtpConnector = require('@silexlabs/silex/dist/plugins/server/plugins/server/FtpConnector').default
12
+ const GitlabConnector = require('@silexlabs/silex/dist/plugins/server/plugins/server/GitlabConnector').default
13
+ const {FsStorage} = require('@silexlabs/silex/dist/server/server/connectors/FsStorage')
14
+ const {FsHosting} = require('@silexlabs/silex/dist/server/server/connectors/FsHosting')
15
+
16
+ module.exports = async function(config, options) {
17
+ // Defaults
18
+ const opts = {
19
+ defaultLanguage: 'en',
20
+ rootPath: join(__dirname, '_site'),
21
+ ...options,
22
+ }
23
+
24
+ config.addHostingConnector([
25
+ new FsHosting(config, {
26
+ path: process.env.SILEX_FS_ROOT,
27
+ }),
28
+ new FtpConnector(config, {
29
+ type: ConnectorType.HOSTING,
30
+ }),
31
+ ])
32
+
33
+ //config.addStorageConnector([
34
+ // //new FsStorage(config, {
35
+ // // path: process.env.SILEX_FS_ROOT,
36
+ // //}),
37
+ // new FtpConnector(config, {
38
+ // type: ConnectorType.STORAGE,
39
+ // }),
40
+ // new GitlabConnector(config, {
41
+ // clientId: process.env.GITLAB_CLIENT_ID,
42
+ // clientSecret: process.env.GITLAB_CLIENT_SECRET,
43
+ // }),
44
+ //])
45
+
46
+ // Detect language from browser
47
+ const languages = JSON.parse(await fs.readFile(join(__dirname, '_data/languages.json')))
48
+
49
+ // Serve the dashboard and the editor
50
+ config.on(ServerEvent.STARTUP_START, ({app}) => {
51
+ const router = express.Router()
52
+ app.use(router)
53
+
54
+ // Use cache
55
+ router.use(withCache)
56
+
57
+ // Localization populate req.locale
58
+ router.use(locale(languages.map(l => l.code), opts.defaultLanguage))
59
+
60
+ // Serve the dashboard
61
+ router.use('/', serveStatic(opts.rootPath))
62
+
63
+ // Serve scripts
64
+ //router.use('/js/vue/', express.static(node_modules('vue') + '/vue'))
65
+ //router.use('/js/@silexlabs/silex/', express.static(node_modules('@silexlabs/silex') + '/@silexlabs/silex'))
66
+ router.use('/', express.static(join(__dirname, 'public')))
67
+
68
+ // Serve the editor when the ?id param is present in the URL
69
+ const editorRouter = express.Router()
70
+ console.log('dashboard route /', {opts})
71
+ editorRouter.use('/', (req, res, next) => {
72
+ console.log('dashboard route / called', req.path, req.query.id, req.locale)
73
+ if (req.path === '/' && !req.query.id) res.redirect(`/${req.locale}/`)
74
+ else next()
75
+ })
76
+ app.use(editorRouter)
77
+ })
78
+ }
@@ -7,7 +7,15 @@
7
7
  "Failed to create website": "Failed to create website",
8
8
  "Deleting a website? Are your sure? Really?": "Deleting a website? Are your sure? Really?",
9
9
  "Website deleted successfully": "Website deleted successfully",
10
- "Failed to delete website": "Failed to delete website"
10
+ "Failed to delete website": "Failed to delete website",
11
+ "New name for this website": "New name for this website",
12
+ "Website renamed successfully": "Website renamed successfully",
13
+ "Login failed": "Error, login failed.",
14
+ "Logout": "Logout",
15
+ "Logging out": "Logging out",
16
+ "Back to home": "< Back",
17
+ "Welcome to Silex": "Welcome to Silex",
18
+ "Please login to continue": "Please login to continue"
11
19
  },
12
20
  "fr": {
13
21
  "Failed to fetch websites": "Erreur, impossible de récupérer la liste des sites",
@@ -17,6 +25,14 @@
17
25
  "Failed to create website": "Erreur, le site n\\'a pas été créé",
18
26
  "Deleting a website? Are your sure? Really?": "Etes vous sûr.e de vouloir supprimer définitivement ce site ?",
19
27
  "Website deleted successfully": "Le site a bien été effacé",
20
- "Failed to delete website": "Erreur, le site n\\'a pas été effacé"
28
+ "Failed to delete website": "Erreur, le site n\\'a pas été effacé",
29
+ "New name for this website": "Nouveau nom",
30
+ "Website renamed successfully": "Changement de nom effectué",
31
+ "Login failed": "Erreur, impossible de se connecter.",
32
+ "Logout": "Déconnexion",
33
+ "Logging out": "Déconnexion en cours",
34
+ "Back to home": "< Retour",
35
+ "Welcome to Silex": "Bienvenue sur Silex",
36
+ "Please login to continue": "Merci de vous connecter pour continuer"
21
37
  }
22
38
  }
@@ -0,0 +1,86 @@
1
+ <script src="/node_modules/vue/dist/vue.global.js"></script>
2
+ <script src="/js/main.js"></script>
3
+ <script type="module">
4
+ window.addEventListener('load', function() {
5
+ const { createApp } = Vue;
6
+ const { api, constants, types } = silex;
7
+ const {
8
+ ConnectorType,
9
+ } = types
10
+ const {
11
+ connectorList,
12
+ logout,
13
+ } = api
14
+
15
+ const App = {
16
+ data() {
17
+ return {
18
+ connectors: [],
19
+ error: null,
20
+ message: null,
21
+ loading: true,
22
+ lastConnector: null,
23
+ }
24
+ },
25
+ mounted() {
26
+ this.init()
27
+ window.addEventListener('message', (event) => {
28
+ if(event.data && event.data.type === 'login') {
29
+ this.loginResult(event.data)
30
+ }
31
+ })
32
+ },
33
+
34
+ methods: {
35
+ async init() {
36
+ try {
37
+ this.loading = true
38
+ console.log('init')
39
+ this.connectors = await connectorList({type: ConnectorType.STORAGE})
40
+ console.log('connectors', this.connectors)
41
+ this.loading = false
42
+ } catch (error) {
43
+ console.error(error)
44
+ this.error = error
45
+ this.loading = false
46
+ }
47
+ },
48
+ openLogin(connector) {
49
+ this.lastConnector = connector
50
+ const nonOAuthUrl = `${constants.API_PATH}${constants.API_CONNECTOR_PATH}${constants.API_CONNECTOR_LOGIN}?connectorId=${connector.connectorId}&type=${connector.type}`
51
+ console.log('openLogin', connector.oauthUrl, nonOAuthUrl)
52
+ window.open(connector.oauthUrl || nonOAuthUrl, '_blank')
53
+ },
54
+ loginResult(data) {
55
+ console.log('loginResult', data)
56
+ if(data.error) {
57
+ this.error = data.error
58
+ this.message = `{{ api-translations[lang]["Login failed"] }} ${data.message}`
59
+ } else {
60
+ window.location.href = '/'
61
+ }
62
+ },
63
+ async logout() {
64
+ try {
65
+ this.message = '{{ api-translations[lang]["Logging out"] }}'
66
+ await logout({type: ConnectorType.STORAGE, connectorId: this.lastConnector.connectorId})
67
+ this.loggedIn = false
68
+ this.user = null
69
+ this.websites = []
70
+ this.loading = false
71
+ this.message = ''
72
+ this.error = false
73
+ } catch (error) {
74
+ console.error(error)
75
+ this.error = error
76
+ this.message = error.message
77
+ this.loading = false
78
+ }
79
+ },
80
+ },
81
+ };
82
+
83
+ // Start vue app
84
+ createApp(App).mount('.app');
85
+ })
86
+ </script>
@@ -0,0 +1,149 @@
1
+ <script src="/node_modules/vue/dist/vue.global.js"></script>
2
+ <script src="/js/main.js"></script>
3
+ <script type="module">
4
+ const CONNECTORS_PATH = '/connectors/'
5
+ window.addEventListener('load', function() {
6
+ const { createApp } = Vue;
7
+ const { api, constants, types } = silex;
8
+ const {
9
+ ConnectorType,
10
+ } = types
11
+ const {
12
+ getUser,
13
+ logout,
14
+ websiteDelete,
15
+ websiteList,
16
+ websiteCreate,
17
+ websiteMetaWrite,
18
+ } = api
19
+
20
+ const App = {
21
+ data() {
22
+ return {
23
+ websites: [],
24
+ newWebsiteName: '',
25
+ showCreationForm: false,
26
+ error: null,
27
+ message: null,
28
+ loggedIn: false,
29
+ loading: true,
30
+ storage: null,
31
+ user: null,
32
+ showMenu: false,
33
+ }
34
+ },
35
+ mounted() {
36
+ this.init()
37
+ },
38
+
39
+ methods: {
40
+ async init() {
41
+ try {
42
+ // Debug
43
+ window.app = this
44
+ const user = await getUser({type: ConnectorType.STORAGE})
45
+ if(user) {
46
+ this.user = user
47
+ this.loggedIn = true
48
+ this.websites = await websiteList({connectorId: this.user.storage.connectorId})
49
+ this.loading = false
50
+ } else {
51
+ this.openLogin()
52
+ }
53
+ } catch (error) {
54
+ console.error(error)
55
+ this.loading = false
56
+ if(error.code === 401 || error.httpStatusCode === 401) {
57
+ this.loggedIn = false
58
+ this.openLogin()
59
+ } else {
60
+ this.error = error
61
+ }
62
+ }
63
+ },
64
+
65
+ openLogin(id, lang) {
66
+ //throw new Error('debug')
67
+ const path = `/{{lang}}${CONNECTORS_PATH}`
68
+ console.log(window.location.pathname, window.location.path, path)
69
+ if(window.location.pathname === path) return
70
+ window.open(path, '_self')
71
+ },
72
+
73
+ openEditor(id, lang) {
74
+ window.open(`/?id=${id}&lang=${lang}&connectorId=${this.user.storage.connectorId}`, '_blank')
75
+ },
76
+
77
+ async logout() {
78
+ await logout({
79
+ type: ConnectorType.STORAGE,
80
+ connectorId: this.user.storage.connectorId,
81
+ })
82
+ window.location.reload()
83
+ },
84
+
85
+ async createWebsite() {
86
+ if (!this.newWebsiteName) throw new Error('{{ api-translations[lang]["You need to provide a website name"] }}')
87
+ this.loading = true
88
+ try {
89
+ const websiteId = this.newWebsiteName.replace(/[/\\?%*:|"<>]/g, '_')
90
+ const result = await websiteCreate({
91
+ websiteId,
92
+ data: {
93
+ name: this.newWebsiteName,
94
+ imageUrl: null,
95
+ },
96
+ connectorId: this.user.storage.connectorId
97
+ })
98
+ this.message = '{{ api-translations[lang]["Website created successfully"] }}'
99
+ this.newWebsiteName = ''
100
+ this.showCreationForm = false;
101
+ this.websites = await websiteList({connectorId: this.user.storage.connectorId})
102
+ this.loading = false
103
+ return result
104
+ } catch (error) {
105
+ this.loading = false
106
+ console.error(error)
107
+ this.error = '{{ api-translations[lang]["Failed to create website"] }}'
108
+ }
109
+ },
110
+
111
+ async deleteWebsite(websiteId) {
112
+ const ok = confirm('{{ api-translations[lang]["Deleting a website? Are your sure? Really?"] }}')
113
+ if (!ok) return
114
+ this.loading = true
115
+ try {
116
+ const result = await websiteDelete({websiteId, connectorId: this.user.storage.connectorId})
117
+ this.message = '{{ api-translations[lang]["Website deleted successfully"] }}'
118
+ this.websites = await websiteList({connectorId: this.user.storage.connectorId})
119
+ this.loading = false
120
+ return result
121
+ } catch (error) {
122
+ this.loading = false
123
+ this.error = '{{ api-translations[lang]["Failed to delete website"] }}'
124
+ }
125
+ },
126
+
127
+ async renameWebsite(websiteId) {
128
+ const website = this.websites.find(w => w.websiteId === websiteId)
129
+ const name = prompt('{{ api-translations[lang]["New name for this website"] }}', website.name)
130
+ if (!name) return
131
+ this.loading = true
132
+ try {
133
+ const result = await websiteMetaWrite({websiteId, connectorId: this.user.storage.connectorId, data: { name }})
134
+ this.message = '{{ api-translations[lang]["Website renamed successfully"] }}'
135
+ this.websites = await websiteList({connectorId: this.user.storage.connectorId})
136
+ this.loading = false
137
+ return result
138
+ } catch (error) {
139
+ this.loading = false
140
+ this.error = '{{ api-translations[lang]["Failed to delete website"] }}'
141
+ }
142
+ },
143
+ },
144
+ };
145
+
146
+ // Start vue app
147
+ createApp(App).mount('.app');
148
+ })
149
+ </script>
@@ -0,0 +1,99 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="">
4
+ <head>
5
+ <link rel="stylesheet" href="/css/connectors.css" />
6
+ {% render "alternate.liquid" languages: languages lang: lang page: page %}
7
+
8
+ <style>
9
+ .button { cursor: pointer; }
10
+ a { text-decoration: none; }
11
+ a:hover { text-decoration: underline; }
12
+
13
+ .skeleton-anim:after {
14
+ width: 100%;
15
+ height: 100%;
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ content: "";
20
+ background:
21
+ linear-gradient(0.25turn, transparent, rgba(255,255,255,.75), transparent),
22
+ linear-gradient(transparent, transparent),
23
+ radial-gradient(38px circle at 19px 19px, transparent 50%, transparent 51%),
24
+ linear-gradient(transparent, transparent);
25
+ background-repeat: no-repeat;
26
+ background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
27
+ background-position: -315px 0, 0 0, 0px 190px, 50px 195px;
28
+ animation: loading 1.5s infinite;
29
+ }
30
+
31
+ @keyframes loading {
32
+ to {
33
+ background-position: 200% 0, 0 0, 0 190px, 50px 195px;
34
+ }
35
+ }
36
+
37
+ </style>
38
+ {% render "api-connectors.js.html" frontmatter: frontmatter page: page site: site api-translations: api-translations lang: lang %}
39
+
40
+ <title>{{ title }}</title>
41
+ <link rel="icon" href="" />
42
+ <meta property="description" content=""/>
43
+ <meta property="og:title" content=""/>
44
+ <meta property="og:description" content=""/>
45
+ <meta property="og:image" content=""/>
46
+ </head>
47
+ <body
48
+ id="i2hcfw"
49
+ class=" app"
50
+
51
+
52
+ ><A
53
+ id="ixzhcr" href="/"
54
+ class="button button-bar__item--secondary "
55
+
56
+
57
+ >{{ api-translations[lang]["Back to home"] }}</A><div
58
+ id="imgx81"
59
+
60
+
61
+
62
+ ><H1
63
+
64
+
65
+
66
+
67
+ >{{ api-translations[lang]["Welcome to Silex"] }}</H1><div
68
+
69
+ class="subtitle "
70
+
71
+
72
+ >{{ api-translations[lang]["Please login to continue"] }}</div><div
73
+ id="in62y2"
74
+ class="button-bar "
75
+
76
+
77
+ ><A
78
+ id="isqe61" href="https://"
79
+ class="h-space button-bar__item--main button-bar_item button big-button "
80
+ v-if="!loading" v-for="(connector, index) in connectors" :key="index" :style="{ backgroundColor: connector.background, color: connector.color }" @click="openLogin(connector)"
81
+
82
+ ><div
83
+ id="i87asw"
84
+
85
+ v-text="connector.displayName"
86
+
87
+ >Insert your text here</div></A></div><div
88
+ id="i9msnk"
89
+
90
+ v-if="error" v-html="message"
91
+
92
+ >Insert your text here</div><div
93
+ id="i6akll"
94
+ class="button button--tertiary "
95
+ v-if="error" @click="logout()"
96
+
97
+ >{{ api-translations[lang]["Logout"] }}</div></div></body>
98
+ </html>
99
+