strapi-plugin-navigation 2.0.0 → 2.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.
- package/README.md +50 -5
- package/__mocks__/strapi.js +30 -19
- package/admin/src/components/ConfirmationDialog/index.js +56 -0
- package/admin/src/components/Item/ItemCardBadge/index.js +1 -1
- package/admin/src/components/Item/ItemCardHeader/index.js +6 -12
- package/admin/src/components/Item/index.js +8 -10
- package/admin/src/components/RestartAlert/index.js +8 -0
- package/admin/src/hooks/useAllContentTypes.js +13 -0
- package/admin/src/hooks/useNavigationConfig.js +58 -0
- package/admin/src/index.js +24 -1
- package/admin/src/pages/SettingsPage/index.js +311 -0
- package/admin/src/pages/View/components/NavigationItemForm/index.js +36 -9
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +3 -6
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +2 -4
- package/admin/src/pages/View/components/NavigationItemPopup/index.js +2 -4
- package/admin/src/translations/en.json +48 -8
- package/admin/src/translations/fr.json +4 -4
- package/admin/src/utils/api.js +51 -0
- package/admin/src/utils/index.js +20 -0
- package/package.json +5 -5
- package/server/bootstrap.js +30 -1
- package/server/controllers/navigation.js +30 -5
- package/server/graphql/index.js +3 -4
- package/server/graphql/queries/render-navigation.js +4 -3
- package/server/graphql/types/content-types-name-fields.js +4 -2
- package/server/graphql/types/navigation-related.js +2 -2
- package/server/routes/admin.js +24 -1
- package/server/services/__tests__/functions.test.js +48 -0
- package/server/services/__tests__/navigation.test.js +26 -4
- package/server/services/navigation.js +56 -16
- package/server/services/utils/functions.js +41 -0
- package/strapi-server.js +0 -2
- package/yarn-error.log +5263 -0
- package/.circleci/config.yml +0 -48
- package/.eslintrc +0 -35
- package/.github/pull_request_template.md +0 -13
- package/.github/stale.yml +0 -15
- package/.nvmrc +0 -1
- package/codecov.yml +0 -3
- package/public/assets/logo.png +0 -0
- package/public/assets/preview.png +0 -0
- package/server/register.js +0 -5
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useIntl } from 'react-intl';
|
|
2
|
+
import { isString } from 'lodash';
|
|
3
|
+
|
|
4
|
+
import pluginId from '../pluginId';
|
|
5
|
+
|
|
6
|
+
const getMessage = (input, defaultMessage = '', inPluginScope = true) => {
|
|
7
|
+
const { formatMessage } = useIntl();
|
|
8
|
+
let formattedId = ''
|
|
9
|
+
if (isString(input)) {
|
|
10
|
+
formattedId = input;
|
|
11
|
+
} else {
|
|
12
|
+
formattedId = input?.id;
|
|
13
|
+
}
|
|
14
|
+
return formatMessage({
|
|
15
|
+
id: `${inPluginScope ? pluginId : 'app.components'}.${formattedId}`,
|
|
16
|
+
defaultMessage,
|
|
17
|
+
}, input?.props || undefined)
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { getMessage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-navigation",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Strapi - Navigation plugin",
|
|
5
5
|
"strapi": {
|
|
6
6
|
"name": "navigation",
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"url": "https://github.com/VirtusLab/strapi-plugin-navigation"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"publish": "npm publish --tag latest",
|
|
16
|
+
"publish:latest": "npm publish --tag latest",
|
|
17
17
|
"test:unit": "jest --verbose --coverage"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@strapi/utils": "^4.0
|
|
20
|
+
"@strapi/utils": "^4.1.0",
|
|
21
21
|
"uuid": "^8.3.0",
|
|
22
22
|
"bad-words": "^3.0.3",
|
|
23
23
|
"lodash": "^4.17.11",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"@strapi/strapi": "4.x"
|
|
45
45
|
},
|
|
46
46
|
"author": {
|
|
47
|
-
"name": "VirtusLab
|
|
48
|
-
"email": "
|
|
47
|
+
"name": "VirtusLab",
|
|
48
|
+
"email": "strapi@virtuslab.com",
|
|
49
49
|
"url": "https://virtuslab.com"
|
|
50
50
|
},
|
|
51
51
|
"maintainers": [
|
package/server/bootstrap.js
CHANGED
|
@@ -23,7 +23,9 @@ module.exports = async ({ strapi }) => {
|
|
|
23
23
|
pluginName: "navigation",
|
|
24
24
|
},
|
|
25
25
|
];
|
|
26
|
+
await strapi.admin.services.permission.actionProvider.registerMany(actions);
|
|
26
27
|
|
|
28
|
+
// Initialize first navigation
|
|
27
29
|
const navigations = await strapi
|
|
28
30
|
.query("plugin::navigation.navigation")
|
|
29
31
|
.findMany();
|
|
@@ -38,5 +40,32 @@ module.exports = async ({ strapi }) => {
|
|
|
38
40
|
}
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
|
-
|
|
43
|
+
|
|
44
|
+
// Initialize configuration
|
|
45
|
+
const pluginStore = strapi.store({
|
|
46
|
+
environment: '',
|
|
47
|
+
type: 'plugin',
|
|
48
|
+
name: 'navigation',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const config = await pluginStore.get({ key: 'config' });
|
|
52
|
+
const pluginDefaultConfig = await strapi.plugin('navigation').config
|
|
53
|
+
const defaultConfigValue = {
|
|
54
|
+
additionalFields: pluginDefaultConfig('additionalFields'),
|
|
55
|
+
contentTypes: pluginDefaultConfig('contentTypes'),
|
|
56
|
+
contentTypesNameFields: pluginDefaultConfig('contentTypesNameFields'),
|
|
57
|
+
allowedLevels: pluginDefaultConfig('allowedLevels'),
|
|
58
|
+
gql: pluginDefaultConfig('gql'),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!config) {
|
|
62
|
+
pluginStore.set({
|
|
63
|
+
key: 'config', value: defaultConfigValue
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (strapi.plugin('graphql')) {
|
|
68
|
+
const graphqlConfiguration = require('./graphql')
|
|
69
|
+
await graphqlConfiguration({ strapi, config: config || defaultConfigValue });
|
|
70
|
+
}
|
|
42
71
|
};
|
|
@@ -19,10 +19,34 @@ const errorHandler = (ctx) => (error) => {
|
|
|
19
19
|
throw error;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
module.exports = {
|
|
22
|
+
module.exports = ({strapi}) => ({
|
|
23
23
|
async config() {
|
|
24
24
|
return getService().config();
|
|
25
25
|
},
|
|
26
|
+
|
|
27
|
+
async updateConfig(ctx) {
|
|
28
|
+
await getService().updateConfig(ctx.request.body)
|
|
29
|
+
return ctx.send({ status: 200 });
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async restoreConfig(ctx) {
|
|
33
|
+
await getService().restoreConfig()
|
|
34
|
+
return ctx.send({ status: 200 })
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async settingsConfig() {
|
|
38
|
+
return getService().config(true);
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
async settingsRestart(ctx) {
|
|
42
|
+
try {
|
|
43
|
+
await getService().restart();
|
|
44
|
+
return ctx.send({ status: 200 });
|
|
45
|
+
} catch (e) {
|
|
46
|
+
errorHandler(ctx, e);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
26
50
|
async get() {
|
|
27
51
|
return getService().get();
|
|
28
52
|
},
|
|
@@ -50,13 +74,14 @@ module.exports = {
|
|
|
50
74
|
},
|
|
51
75
|
async render(ctx) {
|
|
52
76
|
const { params, query = {} } = ctx;
|
|
53
|
-
const { type, menu: menuOnly } = query;
|
|
77
|
+
const { type, menu: menuOnly, path: rootPath } = query;
|
|
54
78
|
const { idOrSlug } = parseParams(params);
|
|
55
|
-
return getService().render(
|
|
79
|
+
return getService().render({
|
|
56
80
|
idOrSlug,
|
|
57
81
|
type,
|
|
58
82
|
menuOnly,
|
|
59
|
-
|
|
83
|
+
rootPath
|
|
84
|
+
});
|
|
60
85
|
},
|
|
61
86
|
async renderChild(ctx) {
|
|
62
87
|
const { params, query = {} } = ctx;
|
|
@@ -69,4 +94,4 @@ module.exports = {
|
|
|
69
94
|
menuOnly
|
|
70
95
|
);
|
|
71
96
|
},
|
|
72
|
-
};
|
|
97
|
+
});
|
package/server/graphql/index.js
CHANGED
|
@@ -2,16 +2,15 @@ const getTypes = require('./types');
|
|
|
2
2
|
const getQueries = require('./queries');
|
|
3
3
|
const getResolversConfig = require('./resolvers-config');
|
|
4
4
|
|
|
5
|
-
module.exports = () => {
|
|
5
|
+
module.exports = async ({ strapi, config }) => {
|
|
6
6
|
const extensionService = strapi.plugin('graphql').service('extension');
|
|
7
|
-
|
|
8
7
|
extensionService.shadowCRUD('plugin::navigation.audience').disable();
|
|
9
8
|
extensionService.shadowCRUD('plugin::navigation.navigation').disable();
|
|
10
9
|
extensionService.shadowCRUD('plugin::navigation.navigation-item').disable();
|
|
11
10
|
extensionService.shadowCRUD('plugin::navigation.navigations-items-related').disable();
|
|
12
11
|
|
|
13
|
-
extensionService.use(({ nexus
|
|
14
|
-
const types = getTypes({ strapi, nexus });
|
|
12
|
+
extensionService.use(({strapi, nexus}) => {
|
|
13
|
+
const types = getTypes({ strapi, nexus, config });
|
|
15
14
|
const queries = getQueries({ strapi, nexus });
|
|
16
15
|
const resolversConfig = getResolversConfig({ strapi });
|
|
17
16
|
|
|
@@ -5,11 +5,12 @@ module.exports = ({ strapi, nexus }) => {
|
|
|
5
5
|
args: {
|
|
6
6
|
navigationIdOrSlug: nonNull(stringArg()),
|
|
7
7
|
type: 'NavigationRenderType',
|
|
8
|
-
menuOnly: booleanArg()
|
|
8
|
+
menuOnly: booleanArg(),
|
|
9
|
+
path: stringArg(),
|
|
9
10
|
},
|
|
10
11
|
resolve(obj, args) {
|
|
11
|
-
const { navigationIdOrSlug, type, menuOnly } = args;
|
|
12
|
-
return strapi.plugin('navigation').service('navigation').render(
|
|
12
|
+
const { navigationIdOrSlug: idOrSlug, type, menuOnly, path: rootPath } = args;
|
|
13
|
+
return strapi.plugin('navigation').service('navigation').render({idOrSlug, type, menuOnly, rootPath});
|
|
13
14
|
},
|
|
14
15
|
};
|
|
15
16
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
module.exports = ({ nexus }) => nexus.objectType({
|
|
2
2
|
name: "ContentTypesNameFields",
|
|
3
|
-
definition(t) {
|
|
3
|
+
async definition(t) {
|
|
4
4
|
t.nonNull.list.nonNull.string("default")
|
|
5
|
-
const
|
|
5
|
+
const pluginStore = strapi.store({ type: 'plugin', name: 'navigation' });
|
|
6
|
+
const config = await pluginStore.get({ key: 'config' });
|
|
7
|
+
const contentTypesNameFields = config.contentTypesNameFields;
|
|
6
8
|
Object.keys(contentTypesNameFields || {}).forEach(key => t.nonNull.list.string(key))
|
|
7
9
|
}
|
|
8
10
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module.exports = ({ strapi, nexus }) => {
|
|
2
|
-
const related =
|
|
1
|
+
module.exports = ({ strapi, nexus, config }) => {
|
|
2
|
+
const related = config.gql?.navigationItemRelated;
|
|
3
3
|
const name = "NavigationRelated";
|
|
4
4
|
|
|
5
5
|
if (related?.length) {
|
package/server/routes/admin.js
CHANGED
|
@@ -16,6 +16,16 @@ module.exports = {
|
|
|
16
16
|
path: '/config',
|
|
17
17
|
handler: 'navigation.config',
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
method: 'PUT',
|
|
21
|
+
path: '/config',
|
|
22
|
+
handler: 'navigation.updateConfig',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
method: 'DELETE',
|
|
26
|
+
path: '/config',
|
|
27
|
+
handler: 'navigation.restoreConfig',
|
|
28
|
+
},
|
|
19
29
|
{
|
|
20
30
|
method: 'GET',
|
|
21
31
|
path: '/:id',
|
|
@@ -33,6 +43,19 @@ module.exports = {
|
|
|
33
43
|
policies: [
|
|
34
44
|
'admin::isAuthenticatedAdmin'
|
|
35
45
|
]
|
|
36
|
-
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
method: 'GET',
|
|
49
|
+
path: '/settings/config',
|
|
50
|
+
handler: 'navigation.settingsConfig',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
method: 'GET',
|
|
54
|
+
path: '/settings/restart',
|
|
55
|
+
handler: 'navigation.settingsRestart',
|
|
56
|
+
config: {
|
|
57
|
+
policies: [],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
37
60
|
]
|
|
38
61
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { setupStrapi } = require('../../../__mocks__/strapi');
|
|
2
|
+
const utilsFunctionsFactory = require('../utils/functions');
|
|
3
|
+
|
|
4
|
+
describe('Utilities functions', () => {
|
|
5
|
+
beforeAll(async () => {
|
|
6
|
+
setupStrapi();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe('Path rendering functions', () => {
|
|
10
|
+
it('Can build nested path structure', async () => {
|
|
11
|
+
const utilsFunctions = utilsFunctionsFactory({ strapi });
|
|
12
|
+
const { itemModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
13
|
+
const rootPath = '/home/side';
|
|
14
|
+
const entities = await strapi
|
|
15
|
+
.query(itemModel.uid)
|
|
16
|
+
.findMany({
|
|
17
|
+
where: {
|
|
18
|
+
master: 1
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const nested = utilsFunctions.buildNestedPaths({ items: entities });
|
|
22
|
+
|
|
23
|
+
expect(nested.length).toBe(2);
|
|
24
|
+
expect(nested[1].path).toBe(rootPath);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('Can filter items by path', async () => {
|
|
28
|
+
const utilsFunctions = utilsFunctionsFactory({ strapi });
|
|
29
|
+
const { itemModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
30
|
+
const rootPath = '/home/side';
|
|
31
|
+
const entities = await strapi
|
|
32
|
+
.query(itemModel.uid)
|
|
33
|
+
.findMany({
|
|
34
|
+
where: {
|
|
35
|
+
master: 1
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const {
|
|
39
|
+
root,
|
|
40
|
+
items
|
|
41
|
+
} = utilsFunctions.filterByPath(entities, rootPath);
|
|
42
|
+
|
|
43
|
+
expect(root).toBeDefined();
|
|
44
|
+
expect(root.path).toBe(rootPath);
|
|
45
|
+
expect(items.length).toBe(1)
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -26,7 +26,7 @@ describe('Navigation services', () => {
|
|
|
26
26
|
describe('Render navigation', () => {
|
|
27
27
|
it('Can render branch in flat format', async () => {
|
|
28
28
|
const service = strapi.plugin('navigation').service('navigation');
|
|
29
|
-
const result = await service.render(1);
|
|
29
|
+
const result = await service.render({ idOrSlug: 1 });
|
|
30
30
|
|
|
31
31
|
expect(result).toBeDefined()
|
|
32
32
|
expect(result.length).toBe(2)
|
|
@@ -34,7 +34,10 @@ describe('Navigation services', () => {
|
|
|
34
34
|
|
|
35
35
|
it('Can render branch in tree format', async () => {
|
|
36
36
|
const service = strapi.plugin('navigation').service('navigation');
|
|
37
|
-
const result = await service.render(
|
|
37
|
+
const result = await service.render({
|
|
38
|
+
idOrSlug: 1,
|
|
39
|
+
type: "TREE"
|
|
40
|
+
});
|
|
38
41
|
|
|
39
42
|
expect(result).toBeDefined()
|
|
40
43
|
expect(result.length).toBeGreaterThan(0)
|
|
@@ -42,7 +45,10 @@ describe('Navigation services', () => {
|
|
|
42
45
|
|
|
43
46
|
it('Can render branch in rfr format', async () => {
|
|
44
47
|
const service = strapi.plugin('navigation').service('navigation');
|
|
45
|
-
const result = await service.render(
|
|
48
|
+
const result = await service.render({
|
|
49
|
+
idOrSlug: 1,
|
|
50
|
+
type: "RFR"
|
|
51
|
+
});
|
|
46
52
|
|
|
47
53
|
expect(result).toBeDefined()
|
|
48
54
|
expect(result.length).toBeGreaterThan(0)
|
|
@@ -50,11 +56,27 @@ describe('Navigation services', () => {
|
|
|
50
56
|
|
|
51
57
|
it('Can render only menu attached elements', async () => {
|
|
52
58
|
const service = strapi.plugin('navigation').service('navigation');
|
|
53
|
-
const result = await service.render(
|
|
59
|
+
const result = await service.render({
|
|
60
|
+
idOrSlug: 1,
|
|
61
|
+
type: "FLAT",
|
|
62
|
+
menuOnly: true.valueOf,
|
|
63
|
+
});
|
|
54
64
|
|
|
55
65
|
expect(result).toBeDefined()
|
|
56
66
|
expect(result.length).toBe(1)
|
|
57
67
|
});
|
|
68
|
+
|
|
69
|
+
it('Can render branch by path', async () => {
|
|
70
|
+
const service = strapi.plugin('navigation').service('navigation');
|
|
71
|
+
const result = await service.render({
|
|
72
|
+
idOrSlug: 1,
|
|
73
|
+
type: "FLAT",
|
|
74
|
+
rootPath: '/home/side'
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(result).toBeDefined();
|
|
78
|
+
expect(result.length).toBe(1);
|
|
79
|
+
});
|
|
58
80
|
});
|
|
59
81
|
|
|
60
82
|
describe('Render child', () => {
|
|
@@ -19,7 +19,7 @@ const { KIND_TYPES } = require('./utils/constant');
|
|
|
19
19
|
const utilsFunctionsFactory = require('./utils/functions');
|
|
20
20
|
const { renderType } = require('../content-types/navigation/lifecycle');
|
|
21
21
|
const { type: itemType, additionalFields: configAdditionalFields } = require('../content-types/navigation-item').lifecycle;
|
|
22
|
-
const { NotFoundError } =
|
|
22
|
+
const { NotFoundError } = require('@strapi/utils').errors
|
|
23
23
|
const excludedContentTypes = ['strapi::'];
|
|
24
24
|
const contentTypesNameFieldsDefaults = ['title', 'subject', 'name'];
|
|
25
25
|
|
|
@@ -56,7 +56,7 @@ module.exports = ({ strapi }) => {
|
|
|
56
56
|
limit: -1,
|
|
57
57
|
},
|
|
58
58
|
sort: ['order:asc'],
|
|
59
|
-
populate: ['related', 'parent']
|
|
59
|
+
populate: ['related', 'parent', 'audience']
|
|
60
60
|
});
|
|
61
61
|
const entities = await this.getRelatedItems(entityItems);
|
|
62
62
|
return {
|
|
@@ -65,12 +65,19 @@ module.exports = ({ strapi }) => {
|
|
|
65
65
|
};
|
|
66
66
|
},
|
|
67
67
|
|
|
68
|
+
async restart() {
|
|
69
|
+
setImmediate(() => strapi.reload());
|
|
70
|
+
},
|
|
71
|
+
|
|
68
72
|
// Get plugin config
|
|
69
|
-
async config() {
|
|
70
|
-
const {
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
73
|
+
async config(viaSettingsPage = false) {
|
|
74
|
+
const { audienceModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
75
|
+
const pluginStore = await strapi.store({ type: 'plugin', name: 'navigation' });
|
|
76
|
+
const config = await pluginStore.get({ key: 'config' });
|
|
77
|
+
const additionalFields = config.additionalFields;
|
|
78
|
+
const contentTypesNameFields = config.contentTypesNameFields;
|
|
79
|
+
const allowedLevels = config.allowedLevels;
|
|
80
|
+
const isGQLPluginEnabled = !isNil(strapi.plugin('graphql'));
|
|
74
81
|
|
|
75
82
|
let extendedResult = {};
|
|
76
83
|
const result = {
|
|
@@ -81,6 +88,7 @@ module.exports = ({ strapi }) => {
|
|
|
81
88
|
},
|
|
82
89
|
allowedLevels,
|
|
83
90
|
additionalFields,
|
|
91
|
+
isGQLPluginEnabled: viaSettingsPage ? isGQLPluginEnabled : undefined,
|
|
84
92
|
};
|
|
85
93
|
|
|
86
94
|
if (additionalFields.includes(configAdditionalFields.AUDIENCE)) {
|
|
@@ -102,10 +110,33 @@ module.exports = ({ strapi }) => {
|
|
|
102
110
|
};
|
|
103
111
|
},
|
|
104
112
|
|
|
113
|
+
async updateConfig(newConfig) {
|
|
114
|
+
const pluginStore = await strapi.store({ type: 'plugin', name: 'navigation' });
|
|
115
|
+
await pluginStore.set({ key: 'config', value: newConfig });
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
async restoreConfig() {
|
|
119
|
+
const pluginStore = await strapi.store({ type: 'plugin', name: 'navigation' });
|
|
120
|
+
const defaultConfig = await strapi.plugin('navigation').config
|
|
121
|
+
|
|
122
|
+
await pluginStore.delete({ key: 'config' })
|
|
123
|
+
await pluginStore.set({
|
|
124
|
+
key: 'config', value: {
|
|
125
|
+
additionalFields: defaultConfig('additionalFields'),
|
|
126
|
+
contentTypes: defaultConfig('contentTypes'),
|
|
127
|
+
contentTypesNameFields: defaultConfig('contentTypesNameFields'),
|
|
128
|
+
allowedLevels: defaultConfig('allowedLevels'),
|
|
129
|
+
gql: defaultConfig('gql'),
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
|
|
105
134
|
async configContentTypes() {
|
|
135
|
+
const pluginStore = strapi.store({ type: 'plugin', name: 'navigation' });
|
|
136
|
+
const config = await pluginStore.get({ key: 'config' });
|
|
106
137
|
const eligibleContentTypes =
|
|
107
138
|
await Promise.all(
|
|
108
|
-
|
|
139
|
+
config.contentTypes
|
|
109
140
|
.filter(contentType => !!strapi.contentTypes[contentType])
|
|
110
141
|
.map(
|
|
111
142
|
async (key) => {
|
|
@@ -311,20 +342,20 @@ module.exports = ({ strapi }) => {
|
|
|
311
342
|
...(type === renderType.FLAT ? { uiRouterKey: childUIKey } : {}),
|
|
312
343
|
};
|
|
313
344
|
|
|
314
|
-
return service.renderType(type, criteria, itemCriteria, filter);
|
|
345
|
+
return service.renderType({ type, criteria, itemCriteria, filter });
|
|
315
346
|
},
|
|
316
347
|
|
|
317
|
-
async render(idOrSlug, type = renderType.FLAT, menuOnly = false) {
|
|
348
|
+
async render({ idOrSlug, type = renderType.FLAT, menuOnly = false, rootPath = null }) {
|
|
318
349
|
const { service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
319
350
|
|
|
320
351
|
const findById = !isNaN(toNumber(idOrSlug)) || isUuid(idOrSlug);
|
|
321
352
|
const criteria = findById ? { id: idOrSlug } : { slug: idOrSlug };
|
|
322
353
|
const itemCriteria = menuOnly ? { menuAttached: true } : {};
|
|
323
354
|
|
|
324
|
-
return service.renderType(type, criteria, itemCriteria);
|
|
355
|
+
return service.renderType({ type, criteria, itemCriteria, rootPath });
|
|
325
356
|
},
|
|
326
357
|
|
|
327
|
-
async renderType(type = renderType.FLAT, criteria = {}, itemCriteria = {}, filter = null) {
|
|
358
|
+
async renderType({ type = renderType.FLAT, criteria = {}, itemCriteria = {}, filter = null, rootPath = null }) {
|
|
328
359
|
const { pluginName, service, masterModel, itemModel } = utilsFunctions.extractMeta(
|
|
329
360
|
strapi.plugins,
|
|
330
361
|
);
|
|
@@ -362,8 +393,8 @@ module.exports = ({ strapi }) => {
|
|
|
362
393
|
const getTemplateName = await utilsFunctions.templateNameFactory(items, strapi, contentTypes);
|
|
363
394
|
const itemParser = (item, path = '', field) => {
|
|
364
395
|
const isExternal = item.type === itemType.EXTERNAL;
|
|
365
|
-
const parentPath = isExternal ? undefined : `${path === '/' ? '' : path}/${item.path === '/'
|
|
366
|
-
?
|
|
396
|
+
const parentPath = isExternal ? undefined : `${path === '/' ? '' : path}/${first(item.path) === '/'
|
|
397
|
+
? item.path.substring(1)
|
|
367
398
|
: item.path}`;
|
|
368
399
|
const slug = isString(parentPath) ? slugify(
|
|
369
400
|
(first(parentPath) === '/' ? parentPath.substring(1) : parentPath).replace(/\//g, '-')) : undefined;
|
|
@@ -391,9 +422,17 @@ module.exports = ({ strapi }) => {
|
|
|
391
422
|
}),
|
|
392
423
|
};
|
|
393
424
|
};
|
|
425
|
+
|
|
426
|
+
const {
|
|
427
|
+
items: itemsFilteredByPath,
|
|
428
|
+
root: rootElement,
|
|
429
|
+
} = utilsFunctions.filterByPath(items, rootPath);
|
|
430
|
+
|
|
394
431
|
const treeStructure = service.renderTree({
|
|
395
|
-
items,
|
|
432
|
+
items: isNil(rootPath) ? items : itemsFilteredByPath,
|
|
396
433
|
field: 'parent',
|
|
434
|
+
id: get(rootElement, 'parent.id'),
|
|
435
|
+
path: get(rootElement, 'parent.path'),
|
|
397
436
|
itemParser,
|
|
398
437
|
});
|
|
399
438
|
|
|
@@ -409,7 +448,7 @@ module.exports = ({ strapi }) => {
|
|
|
409
448
|
}
|
|
410
449
|
return filteredStructure;
|
|
411
450
|
default:
|
|
412
|
-
|
|
451
|
+
const publishedItems = items
|
|
413
452
|
.filter(utilsFunctions.filterOutUnpublished)
|
|
414
453
|
.map((item) => ({
|
|
415
454
|
...item,
|
|
@@ -418,6 +457,7 @@ module.exports = ({ strapi }) => {
|
|
|
418
457
|
related: item.related?.map(({ localizations, ...item }) => item),
|
|
419
458
|
items: null,
|
|
420
459
|
}));
|
|
460
|
+
return isNil(rootPath) ? items : utilsFunctions.filterByPath(publishedItems, rootPath).items;
|
|
421
461
|
}
|
|
422
462
|
}
|
|
423
463
|
throw new NotFoundError();
|
|
@@ -6,6 +6,8 @@ const {
|
|
|
6
6
|
find,
|
|
7
7
|
isString,
|
|
8
8
|
get,
|
|
9
|
+
isNil,
|
|
10
|
+
isArray
|
|
9
11
|
} = require('lodash');
|
|
10
12
|
|
|
11
13
|
const { type: itemType } = require('../../content-types/navigation-item/lifecycle');
|
|
@@ -52,6 +54,45 @@ module.exports = ({ strapi }) => {
|
|
|
52
54
|
});
|
|
53
55
|
},
|
|
54
56
|
|
|
57
|
+
buildNestedPaths({items, id = null, field = 'parent', parentPath = null}){
|
|
58
|
+
return items
|
|
59
|
+
.filter(entity => {
|
|
60
|
+
if (entity[field] == null && id === null) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
let data = entity[field];
|
|
64
|
+
if (data && typeof id === 'string') {
|
|
65
|
+
data = data.toString();
|
|
66
|
+
}
|
|
67
|
+
return (data && data === id) || (isObject(entity[field]) && (entity[field].id === id));
|
|
68
|
+
})
|
|
69
|
+
.reduce((acc, entity) => {
|
|
70
|
+
const path = `${parentPath || ''}/${entity.path}`
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
id: entity.id,
|
|
74
|
+
parent: parentPath && {
|
|
75
|
+
id: get(entity, 'parent.id'),
|
|
76
|
+
path: parentPath,
|
|
77
|
+
},
|
|
78
|
+
path
|
|
79
|
+
},
|
|
80
|
+
...this.buildNestedPaths({items, id: entity.id, field, parentPath: path}),
|
|
81
|
+
...acc,
|
|
82
|
+
];
|
|
83
|
+
}, [])
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
filterByPath(items, path) {
|
|
87
|
+
const itemsWithPaths = this.buildNestedPaths({ items }).filter(({path: itemPath}) => itemPath.includes(path));
|
|
88
|
+
const root = itemsWithPaths.find(({ path: itemPath }) => itemPath === path);
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
root,
|
|
92
|
+
items: isNil(root) ? [] : items.filter(({ id }) => (itemsWithPaths.find(v => v.id === id))),
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
|
|
55
96
|
prepareAuditLog(actions) {
|
|
56
97
|
return [
|
|
57
98
|
...new Set(
|
package/strapi-server.js
CHANGED
|
@@ -4,7 +4,6 @@ const routes = require('./server/routes');
|
|
|
4
4
|
const controllers = require('./server/controllers');
|
|
5
5
|
const contentTypes = require('./server/content-types');
|
|
6
6
|
const config = require('./server/config');
|
|
7
|
-
const register = require('./server/register');
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
module.exports = () => {
|
|
@@ -15,6 +14,5 @@ module.exports = () => {
|
|
|
15
14
|
controllers,
|
|
16
15
|
services,
|
|
17
16
|
contentTypes,
|
|
18
|
-
register,
|
|
19
17
|
};
|
|
20
18
|
};
|