@lilaquadrat/design-core 0.2.1 → 0.3.0
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/README.md +76 -3
- package/html/index.server.html +1 -8
- package/package.json +54 -54
- package/src/client-entry.ts +8 -8
- package/src/components/partials/error.partial.vue +19 -19
- package/src/components/partials/main-components.partial.vue +75 -70
- package/src/components/partials/qrcode.partial.vue +8 -8
- package/src/functions/AuthProviderFactory.ts +30 -0
- package/src/functions/PaymenyProviderFactory.ts +11 -11
- package/src/functions/auth0.provider.ts +75 -0
- package/src/functions/keycloak.provider.ts +228 -0
- package/src/functions/lila-dom.ts +50 -50
- package/src/functions/shopify.provider.ts +176 -154
- package/src/functions/stripe.provider.ts +120 -108
- package/src/globals.d.ts +1 -2
- package/src/index.ts +9 -7
- package/src/interfaces/AuthCallbackResult.interface.ts +5 -0
- package/src/interfaces/AuthConfig.interface.ts +13 -0
- package/src/interfaces/AuthProvider.interface.ts +15 -0
- package/src/interfaces/FrontendConfig.interface.ts +11 -40
- package/src/interfaces/GenericEvents.interface.ts +1 -1
- package/src/interfaces/IdTokenExtended.interface.ts +13 -4
- package/src/interfaces/PaymentProvider.interface.ts +2 -2
- package/src/interfaces/RenderOptions.interface.ts +12 -0
- package/src/libs/ActionNotice.ts +125 -125
- package/src/libs/Models.class.ts +219 -221
- package/src/main.ts +41 -36
- package/src/mixins/createCookieString.ts +50 -36
- package/src/mixins/createModelDeclaration.ts +22 -19
- package/src/mixins/createRouter.ts +12 -12
- package/src/mixins/date.ts +4 -2
- package/src/mixins/formatSize.ts +5 -5
- package/src/mixins/getAnchor.ts +1 -1
- package/src/mixins/getRoutes.ts +13 -25
- package/src/mixins/hasSlotContent.ts +22 -16
- package/src/mixins/hooks.ts +101 -60
- package/src/mixins/loadComponents.ts +60 -58
- package/src/mixins/logger.ts +17 -13
- package/src/mixins/replaceVariables.ts +10 -8
- package/src/mixins/scroll.ts +61 -45
- package/src/models/Address.model.ts +7 -7
- package/src/models/Contact.model.ts +14 -14
- package/src/plugins/analytics.ts +198 -0
- package/src/plugins/auth.ts +74 -60
- package/src/plugins/currency.ts +10 -10
- package/src/plugins/events.ts +101 -97
- package/src/plugins/filters.ts +21 -18
- package/src/plugins/replacer.ts +7 -6
- package/src/plugins/signupFlow.ts +45 -43
- package/src/plugins/traceable.ts +28 -26
- package/src/plugins/translations.ts +9 -9
- package/src/plugins/youtube.ts +39 -34
- package/src/routes.ts +108 -108
- package/src/server-entry.ts +75 -77
- package/src/stores/calls.store.ts +14 -14
- package/src/stores/cart.store.ts +116 -107
- package/src/stores/content.store.ts +87 -45
- package/src/stores/editor.store.ts +16 -16
- package/src/stores/files.store.ts +72 -72
- package/src/stores/main.store.ts +155 -109
- package/src/stores/user.store.ts +72 -68
- package/src/translations/de.ts +127 -127
- package/src/views/content.view.vue +81 -143
- package/src/views/download.view.vue +25 -23
- package/src/views/editor.view.vue +150 -125
- package/src/views/login.view.vue +35 -36
- package/src/views/signup-account.view.vue +14 -14
- package/tooling/cypress/config.ts +68 -54
- package/tooling/cypress/manifest-utils.mjs +34 -22
- package/tooling/cypress/run-parallel.mjs +41 -35
- package/tooling/cypress/support/commands.ts +458 -300
- package/tooling/eslint.config.js +1 -223
- package/tooling/preview.plugin.js +132 -0
- package/tooling/ssr-test/index.mjs +205 -203
- package/tooling/vite.d.ts +36 -0
- package/tooling/vite.js +234 -0
- package/src/interfaces/EditorConfiguration.interface.ts +0 -15
- package/tooling/preview.plugin.ts +0 -134
- package/tooling/stylelint.config.mjs +0 -24
- package/tooling/vite.ts +0 -260
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ longer means porting framework changes by hand into every project.
|
|
|
28
28
|
| `views/*` | content, editor, login, signup-account, download |
|
|
29
29
|
| `partials/*` | client-only, main-components, error, qrcode, action, mediadetection |
|
|
30
30
|
| `translations/de` | framework wording only - validation, lists, files, signup, order |
|
|
31
|
-
| `vite`, `eslint`, `
|
|
31
|
+
| `vite`, `eslint`, `cypress` | build and test tooling |
|
|
32
32
|
|
|
33
33
|
## What is NOT in here, on purpose
|
|
34
34
|
|
|
@@ -54,6 +54,11 @@ optimizeDeps: { exclude: ['@lilaquadrat/studio', '@lilaquadrat/design-core'] }
|
|
|
54
54
|
|
|
55
55
|
`createViteConfig` already sets that.
|
|
56
56
|
|
|
57
|
+
The exception is the tooling Node loads itself at config time (`tooling/vite`):
|
|
58
|
+
Node refuses to strip types for files under `node_modules`, so a published copy
|
|
59
|
+
would never load as `.ts`. Those entries ship as plain `.js` with a `.d.ts`
|
|
60
|
+
beside them for the types.
|
|
61
|
+
|
|
57
62
|
## Using it in a design
|
|
58
63
|
|
|
59
64
|
### vite
|
|
@@ -120,13 +125,81 @@ import de from '@/translations/de';
|
|
|
120
125
|
addMessages('de', de);
|
|
121
126
|
```
|
|
122
127
|
|
|
123
|
-
###
|
|
128
|
+
### authentication
|
|
129
|
+
|
|
130
|
+
Authentication is selected by the runtime configuration, not by the Vue plugin.
|
|
131
|
+
The environment's `auth` configuration is carried into the rendered main store.
|
|
132
|
+
For Keycloak:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
auth: {
|
|
136
|
+
type: 'keycloak',
|
|
137
|
+
url: 'https://auth.example.com',
|
|
138
|
+
realm: 'studio',
|
|
139
|
+
clientId: 'design',
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Keycloak uses the authorization-code flow with PKCE. Register the app's URLs as
|
|
144
|
+
valid redirect URIs and its origin as a web origin on the public client. Explicit
|
|
145
|
+
login and signup return to `/login-callback` on the app's origin; `redirectUri`
|
|
146
|
+
can override it in the frontend auth configuration. Startup is passive by default:
|
|
147
|
+
opening or reloading a public page does not start a login redirect. Login and
|
|
148
|
+
signup redirects only happen when explicitly triggered; incoming authentication
|
|
149
|
+
callbacks are still processed during startup.
|
|
150
|
+
|
|
151
|
+
To restore an existing SSO session after a reload, explicitly set
|
|
152
|
+
`silentCheckSsoRedirectUri` to a consumer-hosted Keycloak silent-check page. The
|
|
153
|
+
core does not ship that page. This opts into an iframe-only SSO check, with
|
|
154
|
+
top-level redirect fallback disabled. If silent authentication is unavailable,
|
|
155
|
+
users must explicitly log in again. Without this configuration, sessions are not
|
|
156
|
+
automatically restored after a reload. Tokens stay in memory.
|
|
157
|
+
|
|
158
|
+
Auth0 configuration uses the same discriminator with its existing SDK options:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
auth: {
|
|
162
|
+
type: 'auth0',
|
|
163
|
+
options: {
|
|
164
|
+
domain: 'tenant.eu.auth0.com',
|
|
165
|
+
clientId: 'public-client-id',
|
|
166
|
+
authorizationParams: {
|
|
167
|
+
redirect_uri: 'https://app.example.com/login-callback',
|
|
168
|
+
audience: 'https://api.example.com',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The shared environment schema currently describes Keycloak; the frontend's
|
|
175
|
+
`AuthConfig` additionally supports Auth0. Existing rendered `auth0Options` and
|
|
176
|
+
direct `auth.init(auth0Options)` calls remain supported. `auth` takes precedence
|
|
177
|
+
over legacy `auth0Options` when both are present. There are no built-in tenant
|
|
178
|
+
credentials or localhost callback URLs.
|
|
179
|
+
|
|
180
|
+
`auth` and `useAuth` from `plugins/auth` remain the provider-neutral entry points.
|
|
181
|
+
`functions/AuthProviderFactory` dynamically imports only the selected adapter;
|
|
182
|
+
the adapters own all runtime SDK imports. Do not statically import or re-export
|
|
183
|
+
the adapters from an application entry point or combine them in a vendor chunk.
|
|
184
|
+
Installing the SDKs does not load them in the browser: the consuming build emits
|
|
185
|
+
separate lazy chunks. With no auth configuration (or `initAuth: false`), neither
|
|
186
|
+
provider is initialized or loaded. Preview, editor and server startup skip auth.
|
|
187
|
+
|
|
188
|
+
Focused auth and browser chunk-graph tests (Node 22+, no live identity server required):
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
yarn node --experimental-strip-types --test tests/auth.test.ts
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### eslint, cypress
|
|
124
195
|
|
|
125
196
|
```js
|
|
126
197
|
// eslint.config.js
|
|
127
|
-
export { default } from '@lilaquadrat/
|
|
198
|
+
export { default } from '@lilaquadrat/frontend/eslint';
|
|
128
199
|
```
|
|
129
200
|
|
|
201
|
+
The `@lilaquadrat/design-core/eslint` export also forwards to this shared config.
|
|
202
|
+
|
|
130
203
|
```ts
|
|
131
204
|
// cypress.config.ts
|
|
132
205
|
import { createCypressConfig } from '@lilaquadrat/design-core/cypress';
|
package/html/index.server.html
CHANGED
|
@@ -4,16 +4,9 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
<link rel="icon" type="image/png" sizes="32x32" href="<!--cdn-->/favicon-32x32.png">
|
|
9
|
-
<link rel="icon" type="image/png" sizes="16x16" href="<!--cdn-->/favicon-16x16.png">
|
|
10
|
-
<link rel="manifest" href="<!--cdn-->/site.webmanifest">
|
|
11
|
-
<link rel="mask-icon" href="<!--cdn-->/safari-pinned-tab.svg" color="#5bbad5">
|
|
12
|
-
<meta name="msapplication-TileColor" content="#da532c">
|
|
13
|
-
<meta name="theme-color" content="#ffffff">
|
|
7
|
+
<!--metalinks-->
|
|
14
8
|
|
|
15
9
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
16
|
-
<meta name="description" content="<!--description-->">
|
|
17
10
|
<title><!--sitetitle--></title>
|
|
18
11
|
<link rel="preconnect" href="<!--cdn-->">
|
|
19
12
|
<link rel="stylesheet" href="<!--style-->">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lilaquadrat/design-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "framework layer shared by every lilaquadrat STUDIO design: app bootstrap, router, stores, plugins and build tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,9 +47,8 @@
|
|
|
47
47
|
"./views/*": "./src/views/*",
|
|
48
48
|
"./partials/*": "./src/components/partials/*",
|
|
49
49
|
"./html/*": "./html/*",
|
|
50
|
-
"./vite": "./tooling/vite.
|
|
50
|
+
"./vite": "./tooling/vite.js",
|
|
51
51
|
"./eslint": "./tooling/eslint.config.js",
|
|
52
|
-
"./stylelint": "./tooling/stylelint.config.mjs",
|
|
53
52
|
"./cypress": "./tooling/cypress/config.ts",
|
|
54
53
|
"./ssr-test": "./tooling/ssr-test/index.mjs",
|
|
55
54
|
"./cypress/*": "./tooling/cypress/*"
|
|
@@ -61,27 +60,31 @@
|
|
|
61
60
|
"release": "standard-version"
|
|
62
61
|
},
|
|
63
62
|
"peerDependencies": {
|
|
64
|
-
"@auth0/auth0-spa-js": "^2.
|
|
65
|
-
"@lilaquadrat/frontend": ">=0.2.
|
|
66
|
-
"@lilaquadrat/interfaces": ">=1.
|
|
67
|
-
"@lilaquadrat/sdk": "^0.
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
63
|
+
"@auth0/auth0-spa-js": "^2.30.0",
|
|
64
|
+
"@lilaquadrat/frontend": ">=0.2.19",
|
|
65
|
+
"@lilaquadrat/interfaces": ">=1.57.0",
|
|
66
|
+
"@lilaquadrat/sdk": "^0.2.2",
|
|
67
|
+
"@vue/devtools-api": "^8.2.1",
|
|
68
|
+
"axios": "^1.21.0",
|
|
69
|
+
"cypress": "^16.0.0",
|
|
70
|
+
"dayjs": "^1.11.23",
|
|
71
|
+
"eslint": "^10.14.0",
|
|
72
|
+
"keycloak-js": "^26.2.5",
|
|
73
|
+
"less": "^4.9.1",
|
|
73
74
|
"object-path": "^0.11.8",
|
|
74
|
-
"pinia": "^
|
|
75
|
+
"pinia": "^4.1.0",
|
|
75
76
|
"qrcode": "^1.5.4",
|
|
76
|
-
"rollup-plugin-visualizer": "^
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"vue": "^
|
|
81
|
-
"vue-
|
|
82
|
-
"vue-router": "^4.5.1"
|
|
77
|
+
"rollup-plugin-visualizer": "^7.1.1",
|
|
78
|
+
"uuid": "^14.0.3",
|
|
79
|
+
"vite": "^8.3.5",
|
|
80
|
+
"vue": "^3.5.44",
|
|
81
|
+
"vue-i18n": "^11.4.17",
|
|
82
|
+
"vue-router": "^5.4.0"
|
|
83
83
|
},
|
|
84
84
|
"peerDependenciesMeta": {
|
|
85
|
+
"@vue/devtools-api": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
85
88
|
"cypress": {
|
|
86
89
|
"optional": true
|
|
87
90
|
},
|
|
@@ -94,52 +97,49 @@
|
|
|
94
97
|
"rollup-plugin-visualizer": {
|
|
95
98
|
"optional": true
|
|
96
99
|
},
|
|
97
|
-
"stylelint": {
|
|
98
|
-
"optional": true
|
|
99
|
-
},
|
|
100
100
|
"vite": {
|
|
101
101
|
"optional": true
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
|
-
"@auth0/auth0-spa-js": "2.
|
|
106
|
-
"@eslint/js": "^
|
|
107
|
-
"@lilaquadrat/frontend": "^0.2.
|
|
108
|
-
"@lilaquadrat/interfaces": "
|
|
109
|
-
"@lilaquadrat/sdk": "^0.
|
|
110
|
-
"@types/node": "^
|
|
105
|
+
"@auth0/auth0-spa-js": "2.30.0",
|
|
106
|
+
"@eslint/js": "^10.0.1",
|
|
107
|
+
"@lilaquadrat/frontend": "^0.2.19",
|
|
108
|
+
"@lilaquadrat/interfaces": "^2.0.0",
|
|
109
|
+
"@lilaquadrat/sdk": "^0.2.2",
|
|
110
|
+
"@types/node": "^26.6.6",
|
|
111
111
|
"@types/object-path": "^0.11.4",
|
|
112
112
|
"@types/qrcode": "^1.5.5",
|
|
113
|
-
"@types/uuid": "^10.0.0",
|
|
114
113
|
"@types/youtube": "^0.1.0",
|
|
115
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
116
|
-
"@typescript-eslint/parser": "^8.
|
|
117
|
-
"@vitejs/plugin-vue": "^
|
|
118
|
-
"@vue/
|
|
119
|
-
"@vue/
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
114
|
+
"@typescript-eslint/eslint-plugin": "^8.72.1",
|
|
115
|
+
"@typescript-eslint/parser": "^8.72.1",
|
|
116
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
117
|
+
"@vue/devtools-api": "^8.2.1",
|
|
118
|
+
"@vue/eslint-config-typescript": "^14.9.0",
|
|
119
|
+
"@vue/tsconfig": "^0.9.1",
|
|
120
|
+
"axios": "^1.21.0",
|
|
121
|
+
"commitizen": "^4.3.2",
|
|
122
|
+
"cypress": "^16.2.1",
|
|
123
123
|
"cz-conventional-changelog": "^3.3.0",
|
|
124
|
-
"dayjs": "^1.11.
|
|
125
|
-
"eslint": "^
|
|
126
|
-
"eslint-plugin-vue": "^10.
|
|
127
|
-
"globals": "^
|
|
128
|
-
"
|
|
124
|
+
"dayjs": "^1.11.23",
|
|
125
|
+
"eslint": "^10.14.0",
|
|
126
|
+
"eslint-plugin-vue": "^10.12.0",
|
|
127
|
+
"globals": "^17.14.0",
|
|
128
|
+
"keycloak-js": "^26.2.5",
|
|
129
|
+
"less": "^4.9.1",
|
|
129
130
|
"object-path": "^0.11.8",
|
|
130
|
-
"pinia": "^
|
|
131
|
+
"pinia": "^4.1.0",
|
|
131
132
|
"qrcode": "^1.5.4",
|
|
132
|
-
"rollup-plugin-visualizer": "^
|
|
133
|
+
"rollup-plugin-visualizer": "^7.1.1",
|
|
133
134
|
"standard-version": "^9.5.0",
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"vue": "^
|
|
139
|
-
"vue-
|
|
140
|
-
"vue-
|
|
141
|
-
"vue-
|
|
142
|
-
"vue-tsc": "^2.2.10"
|
|
135
|
+
"typescript": "~6.0.3",
|
|
136
|
+
"uuid": "^14.0.3",
|
|
137
|
+
"vite": "^8.3.5",
|
|
138
|
+
"vue": "^3.5.44",
|
|
139
|
+
"vue-eslint-parser": "^10.4.1",
|
|
140
|
+
"vue-i18n": "^11.4.17",
|
|
141
|
+
"vue-router": "^5.4.0",
|
|
142
|
+
"vue-tsc": "^3.3.14"
|
|
143
143
|
},
|
|
144
144
|
"config": {
|
|
145
145
|
"commitizen": {
|
package/src/client-entry.ts
CHANGED
|
@@ -8,20 +8,20 @@ import { getAppInstance, type AppComponents } from './main';
|
|
|
8
8
|
* boots the browser app. the project passes its own root component, module
|
|
9
9
|
* registries and route sets - everything else is framework.
|
|
10
10
|
*/
|
|
11
|
-
export function createClientEntry
|
|
11
|
+
export function createClientEntry(options: { components: AppComponents, routes: RouteSets, initAuth?: boolean }) {
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const { app, router } = getAppInstance({}, getRoutes(options.routes), !!window.__INITIAL_STATE__, options.components);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// the static preview has no backend: skip auth init and the customer call
|
|
16
|
+
hooks(router, { initAuth: options.initAuth ?? !__PREVIEW__ }, 'client');
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
router.isReady().then(() => {
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
app.mount('#app');
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
});
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
return { app, router };
|
|
25
25
|
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -17,21 +17,21 @@ const data = ref<SDKResponse<BasicData<Content>>>();
|
|
|
17
17
|
|
|
18
18
|
watch(props, () => getContent());
|
|
19
19
|
|
|
20
|
-
function getFilename
|
|
20
|
+
function getFilename() {
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
if(props.hint) return props.hint;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const nameArray: string[] = ['error', props.status.toString()];
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
if(props.type) nameArray.push(props.type);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
return nameArray.join('-');
|
|
29
29
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async function getContent
|
|
32
|
+
async function getContent() {
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
data.value = await store.getContent({filename: getFilename()}, 'public') as SDKResponse<BasicData<Content>>;
|
|
35
35
|
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -39,31 +39,31 @@ onBeforeMount(async () => await getContent());
|
|
|
39
39
|
|
|
40
40
|
const useData = computed(() => {
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
if(data?.value?.data?.modules) return data.value?.data;
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
if(store.staticData) {
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
if(props.hint) {
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
return store.staticData[props.hint];
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
if(props.status > 0) {
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
return store.staticData[props.status];
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
}
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
return undefined;
|
|
61
61
|
|
|
62
62
|
});
|
|
63
63
|
const contentMerged = computed(() => {
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if(useData.value) return prepareContent(useData.value);
|
|
66
|
+
return prepareContent({})
|
|
67
67
|
|
|
68
68
|
});
|
|
69
69
|
|
|
@@ -27,137 +27,142 @@ const isLocked = computed(() => contentType.value == 'members' && userStore.lock
|
|
|
27
27
|
watch(route, () => getContent());
|
|
28
28
|
watch(() => userStore.locked, () => {
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
if(!userStore.locked) {
|
|
31
|
+
|
|
32
|
+
getContent();
|
|
33
|
+
|
|
34
|
+
}
|
|
33
35
|
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
onBeforeMount(async () => await getContent());
|
|
37
39
|
onServerPrefetch(() => getStoreContent());
|
|
38
40
|
|
|
39
|
-
function getStoreContent
|
|
41
|
+
function getStoreContent() {
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
|
|
44
|
+
const storeContent = contentStore.findByFilename(contentId);
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
if(!storeContent) return;
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
data.value = {
|
|
49
|
+
data: storeContent,
|
|
50
|
+
status: 200,
|
|
51
|
+
};
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
loading.value = 200;
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
dataMerged.value = mergeContent(data.value.data);
|
|
54
56
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
async function getContent
|
|
59
|
+
async function getContent() {
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
getStoreContent();
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
if(data.value?.data?.id === contentId) {
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
return;
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
}
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
if(isLocked.value) {
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
loading.value = 0;
|
|
74
|
+
error.value = true;
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
return;
|
|
77
|
+
|
|
78
|
+
}
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
if(contentType.value !== typeCache.value) {
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
loading.value = 0;
|
|
83
|
+
error.value = false;
|
|
84
|
+
data.value = undefined;
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
}
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
const storeData = contentStore.findByFilename(contentId);
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
if(storeData) {
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
data.value = {data: storeData, status: 200};
|
|
93
|
+
loading.value = 200;
|
|
94
|
+
return;
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
}
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
// get content only if there is a difference between the current and the needed content
|
|
99
|
+
if (data.value?.data?.id !== contentId && loading.value === 0) {
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
loading.value = 100;
|
|
99
102
|
|
|
100
|
-
|
|
103
|
+
try {
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
data.value = await store.getContent({filename: contentId}, contentType.value) as SDKResponse<BasicData<Content>>;
|
|
106
|
+
loading.value = data.value.status;
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
} catch (e: any) {
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
data.value = undefined;
|
|
111
|
+
error.value = true;
|
|
112
|
+
loading.value = e?.response?.status;
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
}
|
|
112
115
|
|
|
113
|
-
|
|
116
|
+
if(data.value?.status === 403 || data.value?.status === 401) {
|
|
114
117
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
error.value = true;
|
|
119
|
+
loading.value = data.value?.status;
|
|
120
|
+
data.value = undefined;
|
|
118
121
|
|
|
119
|
-
|
|
122
|
+
}
|
|
120
123
|
|
|
121
|
-
|
|
124
|
+
typeCache.value = route.meta.contentType as string;
|
|
122
125
|
|
|
123
|
-
|
|
126
|
+
}
|
|
124
127
|
|
|
125
|
-
|
|
128
|
+
if(data.value) {
|
|
126
129
|
|
|
127
|
-
|
|
130
|
+
dataMerged.value = mergeContent(data.value?.data);
|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
} else {
|
|
130
133
|
|
|
131
|
-
|
|
134
|
+
dataMerged.value = undefined;
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
}
|
|
134
137
|
|
|
135
138
|
}
|
|
136
139
|
|
|
137
|
-
function mergeContent
|
|
140
|
+
function mergeContent(baseContent: BasicData<Content>) {
|
|
138
141
|
|
|
139
|
-
|
|
142
|
+
if(baseContent) {
|
|
140
143
|
|
|
141
|
-
|
|
144
|
+
const safeData = hardCopy(baseContent);
|
|
142
145
|
|
|
143
|
-
|
|
144
|
-
|
|
146
|
+
if(safeData.modules) {
|
|
147
|
+
|
|
148
|
+
/**
|
|
145
149
|
* content without generic data is the normal case for a static page, and
|
|
146
150
|
* generateDataWithContent reads Object.keys of what it is given - so it
|
|
147
151
|
* throws on undefined instead of returning nothing
|
|
148
152
|
*/
|
|
149
|
-
|
|
153
|
+
if(safeData.genericData) {
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
distributeGenericData(safeData.modules, generateDataWithContent(safeData.genericData as GenericData));
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
}
|
|
155
160
|
|
|
156
|
-
|
|
161
|
+
return prepareContent(safeData);
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
}
|
|
159
164
|
|
|
160
|
-
|
|
165
|
+
return undefined;
|
|
161
166
|
|
|
162
167
|
}
|
|
163
168
|
|
|
@@ -9,21 +9,21 @@ const qrCanvas = ref<HTMLCanvasElement | null>(null);
|
|
|
9
9
|
|
|
10
10
|
onMounted(() => {
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
renderQRCode();
|
|
13
13
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
const renderQRCode = () => {
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
if (qrCanvas.value) {
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
QRCode.toCanvas(qrCanvas.value, props.content, {
|
|
21
|
+
errorCorrectionLevel: 'M',
|
|
22
|
+
margin: 5,
|
|
23
|
+
width: 250,
|
|
24
|
+
})
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
};
|
|
29
29
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type AuthConfig from '../interfaces/AuthConfig.interface';
|
|
2
|
+
import type AuthProvider from '../interfaces/AuthProvider.interface';
|
|
3
|
+
|
|
4
|
+
export default async function AuthProviderFactory(config: AuthConfig): Promise<AuthProvider> {
|
|
5
|
+
|
|
6
|
+
// These targets inline dynamic imports, so eliminate the SDK branches at build time.
|
|
7
|
+
if (import.meta.env.SSR || (typeof __PREVIEW__ !== 'undefined' && __PREVIEW__)) {
|
|
8
|
+
|
|
9
|
+
throw new Error('AUTH_UNAVAILABLE_FOR_TARGET');
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
switch (config.type) {
|
|
14
|
+
case 'auth0': {
|
|
15
|
+
|
|
16
|
+
const { default: Auth0Provider } = await import('./auth0.provider');
|
|
17
|
+
return new Auth0Provider(config.options);
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
case 'keycloak': {
|
|
21
|
+
|
|
22
|
+
const { default: KeycloakProvider } = await import('./keycloak.provider');
|
|
23
|
+
return new KeycloakProvider(config);
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
throw new Error('AUTH_PROVIDER_UNAVAILABLE');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|