druxt-router 0.23.0 → 0.25.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/CHANGELOG.md +51 -0
- package/dist/components/DruxtRouter.stories.mjs +16 -0
- package/dist/components/DruxtRouter.vue +195 -19
- package/dist/druxt-router.esm.js +15 -4
- package/dist/druxt-router.ssr.js +15 -4
- package/nuxt/index.js +3 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# druxt-router
|
|
2
2
|
|
|
3
|
+
## 0.25.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7b749bd: Added improved error handling.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [7b749bd]
|
|
12
|
+
- druxt@0.16.0
|
|
13
|
+
|
|
14
|
+
## 0.24.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [2ae1d6d]
|
|
19
|
+
- druxt@0.15.0
|
|
20
|
+
|
|
21
|
+
## 0.24.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [45bc0b9]
|
|
26
|
+
- druxt@0.14.0
|
|
27
|
+
|
|
28
|
+
## 0.24.0
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- 9161b38: Added Storybook integration for the DruxtRouter component.
|
|
33
|
+
- 9161b38: Added ability to render a specific route using the Path property.
|
|
34
|
+
|
|
35
|
+
```jsx
|
|
36
|
+
<DruxtRouter path="/node/1" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- 9161b38: Added fetch hook to DruxtRouter component.
|
|
40
|
+
- 9161b38: Added option to disable the DruxtRouter page middleware.
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
export default {
|
|
44
|
+
druxt: {
|
|
45
|
+
router: {
|
|
46
|
+
middleware: false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Note: This is experimental and your results may vary.
|
|
53
|
+
|
|
3
54
|
## 0.23.0
|
|
4
55
|
|
|
5
56
|
### Minor Changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import DruxtRouter from './DruxtRouter.vue'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Druxt/Router/DruxtRouter',
|
|
5
|
+
component: DruxtRouter
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Template = (args, { argTypes }) => ({
|
|
9
|
+
components: { DruxtRouter },
|
|
10
|
+
props: Object.keys(argTypes),
|
|
11
|
+
template: `<DruxtRouter v-bind="$props" />`
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export const Default = Template.bind({})
|
|
15
|
+
Default.storyName = 'DruxtRouter'
|
|
16
|
+
Default.args = { path: '/' }
|
|
@@ -1,21 +1,61 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
|
|
3
3
|
import DruxtModule from 'druxt/dist/components/DruxtModule.vue'
|
|
4
|
-
import { mapState } from 'vuex'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* The DruxtRouter component renders a Drupal decoupled route, or path, using
|
|
7
|
+
* the appropriate Druxt component.
|
|
9
8
|
*
|
|
10
|
-
*
|
|
9
|
+
* `<DruxtRouter path="/" />`
|
|
10
|
+
*
|
|
11
|
+
* If no Path is specified, the Vue router path will be used by default.
|
|
12
|
+
*
|
|
13
|
+
* For instance, using the `/node/1` route would result in a DruxtRouter
|
|
14
|
+
* component for the content in Drupal with the Node ID of 1.
|
|
15
|
+
*
|
|
16
|
+
* @example <caption>Render using the Vue router path</caption> @lang vue
|
|
11
17
|
* <DruxtRouter />
|
|
18
|
+
*
|
|
19
|
+
* @example <caption>Render a specified path</caption> @lang vue
|
|
20
|
+
* <DruxtRouter path="/node/1" />
|
|
21
|
+
*
|
|
22
|
+
* @example <caption>Render the result of the model, bypasses Drupal backend</caption> @lang vue
|
|
23
|
+
* <DruxtRouter v-model="route" />
|
|
24
|
+
*
|
|
25
|
+
* @example <caption>Render via a template</caption> @lang vue
|
|
26
|
+
* <DruxtRouter>
|
|
27
|
+
* <template #default="{ route }">
|
|
28
|
+
* <DruxtRouter v-bind="route.props" />
|
|
29
|
+
* </template>
|
|
30
|
+
* </DruxtRouter>
|
|
12
31
|
*/
|
|
13
32
|
export default {
|
|
14
33
|
name: 'DruxtRouter',
|
|
15
34
|
|
|
16
35
|
extends: DruxtModule,
|
|
17
36
|
|
|
18
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Nuxt middleware; gets and sets the current route, and processes redirects.
|
|
39
|
+
*
|
|
40
|
+
* This can be disabled by setting the `druxt.router.middleware` option to
|
|
41
|
+
* `false` in `nuxt.config.js`
|
|
42
|
+
*
|
|
43
|
+
* @example @lang js
|
|
44
|
+
* export default {
|
|
45
|
+
* druxt: {
|
|
46
|
+
* router: {
|
|
47
|
+
* middleware: false
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
async middleware ({ $druxt, redirect, route, store }) {
|
|
53
|
+
// Ensure Router middleware is enabled.
|
|
54
|
+
if (typeof ($druxt.settings.router || {}).middleware !== 'undefined' && !$druxt.settings.router.middleware) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Get and set the current route and redirect information.
|
|
19
59
|
const result = await store.dispatch('druxtRouter/get', route.fullPath)
|
|
20
60
|
|
|
21
61
|
// Process redirect.
|
|
@@ -24,6 +64,44 @@ export default {
|
|
|
24
64
|
}
|
|
25
65
|
},
|
|
26
66
|
|
|
67
|
+
/** */
|
|
68
|
+
props: {
|
|
69
|
+
/**
|
|
70
|
+
* The Decoupled router path.
|
|
71
|
+
*
|
|
72
|
+
* If not set, the Vue router value will be used instead.
|
|
73
|
+
*
|
|
74
|
+
* @type {string}
|
|
75
|
+
*
|
|
76
|
+
* @example @lang vue
|
|
77
|
+
* <DruxtRouter path="/node/1" />
|
|
78
|
+
*/
|
|
79
|
+
path: {
|
|
80
|
+
type: String,
|
|
81
|
+
default: undefined,
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The Router object, used to determine the resolved route component.
|
|
86
|
+
*
|
|
87
|
+
* Setting this value will bypass the JSON:API.
|
|
88
|
+
*
|
|
89
|
+
* @type {object}
|
|
90
|
+
* @model
|
|
91
|
+
*/
|
|
92
|
+
value: {
|
|
93
|
+
type: Object,
|
|
94
|
+
default: () => undefined
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @property {object} model - The model object.
|
|
100
|
+
*/
|
|
101
|
+
data: ({ value }) => ({
|
|
102
|
+
model: value,
|
|
103
|
+
}),
|
|
104
|
+
|
|
27
105
|
/**
|
|
28
106
|
* Nuxt head method.
|
|
29
107
|
*
|
|
@@ -39,7 +117,7 @@ export default {
|
|
|
39
117
|
{
|
|
40
118
|
hid: 'canonical',
|
|
41
119
|
rel: 'canonical',
|
|
42
|
-
href: this.canonical || this.route.canonical
|
|
120
|
+
href: this.canonical || (this.route || {}).canonical
|
|
43
121
|
}
|
|
44
122
|
]
|
|
45
123
|
}
|
|
@@ -51,44 +129,142 @@ export default {
|
|
|
51
129
|
return head
|
|
52
130
|
},
|
|
53
131
|
|
|
54
|
-
/**
|
|
55
|
-
* Vue.js Computed properties.
|
|
56
|
-
*
|
|
57
|
-
* @vue-computed {object} redirect The current Redirect, if applicable.
|
|
58
|
-
* @vue-computed {object} route The current Route.
|
|
59
|
-
*/
|
|
132
|
+
/** */
|
|
60
133
|
computed: {
|
|
134
|
+
/**
|
|
135
|
+
* The route module.
|
|
136
|
+
*
|
|
137
|
+
* @type {string}
|
|
138
|
+
*/
|
|
61
139
|
module: ({ route }) =>
|
|
62
140
|
(route || {}).component && route.component.startsWith('druxt-') ? route.component.substring(6) : false,
|
|
63
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The route object.
|
|
144
|
+
*
|
|
145
|
+
* @type {object}
|
|
146
|
+
*/
|
|
147
|
+
route: ({ model }) => model,
|
|
148
|
+
|
|
64
149
|
/**
|
|
65
150
|
* Route title.
|
|
66
151
|
* @type {boolean|string}
|
|
67
152
|
* @default false
|
|
68
153
|
*/
|
|
69
|
-
title: ({ route }) => route.label || false,
|
|
154
|
+
title: ({ route }) => (route || {}).label || false,
|
|
70
155
|
|
|
71
156
|
/**
|
|
72
157
|
* Route component property data.
|
|
73
158
|
* @type {object|string}
|
|
74
159
|
* @default false
|
|
75
160
|
*/
|
|
76
|
-
props: ({ route }) => route.props || false,
|
|
161
|
+
props: ({ route }) => (route || {}).props || false,
|
|
162
|
+
},
|
|
77
163
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
164
|
+
/** */
|
|
165
|
+
watch: {
|
|
166
|
+
/**
|
|
167
|
+
* Re-fetch on update to Path prop.
|
|
168
|
+
*/
|
|
169
|
+
async path() {
|
|
170
|
+
await this.$fetch()
|
|
171
|
+
}
|
|
82
172
|
},
|
|
83
173
|
|
|
174
|
+
/** DruxtModule settings */
|
|
84
175
|
druxt: {
|
|
176
|
+
/**
|
|
177
|
+
* Provides the available component naming options for the Druxt Wrapper.
|
|
178
|
+
*
|
|
179
|
+
* @param {object} context - The module component ViewModel.
|
|
180
|
+
* @returns {ComponentOptions}
|
|
181
|
+
*/
|
|
85
182
|
componentOptions: ({ module, route }) => [
|
|
86
183
|
// @TODO - Add Path options.
|
|
87
184
|
[module || 'error', route.isHomePath ? 'front' : 'not-front'],
|
|
88
185
|
['default']
|
|
89
186
|
],
|
|
90
187
|
|
|
91
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Fetch the decoupled route.
|
|
190
|
+
*/
|
|
191
|
+
async fetchConfig() {
|
|
192
|
+
// Use the v-model value if provided.
|
|
193
|
+
if (this.value) {
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Get the route from the Drupal decoupled router module via the
|
|
198
|
+
// druxtRouter store.
|
|
199
|
+
// Use the Path prop or the Vue Router as the route to lookup.
|
|
200
|
+
const path = this.path || this.$route.fullPath
|
|
201
|
+
const route = await this.$store.dispatch('druxtRouter/getRoute', path)
|
|
202
|
+
this.model = route
|
|
203
|
+
|
|
204
|
+
// If this the path is the active Vue route, set the active route in the
|
|
205
|
+
// druxtRouter store for other modules to use.
|
|
206
|
+
// This is also done when via the middleware if in use.
|
|
207
|
+
const setActiveRoute = path === this.$route.fullPath
|
|
208
|
+
if (setActiveRoute) {
|
|
209
|
+
this.$store.commit('druxtRouter/setRoute', path)
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Provides propsData for the DruxtWrapper.
|
|
215
|
+
*
|
|
216
|
+
* @param {object} context - The module component ViewModel.
|
|
217
|
+
* @returns {PropsData}
|
|
218
|
+
*/
|
|
219
|
+
propsData: ({ $route, path, model }) => ({
|
|
220
|
+
path: path || $route.fullPath,
|
|
221
|
+
route: model
|
|
222
|
+
})
|
|
92
223
|
}
|
|
93
224
|
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Provides the available naming options for the Wrapper component.
|
|
228
|
+
*
|
|
229
|
+
* @typedef {array[]} ComponentOptions
|
|
230
|
+
*
|
|
231
|
+
* @example @lang js
|
|
232
|
+
* [
|
|
233
|
+
* 'DruxtRouter[Module][IsFront?]',
|
|
234
|
+
* 'DruxtRouterDefault',
|
|
235
|
+
* ]
|
|
236
|
+
*
|
|
237
|
+
* @example <caption>Entity route</caption> @lang js
|
|
238
|
+
* [
|
|
239
|
+
* 'DruxtRouterEntityFront',
|
|
240
|
+
* 'DruxtRouterEntity',
|
|
241
|
+
* 'DruxtRouterDefault',
|
|
242
|
+
* '',
|
|
243
|
+
* ]
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Provides property data for use in the Wrapper component.
|
|
248
|
+
*
|
|
249
|
+
* @typedef {object} PropsData
|
|
250
|
+
* @param {string} path - The route path.
|
|
251
|
+
* @param {object} route - The Decoupled Router object.
|
|
252
|
+
*
|
|
253
|
+
* @example @lang js
|
|
254
|
+
* {
|
|
255
|
+
* path: '/',
|
|
256
|
+
* route: {
|
|
257
|
+
* canonical: 'https://demo-api.druxtjs.org/en/node',
|
|
258
|
+
* component: 'druxt-view',
|
|
259
|
+
* error: false,
|
|
260
|
+
* isHomePath: true,
|
|
261
|
+
* jsonapi: {},
|
|
262
|
+
* label: 'Home',
|
|
263
|
+
* props: {},
|
|
264
|
+
* redirect: false,
|
|
265
|
+
* resolvedPath: '/en/node',
|
|
266
|
+
* type: 'views',
|
|
267
|
+
* }
|
|
268
|
+
* }
|
|
269
|
+
*/
|
|
94
270
|
</script>
|
package/dist/druxt-router.esm.js
CHANGED
|
@@ -104,7 +104,7 @@ class DruxtRouter {
|
|
|
104
104
|
}
|
|
105
105
|
async getRoute(path) {
|
|
106
106
|
const url = `/router/translate-path?path=${path}`;
|
|
107
|
-
const response = await this.druxt.
|
|
107
|
+
const response = await this.druxt.get(url, {
|
|
108
108
|
validateStatus: (status) => status < 500
|
|
109
109
|
});
|
|
110
110
|
const data = {
|
|
@@ -147,9 +147,16 @@ class DruxtRouter {
|
|
|
147
147
|
break;
|
|
148
148
|
}
|
|
149
149
|
if (!(response.status >= 200 && response.status < 300)) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
if (response.status === 404) {
|
|
151
|
+
if (typeof response.data !== "object") {
|
|
152
|
+
response.data = { errors: [{
|
|
153
|
+
detail: "Please ensure the Decoupled Router module is installed and configured correctly."
|
|
154
|
+
}] };
|
|
155
|
+
} else if (response.data.message || response.data.details) {
|
|
156
|
+
response.data.errors = [{ detail: [response.data.message, response.data.details].filter((s) => s).join("\n") }];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.druxt.error({ response }, { url });
|
|
153
160
|
}
|
|
154
161
|
return route;
|
|
155
162
|
}
|
|
@@ -282,6 +289,10 @@ const DruxtRouterEntityMixin = {
|
|
|
282
289
|
|
|
283
290
|
const DruxtRouterMixin = {
|
|
284
291
|
props: {
|
|
292
|
+
path: {
|
|
293
|
+
type: String,
|
|
294
|
+
default: void 0
|
|
295
|
+
},
|
|
285
296
|
route: {
|
|
286
297
|
type: Object,
|
|
287
298
|
required: true
|
package/dist/druxt-router.ssr.js
CHANGED
|
@@ -112,7 +112,7 @@ class DruxtRouter {
|
|
|
112
112
|
}
|
|
113
113
|
async getRoute(path) {
|
|
114
114
|
const url = `/router/translate-path?path=${path}`;
|
|
115
|
-
const response = await this.druxt.
|
|
115
|
+
const response = await this.druxt.get(url, {
|
|
116
116
|
validateStatus: (status) => status < 500
|
|
117
117
|
});
|
|
118
118
|
const data = {
|
|
@@ -155,9 +155,16 @@ class DruxtRouter {
|
|
|
155
155
|
break;
|
|
156
156
|
}
|
|
157
157
|
if (!(response.status >= 200 && response.status < 300)) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
if (response.status === 404) {
|
|
159
|
+
if (typeof response.data !== "object") {
|
|
160
|
+
response.data = { errors: [{
|
|
161
|
+
detail: "Please ensure the Decoupled Router module is installed and configured correctly."
|
|
162
|
+
}] };
|
|
163
|
+
} else if (response.data.message || response.data.details) {
|
|
164
|
+
response.data.errors = [{ detail: [response.data.message, response.data.details].filter((s) => s).join("\n") }];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
this.druxt.error({ response }, { url });
|
|
161
168
|
}
|
|
162
169
|
return route;
|
|
163
170
|
}
|
|
@@ -290,6 +297,10 @@ const DruxtRouterEntityMixin = {
|
|
|
290
297
|
|
|
291
298
|
const DruxtRouterMixin = {
|
|
292
299
|
props: {
|
|
300
|
+
path: {
|
|
301
|
+
type: String,
|
|
302
|
+
default: void 0
|
|
303
|
+
},
|
|
293
304
|
route: {
|
|
294
305
|
type: Object,
|
|
295
306
|
required: true
|
package/nuxt/index.js
CHANGED
|
@@ -48,6 +48,9 @@ const DruxtRouterNuxtModule = async function(moduleOptions = {}) {
|
|
|
48
48
|
fileName: "store/druxt-router.js",
|
|
49
49
|
options
|
|
50
50
|
});
|
|
51
|
+
this.nuxt.hook("storybook:config", async ({ stories }) => {
|
|
52
|
+
stories.push("druxt-router/dist/components/*.stories.mjs");
|
|
53
|
+
});
|
|
51
54
|
};
|
|
52
55
|
DruxtRouterNuxtModule.meta = require("../package.json");
|
|
53
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "druxt-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Drupal router for Nuxt, powered by the Drupal Decoupled Router module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cms",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"templates"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"druxt": "^0.
|
|
45
|
+
"druxt": "^0.16.0",
|
|
46
46
|
"url-parse": "^1.4.7"
|
|
47
47
|
},
|
|
48
48
|
"optionalDependencies": {
|