strapi-plugin-navigation 2.0.0-beta.5 → 2.0.2

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.
Files changed (54) hide show
  1. package/README.md +65 -22
  2. package/__mocks__/pages.settings.json +25 -0
  3. package/__mocks__/strapi.js +207 -0
  4. package/admin/src/components/ConfirmationDialog/index.js +56 -0
  5. package/admin/src/components/EmptyView/index.js +2 -1
  6. package/admin/src/components/Item/ItemCardBadge/index.js +15 -1
  7. package/admin/src/components/Item/ItemCardHeader/index.js +13 -26
  8. package/admin/src/components/Item/ItemCardRemovedOverlay/index.js +12 -0
  9. package/admin/src/components/Item/index.js +67 -25
  10. package/admin/src/components/NavigationItemList/index.js +8 -0
  11. package/admin/src/components/RestartAlert/index.js +8 -0
  12. package/admin/src/components/Search/index.js +21 -23
  13. package/admin/src/components/icons/navigation.js +14 -0
  14. package/admin/src/hooks/useAllContentTypes.js +13 -0
  15. package/admin/src/hooks/useNavigationConfig.js +58 -0
  16. package/admin/src/index.js +28 -4
  17. package/admin/src/pages/SettingsPage/index.js +311 -0
  18. package/admin/src/pages/View/components/NavigationHeader/index.js +41 -35
  19. package/admin/src/pages/View/components/NavigationHeader/styles.js +13 -0
  20. package/admin/src/pages/View/components/NavigationItemForm/index.js +50 -8
  21. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +3 -6
  22. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +3 -7
  23. package/admin/src/pages/View/components/NavigationItemPopup/index.js +3 -5
  24. package/admin/src/pages/View/index.js +31 -17
  25. package/admin/src/pages/View/utils/parsers.js +10 -4
  26. package/admin/src/permissions.js +8 -0
  27. package/admin/src/translations/en.json +53 -10
  28. package/admin/src/translations/fr.json +4 -4
  29. package/admin/src/utils/api.js +51 -0
  30. package/admin/src/utils/index.js +20 -0
  31. package/package.json +7 -6
  32. package/permissions.js +11 -0
  33. package/server/bootstrap.js +35 -5
  34. package/server/content-types/navigation/schema.json +45 -0
  35. package/server/content-types/navigation-item/schema.json +1 -1
  36. package/server/controllers/navigation.js +26 -2
  37. package/server/graphql/index.js +3 -4
  38. package/server/graphql/types/content-types-name-fields.js +4 -2
  39. package/server/graphql/types/navigation-related.js +2 -2
  40. package/server/routes/admin.js +24 -1
  41. package/server/services/__tests__/navigation.test.js +63 -78
  42. package/server/services/navigation.js +42 -11
  43. package/server/services/utils/functions.js +5 -12
  44. package/strapi-server.js +0 -2
  45. package/yarn-error.log +5263 -0
  46. package/.circleci/config.yml +0 -48
  47. package/.eslintrc +0 -35
  48. package/.github/pull_request_template.md +0 -13
  49. package/.github/stale.yml +0 -15
  50. package/.nvmrc +0 -1
  51. package/admin/src/components/PluginIcon/index.js +0 -6
  52. package/codecov.yml +0 -3
  53. package/server/content-types/navigation/schema.js +0 -45
  54. package/server/register.js +0 -5
@@ -1,84 +1,69 @@
1
- const { setupStrapi } = require('../../__mocks__/helpers/strapi');
1
+ const { setupStrapi } = require('../../../__mocks__/strapi');
2
2
 
