strapi-plugin-navigation 1.0.4 → 1.1.3
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 +15 -29
- package/__mocks__/helpers/strapi.js +17 -5
- package/admin/src/containers/View/components/NavigationItemForm/utils/form.js +1 -1
- package/admin/src/containers/View/utils/parsers.js +11 -12
- package/config/functions/bootstrap.js +107 -11
- package/config/schema.graphql.js +8 -4
- package/controllers/navigation.js +8 -10
- package/models/navigation.settings.json +1 -1
- package/models/navigationItem.js +21 -3
- package/models/navigationItem.settings.json +15 -4
- package/models/navigations_items_related.js +19 -0
- package/models/navigations_items_related.settings.json +45 -0
- package/package.json +1 -1
- package/services/__tests__/navigation.test.js +71 -72
- package/services/navigation.js +181 -87
- package/services/utils/functions.js +10 -10
package/README.md
CHANGED
|
@@ -23,6 +23,11 @@ A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provid
|
|
|
23
23
|
|
|
24
24
|
<img src="public/assets/preview.png" alt="UI preview" />
|
|
25
25
|
|
|
26
|
+
### Versions
|
|
27
|
+
|
|
28
|
+
- **Stable** - [v1.1.2](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
|
|
29
|
+
- **Beta** - v4 support - [v2.0.0-beta.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/feat/strapi-v4-support)
|
|
30
|
+
|
|
26
31
|
### ⏳ Installation
|
|
27
32
|
|
|
28
33
|
(Use **yarn** to install this plugin within your Strapi project (recommended). [Install yarn with these docs](https://yarnpkg.com/lang/en/docs/install/).)
|
|
@@ -73,40 +78,22 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
73
78
|
|
|
74
79
|
## Content Type model relation to Navigation Item
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
inside the `attributes` section like in example below:
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
"attributes": {
|
|
92
|
-
...,
|
|
93
|
-
"navigation": {
|
|
94
|
-
"model": "navigationitem",
|
|
95
|
-
"plugin": "navigation",
|
|
96
|
-
"via": "related",
|
|
97
|
-
"configurable": false,
|
|
98
|
-
"hidden": true
|
|
99
|
-
},
|
|
100
|
-
...
|
|
101
|
-
},
|
|
81
|
+
We can define in `config/plugins.js`
|
|
82
|
+
```js
|
|
83
|
+
navigation: {
|
|
84
|
+
...
|
|
85
|
+
relatedContentTypes: [
|
|
86
|
+
'application::pages.pages'
|
|
87
|
+
],
|
|
88
|
+
...
|
|
89
|
+
},
|
|
102
90
|
```
|
|
103
91
|
|
|
104
92
|
## Configuration
|
|
105
|
-
To setup the plugin properly we recommend to put following snippet as part of `config/
|
|
93
|
+
To setup the plugin properly we recommend to put following snippet as part of `config/plugins.js` or `config/<env>/plugins.js` file. If you've got already configurations for other plugins stores by this way, use just the `navigation` part within exising `plugins` item.
|
|
106
94
|
|
|
107
95
|
```js
|
|
108
96
|
...
|
|
109
|
-
plugins: {
|
|
110
97
|
navigation: {
|
|
111
98
|
additionalFields: ['audience'],
|
|
112
99
|
allowedLevels: 2,
|
|
@@ -116,7 +103,6 @@ To setup the plugin properly we recommend to put following snippet as part of `c
|
|
|
116
103
|
},
|
|
117
104
|
gql: { ... }
|
|
118
105
|
},
|
|
119
|
-
},
|
|
120
106
|
...
|
|
121
107
|
```
|
|
122
108
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const {get} = require('lodash');
|
|
1
2
|
function setupStrapi() {
|
|
2
3
|
Object.defineProperty(global, 'strapi', {
|
|
3
4
|
value: {
|
|
@@ -14,6 +15,9 @@ function setupStrapi() {
|
|
|
14
15
|
},
|
|
15
16
|
},
|
|
16
17
|
},
|
|
18
|
+
get(path, defaultValue) {
|
|
19
|
+
return get(strapi, path, defaultValue);
|
|
20
|
+
},
|
|
17
21
|
},
|
|
18
22
|
api: {
|
|
19
23
|
'home-page': {
|
|
@@ -40,13 +44,13 @@ function setupStrapi() {
|
|
|
40
44
|
modelName: 'pages',
|
|
41
45
|
associations: [{ model: 'navigationitem' }],
|
|
42
46
|
},
|
|
43
|
-
'blog-post': {
|
|
47
|
+
'application::blog-post.blog-post': {
|
|
44
48
|
...require('./blog-post.settings.json'),
|
|
45
49
|
apiName: 'blog-posts',
|
|
46
50
|
modelName: 'blog-posts',
|
|
47
51
|
associations: [{ model: 'navigationitem' }],
|
|
48
52
|
},
|
|
49
|
-
'my-homepage': {
|
|
53
|
+
'application::my-homepages.my-homepage': {
|
|
50
54
|
...require('./my-homepage.settings.json'),
|
|
51
55
|
apiName: 'my-homepage',
|
|
52
56
|
modelName: 'my-homepage',
|
|
@@ -58,12 +62,12 @@ function setupStrapi() {
|
|
|
58
62
|
modelName: 'home-page',
|
|
59
63
|
associations: [{ model: 'navigationitem' }],
|
|
60
64
|
},
|
|
61
|
-
'plugin
|
|
65
|
+
'plugins::another-plugin.pages': {
|
|
62
66
|
...require('./another-plugin/pages.settings.json'),
|
|
63
67
|
modelName: 'plugin-pages',
|
|
64
68
|
associations: [{ model: 'navigationitem' }],
|
|
65
69
|
},
|
|
66
|
-
'plugin
|
|
70
|
+
'plugins::another-plugin.blog-post': {
|
|
67
71
|
...require('./another-plugin/blog-post.settings.json'),
|
|
68
72
|
modelName: 'plugin-blog-posts',
|
|
69
73
|
associations: [{ model: 'navigationitem' }],
|
|
@@ -73,7 +77,15 @@ function setupStrapi() {
|
|
|
73
77
|
navigation: {
|
|
74
78
|
services: {
|
|
75
79
|
navigation: jest.fn().mockImplementation(),
|
|
76
|
-
}
|
|
80
|
+
},
|
|
81
|
+
relatedContentTypes: [
|
|
82
|
+
'application::pages.pages',
|
|
83
|
+
'application::blog-post.blog-post',
|
|
84
|
+
'application::my-homepages.my-homepage',
|
|
85
|
+
'application::page-homes.home-page',
|
|
86
|
+
'plugins::another-plugin.pages',
|
|
87
|
+
'plugins::another-plugin.blog-post'
|
|
88
|
+
]
|
|
77
89
|
},
|
|
78
90
|
anotherPlugin: {
|
|
79
91
|
models: {
|
|
@@ -29,7 +29,7 @@ export const form = {
|
|
|
29
29
|
is: val => val === navigationItemType.EXTERNAL,
|
|
30
30
|
then: yup.string()
|
|
31
31
|
.required(translatedErrors.required)
|
|
32
|
-
.matches(/(#.*)|(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/, {
|
|
32
|
+
.matches(/(#.*)|(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}|mailto:.+@(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)+[^.\s]{2,})/, {
|
|
33
33
|
excludeEmptyString: true,
|
|
34
34
|
message: `${pluginId}.popup.item.form.externalPath.validation.type`,
|
|
35
35
|
}),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isUuid, uuid } from 'uuidv4';
|
|
2
|
-
import { find, get, isArray, isEmpty, isNil, isNumber, isObject, isString,
|
|
2
|
+
import { find, get, isArray, isEmpty, isNil, isNumber, isObject, isString, last, omit, orderBy } from 'lodash';
|
|
3
3
|
import { navigationItemType } from './enums';
|
|
4
4
|
|
|
5
5
|
export const transformItemToRESTPayload = (
|
|
@@ -46,8 +46,7 @@ export const transformItemToRESTPayload = (
|
|
|
46
46
|
order,
|
|
47
47
|
uiRouterKey,
|
|
48
48
|
menuAttached,
|
|
49
|
-
audience: audience.map((audienceItem) =>
|
|
50
|
-
isObject(audienceItem) ? audienceItem.value : audienceItem,
|
|
49
|
+
audience: audience.map((audienceItem) => isObject(audienceItem) ? audienceItem.value || audienceItem.id : audienceItem,
|
|
51
50
|
),
|
|
52
51
|
path: isExternal ? undefined : path,
|
|
53
52
|
externalPath: isExternal ? externalPath : undefined,
|
|
@@ -65,7 +64,7 @@ export const transformItemToRESTPayload = (
|
|
|
65
64
|
};
|
|
66
65
|
|
|
67
66
|
export const transformToRESTPayload = (payload, config = {}) => {
|
|
68
|
-
|
|
67
|
+
const { id, name, visible, items } = payload;
|
|
69
68
|
return {
|
|
70
69
|
id,
|
|
71
70
|
name,
|
|
@@ -120,7 +119,7 @@ const linkRelations = (item, config) => {
|
|
|
120
119
|
const shouldBuildRelated = !relatedRef || (relatedRef && (relatedRef.id !== relatedId));
|
|
121
120
|
if (shouldBuildRelated && !shouldFindRelated) {
|
|
122
121
|
const relatedContentType = find(contentTypes,
|
|
123
|
-
ct =>
|
|
122
|
+
ct => ct.uid === relatedItem.__contentType, {});
|
|
124
123
|
const { uid, labelSingular, isSingle } = relatedContentType;
|
|
125
124
|
relation = {
|
|
126
125
|
related: relatedItem.id,
|
|
@@ -262,7 +261,7 @@ export const usedContentTypes = (items = []) => items.flatMap(
|
|
|
262
261
|
if (item.relatedRef) {
|
|
263
262
|
return [item.relatedRef, ...used];
|
|
264
263
|
}
|
|
265
|
-
return used;
|
|
264
|
+
return used;
|
|
266
265
|
},
|
|
267
266
|
);
|
|
268
267
|
|
|
@@ -284,11 +283,11 @@ export const isRelationPublished = ({ relatedRef, relatedType = {}, type, isColl
|
|
|
284
283
|
return true;
|
|
285
284
|
};
|
|
286
285
|
|
|
287
|
-
export const validateNavigationStructure = (items = []) =>
|
|
288
|
-
items.map(item =>
|
|
289
|
-
(item.removed || isRelationCorrect({
|
|
290
|
-
related: item.related,
|
|
286
|
+
export const validateNavigationStructure = (items = []) =>
|
|
287
|
+
items.map(item =>
|
|
288
|
+
(item.removed || isRelationCorrect({
|
|
289
|
+
related: item.related,
|
|
291
290
|
type: item.type,
|
|
292
|
-
})) &&
|
|
291
|
+
})) &&
|
|
293
292
|
validateNavigationStructure(item.items)
|
|
294
|
-
).filter(item => !item).length === 0;
|
|
293
|
+
).filter(item => !item).length === 0;
|
|
@@ -1,26 +1,112 @@
|
|
|
1
|
-
const { isEmpty } = require(
|
|
1
|
+
const { isEmpty, get, last } = require('lodash');
|
|
2
|
+
|
|
3
|
+
const saveJSONParse = (value) => {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(value).map((_) => ({ ..._, id: _._id }));
|
|
6
|
+
} catch (e) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const getDefaultConnectionName = (strapi) => strapi.config.get('database.defaultConnection');
|
|
12
|
+
|
|
13
|
+
const isMongo = (strapi) => {
|
|
14
|
+
const connectionName = getDefaultConnectionName(strapi);
|
|
15
|
+
return strapi.config.get(`database.connections.${connectionName}.connector`).includes('mongo');
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const getNavigationMorphData = (strapi) => {
|
|
19
|
+
const connectionName = getDefaultConnectionName(strapi);
|
|
20
|
+
const { [connectionName]: knex } = strapi.connections;
|
|
21
|
+
return knex.schema.hasTable('navigations_items_morph').then((exist)=> exist ? knex('navigations_items_morph').select('*') : []);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getNavigationItemsModel = (strapi) => strapi.query('navigationitem', 'navigation');
|
|
25
|
+
|
|
26
|
+
const getRelatedModel = (strapi) => strapi.query('navigations_items_related', 'navigation');
|
|
27
|
+
|
|
28
|
+
const createRelatedData = (relatedModel, navigationItemsModel, items) => ({
|
|
29
|
+
field,
|
|
30
|
+
order,
|
|
31
|
+
related_id,
|
|
32
|
+
related_type,
|
|
33
|
+
navigations_items_id,
|
|
34
|
+
}) => {
|
|
35
|
+
const item = items.find(item => item.id === navigations_items_id);
|
|
36
|
+
const modelUID = get(strapi.query(related_type), 'model.uid');
|
|
37
|
+
if (item && modelUID) {
|
|
38
|
+
const relatedData = {
|
|
39
|
+
field,
|
|
40
|
+
order,
|
|
41
|
+
related_id,
|
|
42
|
+
related_type: modelUID,
|
|
43
|
+
master: get(item.master, 'id', item.master),
|
|
44
|
+
};
|
|
45
|
+
return relatedModel.create(relatedData)
|
|
46
|
+
.then(
|
|
47
|
+
({ id }) => navigationItemsModel.update({ id: navigations_items_id }, { related: id }),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return Promise.resolve();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const migrateNavigationItemsSQL = async (strapi) => {
|
|
54
|
+
const morphData = await getNavigationMorphData(strapi);
|
|
55
|
+
if (morphData.length) {
|
|
56
|
+
const relatedModel = getRelatedModel(strapi);
|
|
57
|
+
const navigationItemsModel = getNavigationItemsModel(strapi);
|
|
58
|
+
const items = await navigationItemsModel.find({});
|
|
59
|
+
await Promise.all(morphData.map(createRelatedData(relatedModel, navigationItemsModel, items)));
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const migrateNavigationItemsMongo = async (strapi) => {
|
|
64
|
+
const navigationItemsModel = getNavigationItemsModel(strapi);
|
|
65
|
+
const connectionName = getDefaultConnectionName(strapi);
|
|
66
|
+
const models = strapi.connections[connectionName].models;
|
|
67
|
+
const items = (await models.NavigationNavigationitem.find({}))
|
|
68
|
+
// workaround to change type from object to int
|
|
69
|
+
.map(_ => ({ ..._.toObject(), related: last(saveJSONParse(get(_.errors, 'related.properties.value', null))) }))
|
|
70
|
+
.filter(_ => _.related);
|
|
71
|
+
|
|
72
|
+
if (items.length) {
|
|
73
|
+
await Promise.all(items.map(item => {
|
|
74
|
+
const data = {
|
|
75
|
+
related_id: item.related.ref,
|
|
76
|
+
related_type: models[item.related.kind].uid,
|
|
77
|
+
field: item.related.field,
|
|
78
|
+
order: 1,
|
|
79
|
+
master: item.master,
|
|
80
|
+
};
|
|
81
|
+
return getRelatedModel(strapi)
|
|
82
|
+
.create(data)
|
|
83
|
+
.then(result => navigationItemsModel.update({ id: item.id }, { related: [result.id] }));
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
};
|
|
2
88
|
|
|
3
89
|
module.exports = async () => {
|
|
4
90
|
// Check if the plugin users-permissions is installed because the navigation needs it
|
|
5
|
-
if (Object.keys(strapi.plugins).indexOf(
|
|
91
|
+
if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) {
|
|
6
92
|
throw new Error(
|
|
7
|
-
|
|
93
|
+
'In order to make the navigation plugin work the users-permissions plugin is required',
|
|
8
94
|
);
|
|
9
95
|
}
|
|
10
96
|
|
|
11
97
|
// Add permissions
|
|
12
98
|
const actions = [
|
|
13
99
|
{
|
|
14
|
-
section:
|
|
15
|
-
displayName:
|
|
16
|
-
uid:
|
|
17
|
-
pluginName:
|
|
100
|
+
section: 'plugins',
|
|
101
|
+
displayName: 'Access the Navigation',
|
|
102
|
+
uid: 'read',
|
|
103
|
+
pluginName: 'navigation',
|
|
18
104
|
},
|
|
19
105
|
{
|
|
20
|
-
section:
|
|
21
|
-
displayName:
|
|
22
|
-
uid:
|
|
23
|
-
pluginName:
|
|
106
|
+
section: 'plugins',
|
|
107
|
+
displayName: 'Ability to change the Navigation',
|
|
108
|
+
uid: 'update',
|
|
109
|
+
pluginName: 'navigation',
|
|
24
110
|
},
|
|
25
111
|
];
|
|
26
112
|
|
|
@@ -36,6 +122,16 @@ module.exports = async () => {
|
|
|
36
122
|
visible: true,
|
|
37
123
|
});
|
|
38
124
|
}
|
|
125
|
+
const relatedModel = getRelatedModel(global.strapi);
|
|
126
|
+
const isMigrated = !!(await relatedModel.count({}));
|
|
127
|
+
if (!isMigrated) {
|
|
128
|
+
const isMongoDB = isMongo(global.strapi);
|
|
129
|
+
if (isMongoDB) {
|
|
130
|
+
await migrateNavigationItemsMongo(global.strapi);
|
|
131
|
+
} else {
|
|
132
|
+
await migrateNavigationItemsSQL(global.strapi);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
39
135
|
|
|
40
136
|
const { actionProvider } = strapi.admin.services.permission;
|
|
41
137
|
await actionProvider.registerMany(actions);
|
package/config/schema.graphql.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const {get} = require('lodash');
|
|
2
1
|
const NAVIGATION_DATE = `
|
|
3
2
|
# SQL
|
|
4
3
|
created_at: String
|
|
@@ -25,12 +24,12 @@ const NAVIGATION = `
|
|
|
25
24
|
`;
|
|
26
25
|
|
|
27
26
|
const getContentTypesNamesFields = () => {
|
|
28
|
-
const contentTypesNameFields = strapi.config.get('
|
|
27
|
+
const contentTypesNameFields = strapi.config.get('plugins.navigation.contentTypesNameFields');
|
|
29
28
|
return Object.keys(contentTypesNameFields || {}).map(key => `${key}: [String]!`).join('\n');
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
const getNavigationRelated = () => {
|
|
33
|
-
const related = strapi.config.get('
|
|
32
|
+
const related = strapi.config.get('plugins.navigation.gql.navigationItemRelated');
|
|
34
33
|
if (related) {
|
|
35
34
|
return related;
|
|
36
35
|
}
|
|
@@ -67,7 +66,7 @@ module.exports = {
|
|
|
67
66
|
parent: Int
|
|
68
67
|
master: Int
|
|
69
68
|
items: [NavigationItem]
|
|
70
|
-
related: NavigationRelated
|
|
69
|
+
related: [NavigationRelated]
|
|
71
70
|
audience: [String]
|
|
72
71
|
${NAVIGATION_DATE}
|
|
73
72
|
${NAVIGATION_USER}
|
|
@@ -149,6 +148,11 @@ module.exports = {
|
|
|
149
148
|
navigationUpdate(id: String!, navigation: CreateNavigation!): Navigation!
|
|
150
149
|
`,
|
|
151
150
|
resolver: {
|
|
151
|
+
NavigationRelated: {
|
|
152
|
+
__resolveType: (data) => {
|
|
153
|
+
return strapi.contentTypes[data.__contentType]?.globalId
|
|
154
|
+
}
|
|
155
|
+
},
|
|
152
156
|
Query: {
|
|
153
157
|
renderNavigation: {
|
|
154
158
|
resolverOf: 'plugins::navigation.navigation.render',
|
|
@@ -23,35 +23,33 @@ const errorHandler = (ctx) => (error) => {
|
|
|
23
23
|
}
|
|
24
24
|
throw error;
|
|
25
25
|
};
|
|
26
|
+
const getService = () => strapi.plugins.navigation.services.navigation;
|
|
26
27
|
|
|
27
28
|
module.exports = {
|
|
28
|
-
getService() {
|
|
29
|
-
return strapi.plugins.navigation.services.navigation;
|
|
30
|
-
},
|
|
31
29
|
/**
|
|
32
30
|
* Default action.
|
|
33
31
|
*
|
|
34
32
|
* @return {Object}
|
|
35
33
|
*/
|
|
36
34
|
async config() {
|
|
37
|
-
return
|
|
35
|
+
return getService().config();
|
|
38
36
|
},
|
|
39
37
|
|
|
40
38
|
async get() {
|
|
41
|
-
return
|
|
39
|
+
return getService().get();
|
|
42
40
|
},
|
|
43
41
|
|
|
44
42
|
async getById(ctx) {
|
|
45
43
|
const { params } = ctx;
|
|
46
44
|
const { id } = parseParams(params);
|
|
47
|
-
return
|
|
45
|
+
return getService().getById(id);
|
|
48
46
|
},
|
|
49
47
|
|
|
50
48
|
async render(ctx) {
|
|
51
49
|
const { params, query = {} } = ctx;
|
|
52
50
|
const { type, menu: menuOnly } = query;
|
|
53
51
|
const { idOrSlug } = parseParams(params);
|
|
54
|
-
return
|
|
52
|
+
return getService().render(
|
|
55
53
|
idOrSlug,
|
|
56
54
|
type,
|
|
57
55
|
menuOnly,
|
|
@@ -61,7 +59,7 @@ module.exports = {
|
|
|
61
59
|
const { params, query = {} } = ctx;
|
|
62
60
|
const { type, menu: menuOnly } = query;
|
|
63
61
|
const { idOrSlug, childUIKey } = parseParams(params);
|
|
64
|
-
return
|
|
62
|
+
return getService().renderChildren(
|
|
65
63
|
idOrSlug,
|
|
66
64
|
childUIKey,
|
|
67
65
|
type,
|
|
@@ -72,14 +70,14 @@ module.exports = {
|
|
|
72
70
|
post(ctx) {
|
|
73
71
|
const { auditLog } = ctx;
|
|
74
72
|
const { body = {} } = ctx.request;
|
|
75
|
-
return
|
|
73
|
+
return getService().post(body, auditLog);
|
|
76
74
|
},
|
|
77
75
|
|
|
78
76
|
put(ctx) {
|
|
79
77
|
const { params, auditLog } = ctx;
|
|
80
78
|
const { id } = parseParams(params);
|
|
81
79
|
const { body = {} } = ctx.request;
|
|
82
|
-
return
|
|
80
|
+
return getService().put(id, body, auditLog)
|
|
83
81
|
.catch(errorHandler(ctx));
|
|
84
82
|
},
|
|
85
83
|
};
|
package/models/navigationItem.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const { camelCase } = require('lodash');
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/models.html#life-cycle-callbacks)
|
|
@@ -7,10 +8,27 @@
|
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
type: {
|
|
10
|
-
INTERNAL:
|
|
11
|
-
EXTERNAL:
|
|
11
|
+
INTERNAL: 'INTERNAL',
|
|
12
|
+
EXTERNAL: 'EXTERNAL',
|
|
12
13
|
},
|
|
13
14
|
additionalFields: {
|
|
14
15
|
AUDIENCE: 'audience',
|
|
15
16
|
},
|
|
17
|
+
lifecycles: {
|
|
18
|
+
afterFind(results) {
|
|
19
|
+
results.forEach(_ => {
|
|
20
|
+
_?.related.forEach(entity => {
|
|
21
|
+
for (const [key, value] of Object.entries(entity)) {
|
|
22
|
+
const newKey = camelCase(key);
|
|
23
|
+
if (value) {
|
|
24
|
+
entity[newKey] = value;
|
|
25
|
+
}
|
|
26
|
+
if (newKey !== key) {
|
|
27
|
+
delete entity[key];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
},
|
|
16
34
|
};
|
|
@@ -15,17 +15,28 @@
|
|
|
15
15
|
},
|
|
16
16
|
"content-type-builder": {
|
|
17
17
|
"visible": false
|
|
18
|
+
},
|
|
19
|
+
"i18n": {
|
|
20
|
+
"localized": false
|
|
18
21
|
}
|
|
19
22
|
},
|
|
20
23
|
"attributes": {
|
|
21
24
|
"title": {
|
|
22
25
|
"type": "text",
|
|
23
26
|
"configurable": false,
|
|
24
|
-
"required": true
|
|
27
|
+
"required": true,
|
|
28
|
+
"pluginOptions": {
|
|
29
|
+
"i18n": {
|
|
30
|
+
"localized": false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
25
33
|
},
|
|
26
34
|
"type": {
|
|
27
35
|
"type": "enumeration",
|
|
28
|
-
"enum": [
|
|
36
|
+
"enum": [
|
|
37
|
+
"INTERNAL",
|
|
38
|
+
"EXTERNAL"
|
|
39
|
+
],
|
|
29
40
|
"default": "INTERNAL",
|
|
30
41
|
"configurable": false
|
|
31
42
|
},
|
|
@@ -53,8 +64,8 @@
|
|
|
53
64
|
"configurable": false
|
|
54
65
|
},
|
|
55
66
|
"related": {
|
|
56
|
-
"collection": "
|
|
57
|
-
"
|
|
67
|
+
"collection": "navigations_items_related",
|
|
68
|
+
"plugin": "navigation",
|
|
58
69
|
"configurable": false
|
|
59
70
|
},
|
|
60
71
|
"parent": {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { camelCase } = require('lodash');
|
|
2
|
+
module.exports = {
|
|
3
|
+
lifecycles: {
|
|
4
|
+
afterFind(results) {
|
|
5
|
+
results
|
|
6
|
+
.forEach(entity => {
|
|
7
|
+
for (const [key, value] of Object.entries(entity)) {
|
|
8
|
+
const newKey = camelCase(key);
|
|
9
|
+
if (value) {
|
|
10
|
+
entity[newKey] = value;
|
|
11
|
+
}
|
|
12
|
+
if (newKey !== key) {
|
|
13
|
+
delete entity[key];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"collectionName": "navigations_items_related",
|
|
3
|
+
"info": {
|
|
4
|
+
"name": "navigations_items_related",
|
|
5
|
+
"description": ""
|
|
6
|
+
},
|
|
7
|
+
"options": {
|
|
8
|
+
"increments": true,
|
|
9
|
+
"timestamps": false,
|
|
10
|
+
"populateCreatorFields": false
|
|
11
|
+
},
|
|
12
|
+
"pluginOptions": {
|
|
13
|
+
"content-manager": {
|
|
14
|
+
"visible": false
|
|
15
|
+
},
|
|
16
|
+
"content-type-builder": {
|
|
17
|
+
"visible": false
|
|
18
|
+
},
|
|
19
|
+
"i18n": {
|
|
20
|
+
"localized": false
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"attributes": {
|
|
24
|
+
"related_id": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"required": true
|
|
27
|
+
},
|
|
28
|
+
"related_type": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"required": true
|
|
31
|
+
},
|
|
32
|
+
"field": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"required": true
|
|
35
|
+
},
|
|
36
|
+
"order": {
|
|
37
|
+
"type": "integer",
|
|
38
|
+
"required": true
|
|
39
|
+
},
|
|
40
|
+
"master": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"required": true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|