strapi-plugin-navigation 2.0.13 → 2.1.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.
Files changed (288) hide show
  1. package/README.md +105 -27
  2. package/admin/src/components/Alert/styles.d.ts +2 -0
  3. package/admin/src/components/Alert/styles.js +10 -4
  4. package/admin/src/components/CollapseButton/index.d.ts +7 -0
  5. package/admin/src/components/CollapseButton/index.js +21 -22
  6. package/admin/src/components/ConfirmationDialog/index.d.ts +28 -0
  7. package/admin/src/components/ConfirmationDialog/index.js +32 -54
  8. package/admin/src/components/EmptyView/index.d.ts +3 -0
  9. package/admin/src/components/EmptyView/index.js +9 -7
  10. package/admin/src/components/Item/ItemCardBadge/index.d.ts +3 -0
  11. package/admin/src/components/Item/ItemCardBadge/index.js +11 -7
  12. package/admin/src/components/Item/ItemCardHeader/Wrapper.d.ts +3 -0
  13. package/admin/src/components/Item/ItemCardHeader/Wrapper.js +10 -6
  14. package/admin/src/components/Item/ItemCardHeader/index.d.ts +12 -0
  15. package/admin/src/components/Item/ItemCardHeader/index.js +33 -52
  16. package/admin/src/components/Item/ItemCardRemovedOverlay/index.d.ts +2 -0
  17. package/admin/src/components/Item/ItemCardRemovedOverlay/index.js +10 -4
  18. package/admin/src/components/Item/Wrapper.d.ts +3 -0
  19. package/admin/src/components/Item/Wrapper.js +10 -6
  20. package/admin/src/components/Item/index.d.ts +31 -0
  21. package/admin/src/components/Item/index.js +163 -242
  22. package/admin/src/components/NavigationItemList/Wrapper.d.ts +3 -0
  23. package/admin/src/components/NavigationItemList/Wrapper.js +9 -5
  24. package/admin/src/components/NavigationItemList/index.d.ts +35 -0
  25. package/admin/src/components/NavigationItemList/index.js +28 -66
  26. package/admin/src/components/RestartAlert/index.d.ts +3 -0
  27. package/admin/src/components/RestartAlert/index.js +10 -5
  28. package/admin/src/components/Search/index.d.ts +6 -0
  29. package/admin/src/components/Search/index.js +57 -46
  30. package/admin/src/components/icons/navigation.d.ts +6 -0
  31. package/admin/src/components/icons/navigation.js +11 -13
  32. package/admin/src/contexts/DataManagerContext.d.ts +3 -0
  33. package/admin/src/contexts/DataManagerContext.js +6 -5
  34. package/admin/src/hooks/useAllContentTypes.d.ts +6 -0
  35. package/admin/src/hooks/useAllContentTypes.js +10 -11
  36. package/admin/src/hooks/useDataManager.d.ts +3 -0
  37. package/admin/src/hooks/useDataManager.js +10 -6
  38. package/admin/src/hooks/useI18nCopyNavigationItemsModal.d.ts +9 -0
  39. package/admin/src/hooks/useI18nCopyNavigationItemsModal.js +51 -0
  40. package/admin/src/hooks/useNavigationConfig.d.ts +10 -0
  41. package/admin/src/hooks/useNavigationConfig.js +52 -56
  42. package/admin/src/hooks/useNavigationManager.d.ts +7 -0
  43. package/admin/src/hooks/useNavigationManager.js +41 -0
  44. package/admin/src/index.d.ts +14 -0
  45. package/admin/src/index.js +92 -76
  46. package/admin/src/pages/App/index.d.ts +3 -0
  47. package/admin/src/pages/App/index.js +43 -31
  48. package/admin/src/pages/DataManagerProvider/actions.d.ts +19 -0
  49. package/admin/src/pages/DataManagerProvider/actions.js +22 -26
  50. package/admin/src/pages/DataManagerProvider/index.d.ts +12 -0
  51. package/admin/src/pages/DataManagerProvider/index.js +316 -298
  52. package/admin/src/pages/DataManagerProvider/init.d.ts +3 -0
  53. package/admin/src/pages/DataManagerProvider/init.js +5 -3
  54. package/admin/src/pages/DataManagerProvider/reducer.d.ts +19 -0
  55. package/admin/src/pages/DataManagerProvider/reducer.js +119 -121
  56. package/admin/src/pages/SettingsPage/components/DisableI18nModal/index.d.ts +24 -0
  57. package/admin/src/pages/SettingsPage/components/DisableI18nModal/index.js +88 -0
  58. package/admin/src/pages/SettingsPage/index.d.ts +3 -0
  59. package/admin/src/pages/SettingsPage/index.js +242 -335
  60. package/admin/src/pages/SettingsPage/utils/functions.d.ts +5 -0
  61. package/admin/src/pages/SettingsPage/utils/functions.js +3 -8
  62. package/admin/src/pages/View/components/I18nCopyNavigationItems/index.d.ts +14 -0
  63. package/admin/src/pages/View/components/I18nCopyNavigationItems/index.js +15 -0
  64. package/admin/src/pages/View/components/NavigationContentHeader/index.d.ts +6 -0
  65. package/admin/src/pages/View/components/NavigationContentHeader/index.js +13 -17
  66. package/admin/src/pages/View/components/NavigationHeader/index.d.ts +12 -0
  67. package/admin/src/pages/View/components/NavigationHeader/index.js +79 -65
  68. package/admin/src/pages/View/components/NavigationHeader/styles.d.ts +2 -0
  69. package/admin/src/pages/View/components/NavigationHeader/styles.js +10 -5
  70. package/admin/src/pages/View/components/NavigationItemForm/index.d.ts +57 -0
  71. package/admin/src/pages/View/components/NavigationItemForm/index.js +416 -453
  72. package/admin/src/pages/View/components/NavigationItemForm/utils/form.d.ts +45 -0
  73. package/admin/src/pages/View/components/NavigationItemForm/utils/form.js +84 -52
  74. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.d.ts +23 -0
  75. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +24 -34
  76. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.d.ts +4 -0
  77. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +16 -16
  78. package/admin/src/pages/View/components/NavigationItemPopup/index.d.ts +30 -0
  79. package/admin/src/pages/View/components/NavigationItemPopup/index.js +85 -108
  80. package/admin/src/pages/View/components/NavigationManager/Create/index.d.ts +9 -0
  81. package/admin/src/pages/View/components/NavigationManager/Create/index.js +57 -0
  82. package/admin/src/pages/View/components/NavigationManager/Delete/index.d.ts +8 -0
  83. package/admin/src/pages/View/components/NavigationManager/Delete/index.js +28 -0
  84. package/admin/src/pages/View/components/NavigationManager/Edit/index.d.ts +8 -0
  85. package/admin/src/pages/View/components/NavigationManager/Edit/index.js +54 -0
  86. package/admin/src/pages/View/components/NavigationManager/Error/index.d.ts +8 -0
  87. package/admin/src/pages/View/components/NavigationManager/Error/index.js +53 -0
  88. package/admin/src/pages/View/components/NavigationManager/Form/index.d.ts +19 -0
  89. package/admin/src/pages/View/components/NavigationManager/Form/index.js +98 -0
  90. package/admin/src/pages/View/components/NavigationManager/List/index.d.ts +8 -0
  91. package/admin/src/pages/View/components/NavigationManager/List/index.js +138 -0
  92. package/admin/src/pages/View/components/NavigationManager/index.d.ts +10 -0
  93. package/admin/src/pages/View/components/NavigationManager/index.js +189 -0
  94. package/admin/src/pages/View/components/NavigationManager/types.d.ts +53 -0
  95. package/admin/src/pages/View/components/NavigationManager/types.js +3 -0
  96. package/admin/src/pages/View/index.d.ts +4 -0
  97. package/admin/src/pages/View/index.js +231 -304
  98. package/admin/src/pages/View/utils/enums.d.ts +9 -0
  99. package/admin/src/pages/View/utils/enums.js +11 -8
  100. package/admin/src/pages/View/utils/form.d.ts +2 -0
  101. package/admin/src/pages/View/utils/form.js +15 -12
  102. package/admin/src/pages/View/utils/index.d.ts +2 -0
  103. package/admin/src/pages/View/utils/index.js +11 -3
  104. package/admin/src/pages/View/utils/parsers.d.ts +49 -0
  105. package/admin/src/pages/View/utils/parsers.js +239 -278
  106. package/admin/src/permissions.d.ts +12 -0
  107. package/admin/src/permissions.js +11 -7
  108. package/admin/src/pluginId.d.ts +3 -0
  109. package/admin/src/pluginId.js +2 -2
  110. package/admin/src/translations/en.json +157 -104
  111. package/admin/src/translations/fr.json +44 -44
  112. package/admin/src/translations/index.d.ts +12 -0
  113. package/admin/src/translations/index.js +17 -11
  114. package/admin/src/utils/api.d.ts +8 -0
  115. package/admin/src/utils/api.js +54 -50
  116. package/admin/src/utils/getTrad.d.ts +3 -0
  117. package/admin/src/utils/getTrad.js +9 -5
  118. package/admin/src/utils/index.d.ts +18 -0
  119. package/admin/src/utils/index.js +36 -15
  120. package/package.json +20 -19
  121. package/permissions.d.ts +9 -0
  122. package/permissions.js +5 -4
  123. package/server/bootstrap/index.d.ts +4 -0
  124. package/server/bootstrap/index.js +41 -0
  125. package/server/config/index.d.ts +5 -0
  126. package/server/config/index.js +33 -9
  127. package/server/config/setupStrategy.d.ts +3 -0
  128. package/server/config/setupStrategy.js +38 -0
  129. package/server/content-types/audience/index.d.ts +27 -0
  130. package/server/content-types/audience/index.js +9 -8
  131. package/server/content-types/audience/schema.d.ts +25 -0
  132. package/server/content-types/audience/schema.js +26 -0
  133. package/server/content-types/index.d.ts +255 -0
  134. package/server/content-types/index.js +15 -12
  135. package/server/content-types/navigation/index.d.ts +64 -0
  136. package/server/content-types/navigation/index.js +11 -8
  137. package/server/content-types/navigation/lifecycle.d.ts +9 -0
  138. package/server/content-types/navigation/lifecycle.js +8 -12
  139. package/server/content-types/navigation/schema.d.ts +55 -0
  140. package/server/content-types/navigation/schema.js +56 -0
  141. package/server/content-types/navigation-item/index.d.ts +112 -0
  142. package/server/content-types/navigation-item/index.js +11 -8
  143. package/server/content-types/navigation-item/lifecycle.d.ts +16 -0
  144. package/server/content-types/navigation-item/lifecycle.js +28 -32
  145. package/server/content-types/navigation-item/schema.d.ts +97 -0
  146. package/server/content-types/navigation-item/schema.js +102 -0
  147. package/server/content-types/navigations-items-related/index.d.ts +56 -0
  148. package/server/content-types/navigations-items-related/index.js +11 -8
  149. package/server/content-types/navigations-items-related/lifecycle.d.ts +8 -0
  150. package/server/content-types/navigations-items-related/lifecycle.js +20 -17
  151. package/server/content-types/navigations-items-related/schema.d.ts +49 -0
  152. package/server/content-types/navigations-items-related/schema.js +50 -0
  153. package/server/controllers/admin.d.ts +4 -0
  154. package/server/controllers/admin.js +130 -0
  155. package/server/controllers/client.d.ts +4 -0
  156. package/server/controllers/client.js +57 -0
  157. package/server/controllers/index.d.ts +4 -0
  158. package/server/controllers/index.js +12 -6
  159. package/server/destroy.d.ts +3 -0
  160. package/server/destroy.js +5 -0
  161. package/server/graphql/config.d.ts +4 -0
  162. package/server/graphql/config.js +28 -0
  163. package/server/graphql/index.d.ts +2 -0
  164. package/server/graphql/index.js +18 -22
  165. package/server/graphql/queries/index.d.ts +3 -0
  166. package/server/graphql/queries/index.js +15 -15
  167. package/server/graphql/queries/render-navigation-child.d.ts +15 -0
  168. package/server/graphql/queries/render-navigation-child.js +24 -15
  169. package/server/graphql/queries/render-navigation.d.ts +21 -0
  170. package/server/graphql/queries/render-navigation.js +31 -15
  171. package/server/graphql/resolvers-config.d.ts +10 -0
  172. package/server/graphql/resolvers-config.js +5 -3
  173. package/server/graphql/setupStrategy.d.ts +3 -0
  174. package/server/graphql/setupStrategy.js +15 -0
  175. package/server/graphql/types/content-types-name-fields.d.ts +6 -0
  176. package/server/graphql/types/content-types-name-fields.js +13 -9
  177. package/server/graphql/types/content-types.d.ts +5 -0
  178. package/server/graphql/types/content-types.js +17 -15
  179. package/server/graphql/types/create-navigation-item.d.ts +5 -0
  180. package/server/graphql/types/create-navigation-item.js +18 -16
  181. package/server/graphql/types/create-navigation-related.d.ts +5 -0
  182. package/server/graphql/types/create-navigation-related.js +9 -7
  183. package/server/graphql/types/create-navigation.d.ts +5 -0
  184. package/server/graphql/types/create-navigation.js +8 -6
  185. package/server/graphql/types/index.d.ts +3 -0
  186. package/server/graphql/types/index.js +15 -13
  187. package/server/graphql/types/navigation-config.d.ts +5 -0
  188. package/server/graphql/types/navigation-config.js +10 -8
  189. package/server/graphql/types/navigation-details.d.ts +5 -0
  190. package/server/graphql/types/navigation-details.js +11 -9
  191. package/server/graphql/types/navigation-item-related-data.d.ts +5 -0
  192. package/server/graphql/types/navigation-item-related-data.js +9 -0
  193. package/server/graphql/types/navigation-item-related.d.ts +7 -0
  194. package/server/graphql/types/navigation-item-related.js +25 -0
  195. package/server/graphql/types/navigation-item.d.ts +5 -0
  196. package/server/graphql/types/navigation-item.js +28 -29
  197. package/server/graphql/types/navigation-render-type.d.ts +5 -0
  198. package/server/graphql/types/navigation-render-type.js +7 -4
  199. package/server/graphql/types/navigation.d.ts +5 -0
  200. package/server/graphql/types/navigation.js +10 -8
  201. package/server/i18n/constant.d.ts +2 -0
  202. package/server/i18n/constant.js +5 -0
  203. package/server/i18n/errors.d.ts +7 -0
  204. package/server/i18n/errors.js +14 -0
  205. package/server/i18n/graphQLEnhancers.d.ts +10 -0
  206. package/server/i18n/graphQLEnhancers.js +10 -0
  207. package/server/i18n/index.d.ts +8 -0
  208. package/server/i18n/index.js +23 -0
  209. package/server/i18n/navigationSetupStrategy.d.ts +3 -0
  210. package/server/i18n/navigationSetupStrategy.js +119 -0
  211. package/server/i18n/serviceEnhancers.d.ts +13 -0
  212. package/server/i18n/serviceEnhancers.js +156 -0
  213. package/server/i18n/types.d.ts +60 -0
  214. package/server/i18n/types.js +3 -0
  215. package/server/i18n/utils.d.ts +12 -0
  216. package/server/i18n/utils.js +29 -0
  217. package/server/index.d.ts +273 -0
  218. package/server/index.js +26 -0
  219. package/server/navigation/index.d.ts +2 -0
  220. package/server/navigation/index.js +18 -0
  221. package/server/navigation/setupStrategy.d.ts +3 -0
  222. package/server/navigation/setupStrategy.js +39 -0
  223. package/server/register/index.d.ts +3 -0
  224. package/server/register/index.js +4 -0
  225. package/server/routes/admin.d.ts +4 -0
  226. package/server/routes/admin.js +82 -61
  227. package/server/routes/client.d.ts +4 -0
  228. package/server/routes/client.js +25 -21
  229. package/server/routes/index.d.ts +6 -0
  230. package/server/routes/index.js +13 -4
  231. package/server/services/admin.d.ts +5 -0
  232. package/server/services/admin.js +238 -0
  233. package/server/services/client.d.ts +5 -0
  234. package/server/services/client.js +249 -0
  235. package/server/services/common.d.ts +5 -0
  236. package/server/services/common.js +313 -0
  237. package/server/services/index.d.ts +7 -0
  238. package/server/services/index.js +14 -6
  239. package/server/utils/constant.d.ts +27 -0
  240. package/server/utils/constant.js +24 -0
  241. package/server/utils/functions.d.ts +139 -0
  242. package/server/utils/functions.js +226 -0
  243. package/server/utils/index.d.ts +3 -0
  244. package/server/utils/index.js +19 -0
  245. package/strapi-admin.d.ts +3 -0
  246. package/strapi-admin.js +8 -1
  247. package/strapi-server.d.ts +273 -0
  248. package/strapi-server.js +6 -17
  249. package/tsconfig.tsbuildinfo +1 -0
  250. package/types/bootstrap.d.ts +13 -0
  251. package/types/bootstrap.js +3 -0
  252. package/types/config.d.ts +21 -0
  253. package/types/config.js +3 -0
  254. package/types/contentTypes.d.ts +85 -0
  255. package/types/contentTypes.js +3 -0
  256. package/types/controllers.d.ts +48 -0
  257. package/types/controllers.js +5 -0
  258. package/types/graphQL.d.ts +3 -0
  259. package/types/graphQL.js +3 -0
  260. package/types/i18n.d.ts +9 -0
  261. package/types/i18n.js +3 -0
  262. package/types/index.d.ts +9 -0
  263. package/types/index.js +25 -0
  264. package/types/services.d.ts +74 -0
  265. package/types/services.js +3 -0
  266. package/types/utils.d.ts +62 -0
  267. package/types/utils.js +27 -0
  268. package/utils/InvalidParamNavigationError.d.ts +4 -0
  269. package/utils/InvalidParamNavigationError.js +8 -0
  270. package/utils/NavigationError.d.ts +5 -0
  271. package/utils/NavigationError.js +7 -7
  272. package/__mocks__/pages.settings.json +0 -25
  273. package/__mocks__/strapi.js +0 -207
  274. package/jest.config.js +0 -14
  275. package/server/bootstrap.js +0 -52
  276. package/server/config.js +0 -9
  277. package/server/content-types/audience/lifecycle.js +0 -8
  278. package/server/content-types/audience/schema.json +0 -23
  279. package/server/content-types/navigation/schema.json +0 -45
  280. package/server/content-types/navigation-item/schema.json +0 -99
  281. package/server/content-types/navigations-items-related/schema.json +0 -47
  282. package/server/controllers/navigation.js +0 -105
  283. package/server/graphql/types/navigation-related.js +0 -25
  284. package/server/services/__tests__/functions.test.js +0 -48
  285. package/server/services/__tests__/navigation.test.js +0 -91
  286. package/server/services/navigation.js +0 -791
  287. package/server/services/utils/constant.js +0 -21
  288. package/server/services/utils/functions.js +0 -226