3
- beforeAll(setupStrapi);
3
+ describe('Navigation services', () => {
4
+ beforeAll(async () => {
5
+ setupStrapi();
6
+ });
7
+
8
+ describe('Correct config', () => {
9
+ it('Declares Strapi instance', () => {
10
+ expect(strapi).toBeDefined()
11
+ expect(strapi.plugin('navigation').service('navigation')).toBeDefined()
12
+ });
4
13
 
5
- describe('Navigation service', () => {
6
- it('Strapi is defined', () => {
7
- expect(strapi).toBeDefined();
8
- expect(strapi.contentTypes).toBeDefined();
9
- expect(Object.keys(strapi.contentTypes).length).toBe(6);
14
+ it('Defines proper content types', () => {
15
+ expect(strapi.contentTypes).toBeDefined()
16
+ expect(strapi.plugin('navigation').contentTypes).toBeDefined()
17
+ });
18
+
19
+ it('Can read and return plugins config', () => {
20
+ expect(strapi.plugin('navigation').config('contentTypes')).toBeDefined()
21
+ expect(strapi.plugin('navigation').config('allowedLevels')).toBeDefined()
22
+ expect(strapi.plugin('navigation').config()).not.toBeDefined()
23
+ });
10
24
  });
11
- it('Config Content Types', () => {
12
- const { configContentTypes } = require('../navigation');
13
- const results = [
14
- {
15
- uid: 'application::pages.pages',
16
- collectionName: 'pages',
17
- isSingle: false,
18
- contentTypeName: 'Pages',
19
- endpoint: 'pages',
20
- label: 'Pages',
21
- labelSingular: 'Page',
22
- name: 'page',
23
- visible: true,
24
- }, {
25
- uid: 'application::blog-post.blog-post',
26
- collectionName: 'blog_posts',
27
- isSingle: false,
28
- contentTypeName: 'BlogPost',
29
- endpoint: 'blog-posts',
30
- label: 'Blog posts',
31
- labelSingular: 'Blog post',
32
- name: 'blog-post',
33
- visible: true,
34
- }, {
35
- uid: 'application::my-homepages.my-homepage',
36
- collectionName: 'my-homepages',
37
- isSingle: true,
38
- contentTypeName: 'MyHomepage',
39
- endpoint: 'my-homepage',
40
- label: 'My Homepage',
41
- labelSingular: 'My Homepage',
42
- name: 'my-homepage',
43
- visible: true,
44
- }, {
45
- uid: 'application::page-homes.home-page',
46
- collectionName: 'page_homes',
47
- isSingle: true,
48
- contentTypeName: 'HomePage',
49
- endpoint: 'custom-api',
50
- label: 'Page Home',
51
- labelSingular: 'Page Home',
52
- name: 'home-page',
53
- visible: true,
54
- }, {
55
- uid: 'plugins::another-plugin.pages',
56
- collectionName: 'pages',
57
- isSingle: false,
58
- contentTypeName: 'Plugin-pages',
59
- endpoint: 'plugin-pages',
60
- label: 'Pages',
61
- labelSingular: 'Page',
62
- name: 'plugin-page',
63
- visible: true,
64
- plugin: 'another-plugin',
65
- }, {
66
- uid: 'plugins::another-plugin.blog-post',
67
- collectionName: 'blog_posts',
68
- isSingle: false,
69
- contentTypeName: 'BlogPost',
70
- endpoint: 'plugin-blog-posts',
71
- label: 'Blog posts',
72
- labelSingular: 'Blog post',
73
- name: 'plugin-blog-post',
74
- visible: true,
75
- plugin: 'another-plugin',
76
- }];
77
- return configContentTypes().then(types => {
78
- types.map(type => {
79
- const result = results.find(({ uid }) => uid === type.uid);
80
- expect(type).toMatchObject(result);
81
- });
25
+
26
+ describe('Render navigation', () => {
27
+ it('Can render branch in flat format', async () => {
28
+ const service = strapi.plugin('navigation').service('navigation');
29
+ const result = await service.render(1);
30
+
31
+ expect(result).toBeDefined()
32
+ expect(result.length).toBe(2)
33
+ });
34
+
35
+ it('Can render branch in tree format', async () => {
36
+ const service = strapi.plugin('navigation').service('navigation');
37
+ const result = await service.render(1, "TREE");
38
+
39
+ expect(result).toBeDefined()
40
+ expect(result.length).toBeGreaterThan(0)
41
+ });
42
+
43
+ it('Can render branch in rfr format', async () => {
44
+ const service = strapi.plugin('navigation').service('navigation');
45
+ const result = await service.render(1, "RFR");
46
+
47
+ expect(result).toBeDefined()
48
+ expect(result.length).toBeGreaterThan(0)
49
+ });
50
+
51
+ it('Can render only menu attached elements', async () => {
52
+ const service = strapi.plugin('navigation').service('navigation');
53
+ const result = await service.render(1, "FLAT", true);
54
+
55
+ expect(result).toBeDefined()
56
+ expect(result.length).toBe(1)
57
+ });
58
+ });
59
+
60
+ describe('Render child', () => {
61
+ it('Can render child', async () => {
62
+ const service = strapi.plugin('navigation').service('navigation');
63
+ const result = await service.renderChildren(1, "home");
64
+
65
+ expect(result).toBeDefined();
66
+ expect(result.length).toBe(1);
82
67
  });
83
68
  });
84
69
  });
@@ -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 } = require('@strapi/utils').errors
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,27 +65,35 @@ 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 { pluginName, audienceModel } = utilsFunctions.extractMeta(strapi.plugins);
71
- const additionalFields = strapi.plugin(pluginName).config('additionalFields')
72
- const contentTypesNameFields = strapi.plugin(pluginName).config('contentTypesNameFields');
73
- const allowedLevels = strapi.plugin(pluginName).config('allowedLevels');
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 = {
77
- contentTypes: await strapi.plugin(pluginName).service('navigation').configContentTypes(),
84
+ contentTypes: await service.configContentTypes(),
78
85
  contentTypesNameFields: {
79
86
  default: contentTypesNameFieldsDefaults,
80
87
  ...(isObject(contentTypesNameFields) ? contentTypesNameFields : {}),
81
88
  },
82
89
  allowedLevels,
83
90
  additionalFields,
91
+ isGQLPluginEnabled: viaSettingsPage ? isGQLPluginEnabled : undefined,
84
92
  };
85
93
 
86
94
  if (additionalFields.includes(configAdditionalFields.AUDIENCE)) {
87
95
  const audienceItems = await strapi
88
- .query(`plugin::${pluginName}.${audienceModel.modelName}`)
96
+ .query(audienceModel.uid)
89
97
  .findMany({
90
98
  paggination: {
91
99
  limit: -1,
@@ -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
- strapi.plugin('navigation').config('contentTypes')
139
+ config.contentTypes
109
140
  .filter(contentType => !!strapi.contentTypes[contentType])
110
141
  .map(
111
142
  async (key) => {
@@ -700,7 +731,7 @@ module.exports = ({ strapi }) => {
700
731
  },
701
732
 
702
733
  removeRelated(relatedItems, master) {
703
- return Promise.all(relatedItems.map(relatedItem => {
734
+ return Promise.all((relatedItems || []).map(relatedItem => {
704
735
  const model = strapi.query('plugin::navigation.navigations-items-related');
705
736
  const entityToRemove = {
706
737
  master,
@@ -20,19 +20,12 @@ module.exports = ({ strapi }) => {
20
20
 
21
21
  extractMeta(plugins) {
22
22
  const { navigation: plugin } = plugins;
23
- const { navigation: service } = plugin.services;
24
- const {
25
- navigation: masterModel,
26
- 'navigation-item': itemModel,
27
- audience: audienceModel,
28
- 'navigations-items-related': relatedModel,
29
- } = plugin.contentTypes;
30
23
  return {
31
- masterModel,
32
- itemModel,
33
- relatedModel,
34
- audienceModel,
35
- service,
24
+ masterModel: plugin.contentType('navigation'),
25
+ itemModel: plugin.contentType('navigation-item'),
26
+ relatedModel: plugin.contentType('navigations-items-related'),
27
+ audienceModel: plugin.contentType('audience'),
28
+ service: plugin.service('navigation'),
36
29
  plugin,
37
30
  pluginName: 'navigation',
38
31
  };
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
  };