@@ -1,791 +0,0 @@
1
- const pluralize = require('pluralize');
2
- const {
3
- find,
4
- get,
5
- isNil,
6
- isObject,
7
- isEmpty,
8
- last,
9
- upperFirst,
10
- map,
11
- toNumber,
12
- isString,
13
- first,
14
- } = require('lodash');
15
- const { validate: isUuid } = require('uuid');
16
- const slugify = require('slugify');
17
- const { KIND_TYPES, ALLOWED_CONTENT_TYPES, RESTRICTED_CONTENT_TYPES } = require('./utils/constant');
18
- const utilsFunctionsFactory = require('./utils/functions');
19
- const { renderType } = require('../content-types/navigation/lifecycle');
20
- const { type: itemType, additionalFields: configAdditionalFields } = require('../content-types/navigation-item').lifecycle;
21
- const { NotFoundError } = require('@strapi/utils').errors
22
- const contentTypesNameFieldsDefaults = ['title', 'subject', 'name'];
23
-
24
- module.exports = ({ strapi }) => {
25
- const utilsFunctions = utilsFunctionsFactory(strapi);
26
-
27
- return {
28
- // Get all available navigations
29
- async get() {
30
- const { masterModel } = utilsFunctions.extractMeta(strapi.plugins);
31
- const entities = await strapi
32
- .query(masterModel.uid)
33
- .findMany({
34
- limit: Number.MAX_SAFE_INTEGER,
35
- });
36
- return entities;
37
- },
38
-
39
- async getById(id) {
40
- const { masterModel, itemModel } = utilsFunctions.extractMeta(strapi.plugins);
41
- const entity = await strapi
42
- .query(masterModel.uid)
43
- .findOne({ where: { id } });
44
-
45
- const entityItems = await strapi
46
- .query(itemModel.uid)
47
- .findMany({
48
- where: {
49
- master: id,
50
- },
51
- limit: Number.MAX_SAFE_INTEGER,
52
- sort: ['order:asc'],
53
- populate: ['related', 'parent', 'audience']
54
- });
55
- const entities = await this.getRelatedItems(entityItems);
56
- return {
57
- ...entity,
58
- items: utilsFunctions.buildNestedStructure(entities),
59
- };
60
- },
61
-
62
- async restart() {
63
- setImmediate(() => strapi.reload());
64
- },
65
-
66
- // Get plugin config
67
- async config(viaSettingsPage = false) {
68
- const { audienceModel } = utilsFunctions.extractMeta(strapi.plugins);
69
- const pluginStore = await this.getPluginStore()
70
- const config = await pluginStore.get({ key: 'config' });
71
- const additionalFields = config.additionalFields;
72
- const contentTypesNameFields = config.contentTypesNameFields;
73
- const contentTypesPopulate = config.contentTypesPopulate;
74
- const allowedLevels = config.allowedLevels;
75
- const isGQLPluginEnabled = !isNil(strapi.plugin('graphql'));
76
-
77
- let extendedResult = {
78
- allowedContentTypes: ALLOWED_CONTENT_TYPES,
79
- restrictedContentTypes: RESTRICTED_CONTENT_TYPES,
80
- };
81
- const result = {
82
- contentTypes: await this.configContentTypes(viaSettingsPage),
83
- contentTypesNameFields: {
84
- default: contentTypesNameFieldsDefaults,
85
- ...(isObject(contentTypesNameFields) ? contentTypesNameFields : {}),
86
- },
87
- contentTypesPopulate: {
88
- ...(isObject(contentTypesPopulate) ? contentTypesPopulate : {}),
89
- },
90
- allowedLevels,
91
- additionalFields,
92
- isGQLPluginEnabled: viaSettingsPage ? isGQLPluginEnabled : undefined,
93
- };
94
-
95
- if (additionalFields.includes(configAdditionalFields.AUDIENCE)) {
96
- const audienceItems = await strapi
97
- .query(audienceModel.uid)
98
- .findMany({
99
- limit: Number.MAX_SAFE_INTEGER,
100
- });
101
- extendedResult = {
102
- ...extendedResult,
103
- availableAudience: audienceItems,
104
- };
105
- }
106
- return {
107
- ...result,
108
- ...extendedResult,
109
- };
110
- },
111
-
112
- async updateConfig(newConfig) {
113
- const pluginStore = await this.getPluginStore()
114
- await pluginStore.set({ key: 'config', value: newConfig });
115
- },
116
-
117
- async getPluginStore() {
118
- return await strapi.store({ type: 'plugin', name: 'navigation' });
119
- },
120
-
121
- async setDefaultConfig() {
122
- const pluginStore = await this.getPluginStore()
123
- const config = await pluginStore.get({ key: 'config' });
124
- const pluginDefaultConfig = await strapi.plugin('navigation').config
125
-
126
- // If new value gets introduced to the config it either is read from plugin store or from default plugin config
127
- // This is fix for backwards compatibility and migration of config to newer version of the plugin
128
- const defaultConfigValue = {
129
- additionalFields: get(config, 'additionalFields', pluginDefaultConfig('additionalFields')),
130
- contentTypes: get(config, 'contentTypes', pluginDefaultConfig('contentTypes')),
131
- contentTypesNameFields: get(config, 'contentTypesNameFields', pluginDefaultConfig('contentTypesNameFields')),
132
- contentTypesPopulate: get(config, 'contentTypesPopulate', pluginDefaultConfig('contentTypesPopulate')),
133
- allowedLevels: get(config, 'allowedLevels', pluginDefaultConfig('allowedLevels')),
134
- gql: get(config, 'gql', pluginDefaultConfig('gql')),
135
- }
136
- pluginStore.set({ key: 'config', value: defaultConfigValue });
137
-
138
- return defaultConfigValue;
139
- },
140
-
141
- async restoreConfig() {
142
- const pluginStore = await this.getPluginStore()
143
- await pluginStore.delete({ key: 'config' });
144
- await strapi.plugin('navigation').service('navigation').setDefaultConfig();
145
- },
146
-
147
- async configContentTypes(viaSettingsPage = false) {
148
- const pluginStore = await this.getPluginStore()
149
- const config = await pluginStore.get({ key: 'config' });
150
- const eligibleContentTypes =
151
- await Promise.all(
152
- config.contentTypes
153
- .filter(contentType => !!strapi.contentTypes[contentType] && utilsFunctions.isContentTypeEligible(contentType))
154
- .map(
155
- async (key) => {
156
- const item = strapi.contentTypes[key];
157
-
158
- const { kind, options, uid } = item;
159
- const { draftAndPublish } = options;
160
-
161
- const isSingleType = kind === KIND_TYPES.SINGLE;
162
- const isSingleTypeWithPublishFlow = isSingleType && draftAndPublish;
163
-
164
- const returnType = (available) => ({
165
- key,
166
- available,
167
- });
168
-
169
- if (isSingleType) {
170
- if (isSingleTypeWithPublishFlow) {
171
- const itemsCountOrBypass = isSingleTypeWithPublishFlow ?
172
- await strapi.query(uid).count({
173
- publicationState: 'live',
174
- }) :
175
- true;
176
- return returnType(itemsCountOrBypass !== 0);
177
- }
178
- const isAvailable = await strapi.query(uid).count();
179
- return isAvailable === 1 ?
180
- returnType(true) :
181
- (viaSettingsPage ? returnType(false) : undefined);
182
- }
183
- return returnType(true);
184
- },
185
- ),
186
- );
187
- return eligibleContentTypes
188
- .filter(key => key)
189
- .map(({ key, available }) => {
190
- const item = strapi.contentTypes[key];
191
- const relatedField = (item.associations || []).find(_ => _.model === 'navigationitem');
192
- const { uid, options, info, collectionName, modelName, apiName, plugin, kind, pluginOptions } = item;
193
- const { visible = true } = pluginOptions['content-manager'] || {};
194
- const { name, description } = info;
195
- const { hidden, templateName } = options;
196
- const findRouteConfig = find(get(strapi.api, `[${modelName}].config.routes`, []),
197
- route => route.handler.includes('.find'));
198
- const findRoutePath = findRouteConfig && findRouteConfig.path.split('/')[1];
199
- const apiPath = findRoutePath && (findRoutePath !== apiName) ? findRoutePath : apiName || modelName;
200
- const isSingle = kind === KIND_TYPES.SINGLE;
201
- const endpoint = isSingle ? apiPath : pluralize(apiPath);
202
- const relationName = utilsFunctions.singularize(modelName);
203
- const relationNameParts = last(uid.split('.')).split('-');
204
- const contentTypeName = relationNameParts.length > 1 ? relationNameParts.reduce(
205
- (prev, curr) => `${prev}${upperFirst(curr)}`, '') : upperFirst(modelName);
206
- const labelSingular = name ||
207
- (upperFirst(relationNameParts.length > 1 ? relationNameParts.join(' ') : relationName));
208
- return {
209
- uid,
210
- name: relationName,
211
- isSingle,
212
- description,
213
- collectionName,
214
- contentTypeName,
215
- label: isSingle ? labelSingular : pluralize(name || labelSingular),
216
- relatedField: relatedField ? relatedField.alias : undefined,
217
- labelSingular: utilsFunctions.singularize(labelSingular),
218
- endpoint,
219
- plugin,
220
- available: available && !hidden,
221
- visible,
222
- templateName,
223
- };
224
- })
225
- .filter((item) => viaSettingsPage || (item && item.available));
226
- },
227
-
228
- async getRelatedItems(entityItems) {
229
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
230
- const config = await pluginStore.get({ key: 'config' });
231
- const relatedTypes = new Set(entityItems.flatMap((item) => get(item.related, 'related_type')));
232
- const groupedItems = Array.from(relatedTypes).filter((relatedType) => relatedType).reduce(
233
- (acc, relatedType) => Object.assign(acc, {
234
- [relatedType]: [
235
- ...(acc[relatedType] || []),
236
- ...entityItems
237
- .filter((item => item.related?.related_type === relatedType))
238
- .flatMap((item) => Object.assign(item.related, { navigationItemId: item.id })),
239
- ],
240
- }),
241
- {});
242
-
243
- const data = new Map(
244
- (
245
- await Promise.all(
246
- Object.entries(groupedItems)
247
- .map(async ([model, related]) => {
248
- const relationData = await strapi
249
- .query(model)
250
- .findMany({
251
- where: {
252
- id: { $in: map(related, 'related_id') },
253
- },
254
- populate: config.contentTypesPopulate[model] || []
255
- });
256
- return relationData
257
- .flatMap(_ =>
258
- Object.assign(
259
- _,
260
- {
261
- __contentType: model,
262
- navigationItemId: related.find(
263
- ({ related_id }) => related_id === _.id.toString())?.navigationItemId,
264
- },
265
- ),
266
- );
267
- }),
268
- )
269
- )
270
- .flat(1)
271
- .map(_ => [_.navigationItemId, _]),
272
- );
273
- return entityItems
274
- .map(({ related, ...item }) => {
275
- const relatedData = data.get(item.id);
276
- if (relatedData) {
277
- return Object.assign(item, { related: [relatedData] });
278
- }
279
- return item;
280
- });
281
- },
282
-
283
- async getContentTypeItems(model) {
284
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
285
- const config = await pluginStore.get({ key: 'config' });
286
- try {
287
- const contentTypeItems = await strapi.query(model).findMany({
288
- populate: config.contentTypesPopulate[model] || []
289
- })
290
- return contentTypeItems;
291
- } catch (err) {
292
- return [];
293
- }
294
- },
295
-
296
- async post(payload, auditLog) {
297
- const { masterModel, service } = utilsFunctions.extractMeta(strapi.plugins);
298
- const { name, visible } = payload;
299
- const data = {
300
- name,
301
- slug: slugify(name).toLowerCase(),
302
- visible,
303
- }
304
-
305
- const existingEntity = await strapi
306
- .query(masterModel.uid)
307
- .create({ data });
308
-
309
- return service
310
- .createBranch(payload.items, existingEntity, null)
311
- .then(() => service.getById(existingEntity.id))
312
- .then((newEntity) => {
313
- utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
314
- { actionType: 'CREATE', oldEntity: existingEntity, newEntity });
315
- return newEntity;
316
- });
317
- },
318
-
319
- async put(id, payload, auditLog) {
320
- const { masterModel, service } = utilsFunctions.extractMeta(strapi.plugins);
321
- const { name, visible } = payload;
322
-
323
- const existingEntity = await service.getById(id);
324
- const entityNameHasChanged = existingEntity.name !== name || existingEntity.visible !== visible;
325
- if (entityNameHasChanged) {
326
-
327
- await strapi.query(masterModel.uid).update({
328
- where: { id },
329
- data: {
330
- name: entityNameHasChanged ? name : existingEntity.name,
331
- slug: entityNameHasChanged ? slugify(name).toLowerCase() : existingEntity.slug,
332
- visible,
333
- },
334
- });
335
- }
336
- return service
337
- .analyzeBranch(payload.items, existingEntity, null)
338
- .then((auditLogsOperations) =>
339
- Promise.all([
340
- auditLog ? utilsFunctions.prepareAuditLog((auditLogsOperations || []).flat(Number.MAX_SAFE_INTEGER)) : [],
341
- service.getById(existingEntity.id)],
342
- ))
343
- .then(([actionType, newEntity]) => {
344
- utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
345
- { actionType, oldEntity: existingEntity, newEntity });
346
- return newEntity;
347
- });
348
- },
349
-
350
- async renderChildren(
351
- idOrSlug,
352
- childUIKey,
353
- type = renderType.FLAT,
354
- menuOnly = false,
355
- ) {
356
- const { service } = utilsFunctions.extractMeta(strapi.plugins);
357
- const findById = !isNaN(toNumber(idOrSlug)) || isUuid(idOrSlug);
358
- const criteria = findById ? { id: idOrSlug } : { slug: idOrSlug };
359
- const filter = type === renderType.FLAT ? null : childUIKey;
360
-
361
- const itemCriteria = {
362
- ...(menuOnly && { menuAttached: true }),
363
- ...(type === renderType.FLAT ? { uiRouterKey: childUIKey } : {}),
364
- };
365
-
366
- return service.renderType({ type, criteria, itemCriteria, filter });
367
- },
368
-
369
- async render({ idOrSlug, type = renderType.FLAT, menuOnly = false, rootPath = null }) {
370
- const { service } = utilsFunctions.extractMeta(strapi.plugins);
371
-
372
- const findById = !isNaN(toNumber(idOrSlug)) || isUuid(idOrSlug);
373
- const criteria = findById ? { id: idOrSlug } : { slug: idOrSlug };
374
- const itemCriteria = menuOnly ? { menuAttached: true } : {};
375
-
376
- return service.renderType({ type, criteria, itemCriteria, rootPath });
377
- },
378
-
379
- async renderType({ type = renderType.FLAT, criteria = {}, itemCriteria = {}, filter = null, rootPath = null }) {
380
- const { pluginName, service, masterModel, itemModel } = utilsFunctions.extractMeta(
381
- strapi.plugins,
382
- );
383
-
384
- const entity = await strapi
385
- .query(masterModel.uid)
386
- .findOne({
387
- where: {
388
- ...criteria,
389
- visible: true,
390
- }
391
- });
392
- if (entity && entity.id) {
393
- const entities = await strapi.query(itemModel.uid).findMany({
394
- where: {
395
- master: entity.id,
396
- ...itemCriteria,
397
- },
398
- limit: Number.MAX_SAFE_INTEGER,
399
- sort: ['order:asc'],
400
- populate: ['related', 'audience', 'parent'],
401
- });
402
-
403
- if (!entities) {
404
- return [];
405
- }
406
- const items = await this.getRelatedItems(entities);
407
- const { contentTypes, contentTypesNameFields } = await service.config();
408
-
409
- switch (type?.toLowerCase()) {
410
- case renderType.TREE:
411
- case renderType.RFR:
412
- const getTemplateName = await utilsFunctions.templateNameFactory(items, strapi, contentTypes);
413
- const itemParser = (item, path = '', field) => {
414
- const isExternal = item.type === itemType.EXTERNAL;
415
- const parentPath = isExternal ? undefined : `${path === '/' ? '' : path}/${first(item.path) === '/'
416
- ? item.path.substring(1)
417
- : item.path}`;
418
- const slug = isString(parentPath) ? slugify(
419
- (first(parentPath) === '/' ? parentPath.substring(1) : parentPath).replace(/\//g, '-')) : undefined;
420
- const lastRelated = item.related ? last(item.related) : undefined;
421
- return {
422
- id: item.id,
423
- title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
424
- menuAttached: item.menuAttached,
425
- order: item.order,
426
- path: isExternal ? item.externalPath : parentPath,
427
- type: item.type,
428
- uiRouterKey: item.uiRouterKey,
429
- slug: !slug && item.uiRouterKey ? slugify(item.uiRouterKey) : slug,
430
- external: isExternal,
431
- related: isExternal || !lastRelated ? undefined : {
432
- ...lastRelated,
433
- __templateName: getTemplateName(lastRelated.relatedType || lastRelated.__contentType, lastRelated.id),
434
- },
435
- audience: !isEmpty(item.audience) ? item.audience.map(aItem => aItem.key) : undefined,
436
- items: isExternal ? undefined : service.renderTree({
437
- items,
438
- id: item.id,
439
- field,
440
- path: parentPath,
441
- itemParser,
442
- }),
443
- };
444
- };
445
-
446
- const {
447
- items: itemsFilteredByPath,
448
- root: rootElement,
449
- } = utilsFunctions.filterByPath(items, rootPath);
450
-
451
- const treeStructure = service.renderTree({
452
- items: isNil(rootPath) ? items : itemsFilteredByPath,
453
- field: 'parent',
454
- id: get(rootElement, 'parent.id'),
455
- path: get(rootElement, 'parent.path'),
456
- itemParser,
457
- });
458
-
459
- const filteredStructure = filter
460
- ? treeStructure.filter((item) => item.uiRouterKey === filter)
461
- : treeStructure;
462
-
463
- if (type === renderType.RFR) {
464
- return service.renderRFR({
465
- items: filteredStructure,
466
- contentTypes,
467
- });
468
- }
469
- return filteredStructure;
470
- default:
471
- const publishedItems = items
472
- .filter(utilsFunctions.filterOutUnpublished)
473
- .map((item) => ({
474
- ...item,
475
- audience: item.audience?.map(_ => _.key),
476
- title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
477
- related: last(item.related?.map(({ localizations, ...item }) => item)),
478
- items: null,
479
- }));
480
- return isNil(rootPath) ? publishedItems : utilsFunctions.filterByPath(publishedItems, rootPath).items;
481
- }
482
- }
483
- throw new NotFoundError();
484
- },
485
-
486
- renderTree({
487
- items = [],
488
- id = null,
489
- field = 'parent',
490
- path = '',
491
- itemParser = (i) => i,
492
- }) {
493
- return items
494
- .filter(
495
- (item) => {
496
- if (item[field] === null && id === null) {
497
- return true;
498
- }
499
- let data = item[field];
500
- if (data && typeof id === 'string') {
501
- data = data.toString();
502
- }
503
- return (data && data === id) || (isObject(item[field]) && (item[field].id === id));
504
- },
505
- )
506
- .filter(utilsFunctions.filterOutUnpublished)
507
- .map(item => itemParser({
508
- ...item,
509
- }, path, field))
510
- .sort((x, y) => {
511
- return x.order - y.order;
512
- });
513
- },
514
-
515
- renderRFR({ items, parent = null, parentNavItem = null, contentTypes = [] }) {
516
- const { service } = utilsFunctions.extractMeta(strapi.plugins);
517
- let pages = {};
518
- let nav = {};
519
- let navItems = [];
520
-
521
- items.forEach(item => {
522
- const { items: itemChilds, ...itemProps } = item;
523
- const itemNav = service.renderRFRNav(itemProps);
524
- const itemPage = service.renderRFRPage({
525
- item: itemProps,
526
- parent,
527
- });
528
-
529
- if (item.type === itemType.INTERNAL) {
530
- pages = {
531
- ...pages,
532
- [itemPage.id]: {
533
- ...itemPage,
534
- },
535
- };
536
- }
537
-
538
- if (item.menuAttached) {
539
- navItems.push(itemNav);
540
- }
541
-
542
- if (!parent) {
543
- nav = {
544
- ...nav,
545
- root: navItems,
546
- };
547
- } else {
548
- const navLevel = navItems
549
- .filter(navItem => navItem.type === itemType.INTERNAL.toLowerCase());
550
- if (!isEmpty(navLevel))
551
- nav = {
552
- ...nav,
553
- [parent]: [].concat(parentNavItem ? parentNavItem : [], navLevel),
554
- };
555
- }
556
-
557
- if (!isEmpty(itemChilds)) {
558
- const { nav: nestedNavs } = service.renderRFR({
559
- items: itemChilds,
560
- parent: itemPage.id,
561
- parentNavItem: itemNav,
562
- contentTypes,
563
- });
564
- const { pages: nestedPages } = service.renderRFR({
565
- items: itemChilds.filter(child => child.type === itemType.INTERNAL),
566
- parent: itemPage.id,
567
- parentNavItem: itemNav,
568
- contentTypes,
569
- });
570
- pages = {
571
- ...pages,
572
- ...nestedPages,
573
- };
574
- nav = {
575
- ...nav,
576
- ...nestedNavs,
577
- };
578
- }
579
- });
580
-
581
- return {
582
- pages,
583
- nav,
584
- };
585
- },
586
-
587
- renderRFRNav(item) {
588
- const { uiRouterKey, title, path, type, audience } = item;
589
- return {
590
- label: title,
591
- type: type.toLowerCase(),
592
- page: type === itemType.INTERNAL ? uiRouterKey : undefined,
593
- url: type === itemType.EXTERNAL ? path : undefined,
594
- audience,
595
- };
596
- },
597
-
598
- renderRFRPage({ item, parent }) {
599
- const { uiRouterKey, title, path, slug, related, type, audience, menuAttached } = item;
600
- const { __contentType, id, __templateName } = related || {};
601
- const contentType = __contentType || '';
602
- return {
603
- id: uiRouterKey,
604
- title,
605
- templateName: __templateName,
606
- related: type === itemType.INTERNAL ? {
607
- contentType,
608
- id,
609
- } : undefined,
610
- path,
611
- slug,
612
- parent,
613
- audience,
614
- menuAttached,
615
- };
616
- },
617
-
618
- createBranch(items = [], masterEntity = null, parentItem = null, operations = {}) {
619
- const { itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
620
- return Promise.all(
621
- items.map(async (item) => {
622
- operations.create = true;
623
- const { parent, master, related, ...params } = item;
624
- const relatedItems = await this.getIdsRelated(related, master);
625
- const data = {
626
- ...params,
627
- related: relatedItems,
628
- master: masterEntity,
629
- parent: parentItem ? { ...parentItem, _id: parentItem.id } : null,
630
- }
631
- const navigationItem = await strapi
632
- .query(itemModel.uid)
633
- .create({ data, populate: ['related', 'items'] });
634
- return !isEmpty(item.items)
635
- ? service.createBranch(
636
- item.items,
637
- masterEntity,
638
- navigationItem,
639
- operations,
640
- )
641
- : operations;
642
- }),
643
- );
644
- },
645
-
646
- removeBranch(items = [], operations = {}) {
647
- const { itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
648
- return Promise.all(
649
- items
650
- .filter(item => item.id)
651
- .map(async (item) => {
652
- operations.remove = true;
653
- const { id, related, master } = item;
654
- await Promise.all([
655
- strapi
656
- .query(itemModel.uid)
657
- .delete({ where: { id } }),
658
- this.removeRelated(related, master),
659
- ]);
660
- return !isEmpty(item.items)
661
- ? service.removeBranch(
662
- item.items,
663
- operations,
664
- )
665
- : operations;
666
- }),
667
- );
668
- },
669
-
670
- async updateBranch(toUpdate, masterEntity, parentItem, operations) {
671
- const { itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
672
- const databaseModel = strapi.query(itemModel.uid);
673
- return Promise.all(
674
- toUpdate.map(async (item) => {
675
- operations.update = true;
676
- const { id, updated, parent, master, related, items, ...params } = item;
677
- let currentItem;
678
- if (updated) {
679
- const relatedItems = await this.getIdsRelated(related, master);
680
- currentItem = await databaseModel
681
- .update({
682
- where: { id },
683
- data: {
684
- ...params,
685
- related: relatedItems,
686
- master: masterEntity,
687
- parent: parentItem ? { ...parentItem, _id: parentItem.id } : null,
688
- },
689
- });
690
- } else {
691
- currentItem = item;
692
- }
693
- return !isEmpty(items)
694
- ? service.analyzeBranch(
695
- items,
696
- masterEntity,
697
- currentItem,
698
- operations,
699
- )
700
- : operations;
701
- }),
702
- );
703
- },
704
-
705
- analyzeBranch(items = [], masterEntity = null, parentItem = null, prevOperations = {}) {
706
- const { service } = utilsFunctions.extractMeta(strapi.plugins);
707
- const { toCreate, toRemove, toUpdate } = items
708
- .reduce((acc, _) => {
709
- const branchName = service.getBranchName(_);
710
- if (branchName) {
711
- return { ...acc, [branchName]: [...acc[branchName], _] };
712
- }
713
- return acc;
714
- },
715
- { toRemove: [], toCreate: [], toUpdate: [] },
716
- );
717
- const operations = {
718
- create: prevOperations.create || !!toCreate.length,
719
- update: prevOperations.update || !!toUpdate.length,
720
- remove: prevOperations.remove || !!toRemove.length,
721
- };
722
- return utilsFunctions.checkDuplicatePath(parentItem || masterEntity, toCreate.concat(toUpdate))
723
- .then(() => Promise.all(
724
- [
725
- service.createBranch(toCreate, masterEntity, parentItem, operations),
726
- service.removeBranch(toRemove, operations),
727
- service.updateBranch(toUpdate, masterEntity, parentItem, operations),
728
- ],
729
- ));
730
- },
731
-
732
- getIdsRelated(relatedItems, master) {
733
- if (relatedItems) {
734
- return Promise.all(relatedItems.map(async relatedItem => {
735
- try {
736
- const model = strapi.query('plugin::navigation.navigations-items-related');
737
- const entity = await model
738
- .findOne({
739
- where: {
740
- related_id: relatedItem.refId,
741
- related_type: relatedItem.ref,
742
- field: relatedItem.field,
743
- master,
744
- }
745
- });
746
- if (!entity) {
747
- const newEntity = {
748
- master,
749
- order: 1,
750
- field: relatedItem.field,
751
- related_id: relatedItem.refId,
752
- related_type: relatedItem.ref,
753
- };
754
- return model.create({ data: newEntity }).then(({ id }) => id);
755
- }
756
- return entity.id;
757
- } catch (e) {
758
- console.error(e);
759
- }
760
- }));
761
- }
762
- },
763
-
764
- removeRelated(relatedItems, master) {
765
- return Promise.all((relatedItems || []).map(relatedItem => {
766
- const model = strapi.query('plugin::navigation.navigations-items-related');
767
- const entityToRemove = {
768
- master,
769
- field: relatedItem.field,
770
- related_id: relatedItem.refId,
771
- related_type: relatedItem.ref,
772
- };
773
- return model.delete({ where: entityToRemove });
774
- }));
775
- },
776
-
777
- getBranchName(item) {
778
- const hasId = !isNil(item.id);
779
- const toRemove = item.removed;
780
- if (hasId && !toRemove) {
781
- return 'toUpdate';
782
- }
783
- if (hasId && toRemove) {
784
- return 'toRemove';
785
- }
786
- if (!hasId && !toRemove) {
787
- return 'toCreate';
788
- }
789
- },
790
- }
791
- }