strapi-plugin-navigation 1.0.2 → 1.1.1
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/.circleci/config.yml +1 -1
- package/.github/stale.yml +15 -0
- package/.nvmrc +1 -1
- package/README.md +41 -31
- package/__mocks__/helpers/another-plugin/blog-post.settings.json +31 -0
- package/__mocks__/helpers/another-plugin/pages.settings.json +28 -0
- package/__mocks__/helpers/blog-post.settings.json +2 -1
- package/__mocks__/helpers/home-page.settings.json +4 -0
- package/__mocks__/helpers/my-homepage.settings.json +27 -0
- package/__mocks__/helpers/strapi.js +63 -4
- package/admin/src/containers/View/components/NavigationItemForm/utils/form.js +1 -1
- package/admin/src/containers/View/index.js +2 -2
- package/admin/src/containers/View/utils/parsers.js +11 -12
- package/admin/src/translations/en.json +2 -0
- package/admin/src/translations/fr.json +39 -0
- package/admin/src/translations/index.js +3 -1
- package/config/functions/bootstrap.js +107 -11
- package/config/routes.json +8 -0
- package/config/schema.graphql.js +204 -0
- package/controllers/navigation.js +18 -9
- 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 +3 -3
- package/services/__tests__/navigation.test.js +75 -30
- package/services/navigation.js +224 -102
- package/services/utils/functions.js +10 -10
package/services/navigation.js
CHANGED
|
@@ -5,20 +5,20 @@ const slugify = require('slugify');
|
|
|
5
5
|
const pluralize = require('pluralize');
|
|
6
6
|
const { sanitizeEntity } = require('strapi-utils');
|
|
7
7
|
const {
|
|
8
|
-
isArray,
|
|
9
8
|
isEmpty,
|
|
10
9
|
isObject,
|
|
11
10
|
isNil,
|
|
12
|
-
|
|
11
|
+
toNumber,
|
|
12
|
+
isNaN,
|
|
13
13
|
find,
|
|
14
14
|
first,
|
|
15
15
|
get,
|
|
16
|
-
kebabCase,
|
|
17
16
|
last,
|
|
18
17
|
upperFirst,
|
|
19
18
|
isString,
|
|
19
|
+
map,
|
|
20
20
|
} = require('lodash');
|
|
21
|
-
const { KIND_TYPES } = require(
|
|
21
|
+
const { KIND_TYPES } = require('./utils/constant');
|
|
22
22
|
const utilsFunctions = require('./utils/functions');
|
|
23
23
|
const { renderType } = require('../models/navigation');
|
|
24
24
|
const { type: itemType, additionalFields: configAdditionalFields } = require('../models/navigationItem');
|
|
@@ -32,29 +32,34 @@ const { type: itemType, additionalFields: configAdditionalFields } = require('..
|
|
|
32
32
|
const excludedContentTypes = ['strapi::'];
|
|
33
33
|
|
|
34
34
|
const contentTypesNameFieldsDefaults = [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
'title',
|
|
36
|
+
'subject',
|
|
37
|
+
'name',
|
|
38
38
|
];
|
|
39
|
-
const
|
|
39
|
+
const getContentTypesNameFields = () => get(
|
|
40
40
|
strapi.config,
|
|
41
|
-
|
|
41
|
+
'plugins.navigation.contentTypesNameFields',
|
|
42
42
|
{},
|
|
43
43
|
);
|
|
44
44
|
|
|
45
45
|
module.exports = {
|
|
46
|
+
isMongoDB() {
|
|
47
|
+
const { pluginName, model } = utilsFunctions.extractMeta(strapi.plugins);
|
|
48
|
+
const orm = strapi.query(model.modelName, pluginName).model.orm;
|
|
49
|
+
return orm === 'mongoose';
|
|
50
|
+
},
|
|
46
51
|
// Get plugin configuration
|
|
47
|
-
|
|
52
|
+
async config() {
|
|
48
53
|
const { pluginName, service, audienceModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
49
|
-
const additionalFields = get(strapi.config, '
|
|
54
|
+
const additionalFields = get(strapi.config, 'plugins.navigation.additionalFields', []);
|
|
50
55
|
let extendedResult = {};
|
|
51
56
|
const result = {
|
|
52
57
|
contentTypes: await service.configContentTypes(),
|
|
53
58
|
contentTypesNameFields: {
|
|
54
59
|
default: contentTypesNameFieldsDefaults,
|
|
55
|
-
...(
|
|
60
|
+
...getContentTypesNameFields(),
|
|
56
61
|
},
|
|
57
|
-
allowedLevels: get(strapi.config, '
|
|
62
|
+
allowedLevels: get(strapi.config, 'plugins.navigation.allowedLevels'),
|
|
58
63
|
additionalFields,
|
|
59
64
|
};
|
|
60
65
|
|
|
@@ -77,22 +82,20 @@ module.exports = {
|
|
|
77
82
|
};
|
|
78
83
|
},
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
async configContentTypes() {
|
|
81
86
|
const eligibleContentTypes =
|
|
82
87
|
await Promise.all(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (hasDefinedNavigationRelation) {
|
|
88
|
+
strapi.config.get('plugins.navigation.relatedContentTypes', [])
|
|
89
|
+
.filter(contentType => !!strapi.contentTypes[contentType])
|
|
90
|
+
.map(
|
|
91
|
+
async (key) => {
|
|
92
|
+
if (find(excludedContentTypes, name => key.includes(name))) { // exclude internal content types
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const item = strapi.contentTypes[key];
|
|
96
|
+
const { kind, options, uid } = item;
|
|
97
|
+
const { draftAndPublish } = options;
|
|
98
|
+
|
|
96
99
|
const isSingleType = kind === KIND_TYPES.SINGLE;
|
|
97
100
|
const isSingleTypeWithPublishFlow = isSingleType && draftAndPublish;
|
|
98
101
|
|
|
@@ -103,36 +106,40 @@ module.exports = {
|
|
|
103
106
|
|
|
104
107
|
if (isSingleType) {
|
|
105
108
|
if (isSingleTypeWithPublishFlow) {
|
|
106
|
-
const itemsCountOrBypass = isSingleTypeWithPublishFlow ?
|
|
109
|
+
const itemsCountOrBypass = isSingleTypeWithPublishFlow ?
|
|
107
110
|
await strapi.query(uid).count({
|
|
108
|
-
_publicationState: 'live'
|
|
109
|
-
}) :
|
|
111
|
+
_publicationState: 'live',
|
|
112
|
+
}) :
|
|
110
113
|
true;
|
|
111
114
|
return returnType(itemsCountOrBypass !== 0);
|
|
112
115
|
}
|
|
113
116
|
const isAvailable = await strapi.query(uid).count();
|
|
114
117
|
return isAvailable === 1 ? returnType(true) : undefined;
|
|
115
|
-
}
|
|
118
|
+
}
|
|
116
119
|
return returnType(true);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
)
|
|
120
|
+
},
|
|
121
|
+
),
|
|
121
122
|
);
|
|
122
123
|
return eligibleContentTypes
|
|
123
124
|
.filter(key => key)
|
|
124
|
-
.map(({ key, available}) => {
|
|
125
|
+
.map(({ key, available }) => {
|
|
125
126
|
const item = strapi.contentTypes[key];
|
|
126
127
|
const relatedField = (item.associations || []).find(_ => _.model === 'navigationitem');
|
|
127
|
-
const { uid, options, info, collectionName, apiName, plugin, kind } = item;
|
|
128
|
+
const { uid, options, info, collectionName, modelName, apiName, plugin, kind } = item;
|
|
128
129
|
const { name, description } = info;
|
|
129
130
|
const { isManaged, hidden, templateName } = options;
|
|
131
|
+
const findRouteConfig = find(get(strapi.api, `[${modelName}].config.routes`, []),
|
|
132
|
+
route => route.handler.includes('.find'));
|
|
133
|
+
const findRoutePath = findRouteConfig && findRouteConfig.path.split('/')[1];
|
|
134
|
+
const apiPath = findRoutePath && (findRoutePath !== apiName) ? findRoutePath : apiName || modelName;
|
|
130
135
|
const isSingle = kind === KIND_TYPES.SINGLE;
|
|
131
|
-
const endpoint = isSingle ?
|
|
132
|
-
const relationName = utilsFunctions.singularize(
|
|
136
|
+
const endpoint = isSingle ? apiPath : pluralize(apiPath);
|
|
137
|
+
const relationName = utilsFunctions.singularize(modelName);
|
|
133
138
|
const relationNameParts = last(uid.split('.')).split('-');
|
|
134
|
-
const contentTypeName = relationNameParts.length > 1 ? relationNameParts.reduce(
|
|
135
|
-
|
|
139
|
+
const contentTypeName = relationNameParts.length > 1 ? relationNameParts.reduce(
|
|
140
|
+
(prev, curr) => `${prev}${upperFirst(curr)}`, '') : upperFirst(modelName);
|
|
141
|
+
const labelSingular = name ||
|
|
142
|
+
(upperFirst(relationNameParts.length > 1 ? relationNameParts.join(' ') : relationName));
|
|
136
143
|
return {
|
|
137
144
|
uid,
|
|
138
145
|
name: relationName,
|
|
@@ -154,7 +161,7 @@ module.exports = {
|
|
|
154
161
|
},
|
|
155
162
|
|
|
156
163
|
// Get all available navigations
|
|
157
|
-
|
|
164
|
+
async get() {
|
|
158
165
|
const { pluginName, masterModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
159
166
|
const entities = await strapi
|
|
160
167
|
.query(masterModel.modelName, pluginName)
|
|
@@ -165,7 +172,7 @@ module.exports = {
|
|
|
165
172
|
},
|
|
166
173
|
|
|
167
174
|
// Get navigation by id with related
|
|
168
|
-
|
|
175
|
+
async getById(id) {
|
|
169
176
|
const { pluginName, masterModel, itemModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
170
177
|
const entity = await strapi
|
|
171
178
|
.query(masterModel.modelName, pluginName)
|
|
@@ -177,17 +184,17 @@ module.exports = {
|
|
|
177
184
|
master: id,
|
|
178
185
|
_limit: -1,
|
|
179
186
|
_sort: 'order:asc',
|
|
180
|
-
}
|
|
181
|
-
|
|
187
|
+
});
|
|
188
|
+
const entities = await this.getRelatedItems(entityItems);
|
|
182
189
|
return {
|
|
183
190
|
...sanitizeEntity(entity,
|
|
184
191
|
{ model: masterModel },
|
|
185
192
|
),
|
|
186
|
-
items: utilsFunctions.buildNestedStructure(
|
|
193
|
+
items: utilsFunctions.buildNestedStructure(entities),
|
|
187
194
|
};
|
|
188
195
|
},
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
async post(payload, auditLog) {
|
|
191
198
|
const { pluginName, masterModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
192
199
|
const { name, visible } = payload;
|
|
193
200
|
|
|
@@ -196,19 +203,20 @@ module.exports = {
|
|
|
196
203
|
.create({
|
|
197
204
|
name,
|
|
198
205
|
slug: slugify(name).toLowerCase(),
|
|
199
|
-
visible,
|
|
206
|
+
visible: !!visible,
|
|
200
207
|
});
|
|
201
208
|
|
|
202
209
|
return service
|
|
203
210
|
.createBranch(payload.items, existingEntity, null)
|
|
204
211
|
.then(() => service.getById(existingEntity.id))
|
|
205
212
|
.then((newEntity) => {
|
|
206
|
-
utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
|
|
213
|
+
utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
|
|
214
|
+
{ actionType: 'CREATE', oldEntity: existingEntity, newEntity });
|
|
207
215
|
return newEntity;
|
|
208
216
|
});
|
|
209
217
|
},
|
|
210
218
|
|
|
211
|
-
|
|
219
|
+
async put(id, payload, auditLog) {
|
|
212
220
|
const { pluginName, masterModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
213
221
|
const { name, visible } = payload;
|
|
214
222
|
|
|
@@ -220,7 +228,7 @@ module.exports = {
|
|
|
220
228
|
{
|
|
221
229
|
name: entityNameHasChanged ? name : existingEntity.name,
|
|
222
230
|
slug: entityNameHasChanged ? slugify(name).toLowerCase() : existingEntity.slug,
|
|
223
|
-
visible,
|
|
231
|
+
visible: !!visible,
|
|
224
232
|
},
|
|
225
233
|
);
|
|
226
234
|
}
|
|
@@ -232,23 +240,43 @@ module.exports = {
|
|
|
232
240
|
service.getById(existingEntity.id)],
|
|
233
241
|
))
|
|
234
242
|
.then(([actionType, newEntity]) => {
|
|
235
|
-
utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
|
|
243
|
+
utilsFunctions.sendAuditLog(auditLog, 'onChangeNavigation',
|
|
244
|
+
{ actionType, oldEntity: existingEntity, newEntity });
|
|
236
245
|
return newEntity;
|
|
237
246
|
});
|
|
238
247
|
},
|
|
239
248
|
|
|
240
|
-
|
|
249
|
+
async render(idOrSlug, type = renderType.FLAT, menuOnly = false) {
|
|
241
250
|
const { service } = utilsFunctions.extractMeta(
|
|
242
251
|
strapi.plugins,
|
|
243
252
|
);
|
|
244
|
-
const findById =
|
|
253
|
+
const findById = !isNaN(toNumber(idOrSlug)) || isUuid(idOrSlug);
|
|
245
254
|
const criteria = findById ? { id: idOrSlug } : { slug: idOrSlug };
|
|
246
255
|
const itemCriteria = menuOnly ? { menuAttached: true } : {};
|
|
247
256
|
|
|
248
257
|
return service.renderType(type, criteria, itemCriteria);
|
|
249
258
|
},
|
|
250
259
|
|
|
251
|
-
|
|
260
|
+
async renderChildren(
|
|
261
|
+
idOrSlug,
|
|
262
|
+
childUIKey,
|
|
263
|
+
type = renderType.FLAT,
|
|
264
|
+
menuOnly = false,
|
|
265
|
+
) {
|
|
266
|
+
const { service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
267
|
+
const findById = !isNaN(toNumber(idOrSlug)) || isUuid(idOrSlug);
|
|
268
|
+
const criteria = findById ? { id: idOrSlug } : { slug: idOrSlug };
|
|
269
|
+
const filter = type === renderType.FLAT ? null : childUIKey;
|
|
270
|
+
|
|
271
|
+
const itemCriteria = {
|
|
272
|
+
...(menuOnly && { menuAttached: true }),
|
|
273
|
+
...(type === renderType.FLAT ? { uiRouterKey: childUIKey } : {}),
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
return service.renderType(type, criteria, itemCriteria, filter);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
async renderType(type = renderType.FLAT, criteria = {}, itemCriteria = {}, filter = null) {
|
|
252
280
|
const { pluginName, service, masterModel, itemModel } = utilsFunctions.extractMeta(
|
|
253
281
|
strapi.plugins,
|
|
254
282
|
);
|
|
@@ -260,31 +288,36 @@ module.exports = {
|
|
|
260
288
|
visible: true,
|
|
261
289
|
});
|
|
262
290
|
if (entity && entity.id) {
|
|
263
|
-
const
|
|
291
|
+
const entities = await strapi.query(itemModel.modelName, pluginName).find(
|
|
264
292
|
{
|
|
265
293
|
master: entity.id,
|
|
266
294
|
...itemCriteria,
|
|
267
295
|
_limit: -1,
|
|
268
296
|
_sort: 'order:asc',
|
|
269
297
|
},
|
|
270
|
-
[
|
|
298
|
+
['related', 'audience'],
|
|
271
299
|
);
|
|
272
300
|
|
|
273
|
-
if (!
|
|
301
|
+
if (!entities) {
|
|
274
302
|
return [];
|
|
275
303
|
}
|
|
304
|
+
const items = await this.getRelatedItems(entities);
|
|
276
305
|
const { contentTypes, contentTypesNameFields } = await service.config();
|
|
277
|
-
const getTemplateName = await utilsFunctions.templateNameFactory(items, strapi, contentTypes)
|
|
278
306
|
|
|
279
|
-
switch (type) {
|
|
307
|
+
switch (type?.toLowerCase()) {
|
|
280
308
|
case renderType.TREE:
|
|
281
309
|
case renderType.RFR:
|
|
310
|
+
const getTemplateName = await utilsFunctions.templateNameFactory(items, strapi, contentTypes);
|
|
282
311
|
const itemParser = (item, path = '', field) => {
|
|
283
312
|
const isExternal = item.type === itemType.EXTERNAL;
|
|
284
|
-
const parentPath = isExternal ? undefined : `${path === '/' ? '' : path}/${item.path === '/'
|
|
285
|
-
|
|
313
|
+
const parentPath = isExternal ? undefined : `${path === '/' ? '' : path}/${item.path === '/'
|
|
314
|
+
? ''
|
|
315
|
+
: item.path}`;
|
|
316
|
+
const slug = isString(parentPath) ? slugify(
|
|
317
|
+
(first(parentPath) === '/' ? parentPath.substring(1) : parentPath).replace(/\//g, '-')) : undefined;
|
|
286
318
|
const lastRelated = item.related ? last(item.related) : undefined;
|
|
287
319
|
return {
|
|
320
|
+
id: item.id,
|
|
288
321
|
title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
|
|
289
322
|
menuAttached: item.menuAttached,
|
|
290
323
|
path: isExternal ? item.externalPath : parentPath,
|
|
@@ -294,7 +327,7 @@ module.exports = {
|
|
|
294
327
|
external: isExternal,
|
|
295
328
|
related: isExternal || !lastRelated ? undefined : {
|
|
296
329
|
...lastRelated,
|
|
297
|
-
__templateName: getTemplateName(lastRelated.
|
|
330
|
+
__templateName: getTemplateName(lastRelated.relatedType, lastRelated.id),
|
|
298
331
|
},
|
|
299
332
|
audience: !isEmpty(item.audience) ? item.audience.map(aItem => aItem.key) : undefined,
|
|
300
333
|
items: isExternal ? undefined : service.renderTree({
|
|
@@ -311,20 +344,26 @@ module.exports = {
|
|
|
311
344
|
field: 'parent',
|
|
312
345
|
itemParser,
|
|
313
346
|
});
|
|
347
|
+
|
|
348
|
+
const filteredStructure = filter
|
|
349
|
+
? treeStructure.filter((item) => item.uiRouterKey === filter)
|
|
350
|
+
: treeStructure;
|
|
351
|
+
|
|
314
352
|
if (type === renderType.RFR) {
|
|
315
353
|
return service.renderRFR({
|
|
316
|
-
items:
|
|
354
|
+
items: filteredStructure,
|
|
317
355
|
contentTypes,
|
|
318
356
|
});
|
|
319
357
|
}
|
|
320
|
-
return
|
|
358
|
+
return filteredStructure;
|
|
321
359
|
default:
|
|
322
360
|
return items
|
|
323
361
|
.filter(utilsFunctions.filterOutUnpublished)
|
|
324
362
|
.map((item) => ({
|
|
325
363
|
...sanitizeEntity(item, { model: itemModel }),
|
|
364
|
+
audience: item.audience?.map(_ => _.key),
|
|
326
365
|
title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
|
|
327
|
-
related: item.related,
|
|
366
|
+
related: item.related?.map(({ localizations, ...item }) => item),
|
|
328
367
|
items: null,
|
|
329
368
|
}));
|
|
330
369
|
}
|
|
@@ -332,13 +371,13 @@ module.exports = {
|
|
|
332
371
|
throw strapi.errors.notFound();
|
|
333
372
|
},
|
|
334
373
|
|
|
335
|
-
renderTree
|
|
374
|
+
renderTree({
|
|
336
375
|
items = [],
|
|
337
376
|
id = null,
|
|
338
377
|
field = 'parent',
|
|
339
378
|
path = '',
|
|
340
379
|
itemParser = (i) => i,
|
|
341
|
-
})
|
|
380
|
+
}) {
|
|
342
381
|
return items
|
|
343
382
|
.filter(
|
|
344
383
|
(item) => {
|
|
@@ -354,11 +393,11 @@ module.exports = {
|
|
|
354
393
|
)
|
|
355
394
|
.filter(utilsFunctions.filterOutUnpublished)
|
|
356
395
|
.map(item => itemParser({
|
|
357
|
-
...item
|
|
396
|
+
...item,
|
|
358
397
|
}, path, field));
|
|
359
398
|
},
|
|
360
399
|
|
|
361
|
-
renderRFR
|
|
400
|
+
renderRFR({ items, parent = null, parentNavItem = null, contentTypes = [] }) {
|
|
362
401
|
const { service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
363
402
|
let pages = {};
|
|
364
403
|
let nav = {};
|
|
@@ -368,7 +407,7 @@ module.exports = {
|
|
|
368
407
|
const { items: itemChilds, ...itemProps } = item;
|
|
369
408
|
const itemNav = service.renderRFRNav(itemProps);
|
|
370
409
|
const itemPage = service.renderRFRPage({
|
|
371
|
-
item: itemProps,
|
|
410
|
+
item: itemProps,
|
|
372
411
|
parent,
|
|
373
412
|
});
|
|
374
413
|
|
|
@@ -402,15 +441,15 @@ module.exports = {
|
|
|
402
441
|
|
|
403
442
|
if (!isEmpty(itemChilds)) {
|
|
404
443
|
const { nav: nestedNavs } = service.renderRFR({
|
|
405
|
-
items: itemChilds,
|
|
406
|
-
parent: itemPage.id,
|
|
444
|
+
items: itemChilds,
|
|
445
|
+
parent: itemPage.id,
|
|
407
446
|
parentNavItem: itemNav,
|
|
408
447
|
contentTypes,
|
|
409
448
|
});
|
|
410
449
|
const { pages: nestedPages } = service.renderRFR({
|
|
411
|
-
items: itemChilds.filter(child => child.type === itemType.INTERNAL),
|
|
412
|
-
parent: itemPage.id,
|
|
413
|
-
parentNavItem: itemNav,
|
|
450
|
+
items: itemChilds.filter(child => child.type === itemType.INTERNAL),
|
|
451
|
+
parent: itemPage.id,
|
|
452
|
+
parentNavItem: itemNav,
|
|
414
453
|
contentTypes,
|
|
415
454
|
});
|
|
416
455
|
pages = {
|
|
@@ -430,7 +469,7 @@ module.exports = {
|
|
|
430
469
|
};
|
|
431
470
|
},
|
|
432
471
|
|
|
433
|
-
renderRFRPage
|
|
472
|
+
renderRFRPage({ item, parent }) {
|
|
434
473
|
const { uiRouterKey, title, path, slug, related, type, audience, menuAttached } = item;
|
|
435
474
|
const { __contentType, id, __templateName } = related || {};
|
|
436
475
|
const contentType = __contentType || '';
|
|
@@ -439,7 +478,7 @@ module.exports = {
|
|
|
439
478
|
title,
|
|
440
479
|
templateName: __templateName,
|
|
441
480
|
related: type === itemType.INTERNAL ? {
|
|
442
|
-
contentType
|
|
481
|
+
contentType,
|
|
443
482
|
id,
|
|
444
483
|
} : undefined,
|
|
445
484
|
path,
|
|
@@ -450,7 +489,7 @@ module.exports = {
|
|
|
450
489
|
};
|
|
451
490
|
},
|
|
452
491
|
|
|
453
|
-
renderRFRNav
|
|
492
|
+
renderRFRNav(item) {
|
|
454
493
|
const { uiRouterKey, title, path, type, audience } = item;
|
|
455
494
|
return {
|
|
456
495
|
label: title,
|
|
@@ -461,19 +500,18 @@ module.exports = {
|
|
|
461
500
|
};
|
|
462
501
|
},
|
|
463
502
|
|
|
464
|
-
createBranch
|
|
503
|
+
createBranch(items = [], masterEntity = null, parentItem = null, operations = {}) {
|
|
465
504
|
const { pluginName, itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
466
505
|
return Promise.all(
|
|
467
506
|
items.map(async (item) => {
|
|
468
507
|
operations.create = true;
|
|
469
508
|
const { parent, master, related, ...params } = item;
|
|
470
|
-
const
|
|
471
|
-
isNil(related) || params.type === itemType.EXTERNAL ? [] : related;
|
|
509
|
+
const relatedItems = await this.getIdsRelated(related, master);
|
|
472
510
|
const navigationItem = await strapi
|
|
473
511
|
.query(itemModel.modelName, pluginName)
|
|
474
512
|
.create({
|
|
475
513
|
...params,
|
|
476
|
-
related:
|
|
514
|
+
related: relatedItems,
|
|
477
515
|
master: masterEntity,
|
|
478
516
|
parent: parentItem ? { ...parentItem, _id: parentItem.id } : null,
|
|
479
517
|
});
|
|
@@ -489,17 +527,20 @@ module.exports = {
|
|
|
489
527
|
);
|
|
490
528
|
},
|
|
491
529
|
|
|
492
|
-
removeBranch
|
|
530
|
+
removeBranch(items = [], operations = {}) {
|
|
493
531
|
const { pluginName, itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
494
532
|
return Promise.all(
|
|
495
533
|
items
|
|
496
534
|
.filter(item => item.id)
|
|
497
535
|
.map(async (item) => {
|
|
498
536
|
operations.remove = true;
|
|
499
|
-
const { id } = item;
|
|
500
|
-
await
|
|
501
|
-
|
|
502
|
-
|
|
537
|
+
const { id, related, master } = item;
|
|
538
|
+
await Promise.all([
|
|
539
|
+
strapi
|
|
540
|
+
.query(itemModel.modelName, pluginName)
|
|
541
|
+
.delete({ id }),
|
|
542
|
+
this.removeRelated(related, master),
|
|
543
|
+
]);
|
|
503
544
|
return !isEmpty(item.items)
|
|
504
545
|
? service.removeBranch(
|
|
505
546
|
item.items,
|
|
@@ -510,7 +551,7 @@ module.exports = {
|
|
|
510
551
|
);
|
|
511
552
|
},
|
|
512
553
|
|
|
513
|
-
|
|
554
|
+
async updateBranch(toUpdate, masterEntity, parentItem, operations) {
|
|
514
555
|
const { pluginName, itemModel, service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
515
556
|
const databaseModel = strapi.query(itemModel.modelName, pluginName);
|
|
516
557
|
return Promise.all(
|
|
@@ -519,21 +560,13 @@ module.exports = {
|
|
|
519
560
|
const { id, updated, parent, master, related, items, ...params } = item;
|
|
520
561
|
let currentItem;
|
|
521
562
|
if (updated) {
|
|
522
|
-
const
|
|
523
|
-
isNil(related) || params.type === itemType.EXTERNAL
|
|
524
|
-
? []
|
|
525
|
-
: related;
|
|
526
|
-
await databaseModel
|
|
527
|
-
.update(
|
|
528
|
-
{ id },
|
|
529
|
-
{ related: [] },
|
|
530
|
-
); // clearing the relation to get it updated properly and not duplicate _morph records
|
|
563
|
+
const relatedItems = await this.getIdsRelated(related, master);
|
|
531
564
|
currentItem = await databaseModel
|
|
532
565
|
.update(
|
|
533
566
|
{ id },
|
|
534
567
|
{
|
|
535
568
|
...params,
|
|
536
|
-
related:
|
|
569
|
+
related: relatedItems,
|
|
537
570
|
master: masterEntity,
|
|
538
571
|
parent: parentItem ? { ...parentItem, _id: parentItem.id } : null,
|
|
539
572
|
},
|
|
@@ -552,7 +585,7 @@ module.exports = {
|
|
|
552
585
|
}),
|
|
553
586
|
);
|
|
554
587
|
},
|
|
555
|
-
getBranchName
|
|
588
|
+
getBranchName(item) {
|
|
556
589
|
const hasId = !isNil(item.id);
|
|
557
590
|
const toRemove = item.removed;
|
|
558
591
|
if (hasId && !toRemove) {
|
|
@@ -566,7 +599,7 @@ module.exports = {
|
|
|
566
599
|
}
|
|
567
600
|
},
|
|
568
601
|
|
|
569
|
-
analyzeBranch
|
|
602
|
+
analyzeBranch(items = [], masterEntity = null, parentItem = null, prevOperations = {}) {
|
|
570
603
|
const { service } = utilsFunctions.extractMeta(strapi.plugins);
|
|
571
604
|
const { toCreate, toRemove, toUpdate } = items
|
|
572
605
|
.reduce((acc, _) => {
|
|
@@ -593,7 +626,96 @@ module.exports = {
|
|
|
593
626
|
));
|
|
594
627
|
},
|
|
595
628
|
|
|
596
|
-
|
|
629
|
+
async getRelatedItems(entityItems) {
|
|
630
|
+
const relatedTypes = new Set(entityItems.flatMap((item) => map(item.related, 'relatedType')));
|
|
631
|
+
const groupedItems = Array.from(relatedTypes).reduce(
|
|
632
|
+
(acc, relatedType) => Object.assign(acc, {
|
|
633
|
+
[relatedType]: [
|
|
634
|
+
...(acc[relatedType] || []),
|
|
635
|
+
...entityItems
|
|
636
|
+
.filter((item => item?.related.some(related => related.relatedType === relatedType)))
|
|
637
|
+
.flatMap((item) => item.related.map(related => Object.assign(related, { navigationItemId: item.id }))),
|
|
638
|
+
],
|
|
639
|
+
}),
|
|
640
|
+
{});
|
|
641
|
+
|
|
642
|
+
const data = new Map(
|
|
643
|
+
(
|
|
644
|
+
await Promise.all(
|
|
645
|
+
Object.entries(groupedItems)
|
|
646
|
+
.map(async ([model, related]) => {
|
|
647
|
+
const relationData = await strapi.query(model).find({ id_in: map(related, 'relatedId') });
|
|
648
|
+
return relationData
|
|
649
|
+
.flatMap(_ =>
|
|
650
|
+
Object.assign(
|
|
651
|
+
_,
|
|
652
|
+
{
|
|
653
|
+
__contentType: model,
|
|
654
|
+
navigationItemId: related.find(
|
|
655
|
+
({ relatedId }) => relatedId === _.id.toString())?.navigationItemId,
|
|
656
|
+
},
|
|
657
|
+
),
|
|
658
|
+
);
|
|
659
|
+
}),
|
|
660
|
+
)
|
|
661
|
+
)
|
|
662
|
+
.flat(1)
|
|
663
|
+
.map(_ => [_.navigationItemId, _]),
|
|
664
|
+
);
|
|
665
|
+
return entityItems
|
|
666
|
+
.map(({ related, ...item }) => {
|
|
667
|
+
const relatedData = data.get(item.id);
|
|
668
|
+
if (relatedData) {
|
|
669
|
+
return Object.assign(item, { related: [relatedData] });
|
|
670
|
+
}
|
|
671
|
+
return item;
|
|
672
|
+
});
|
|
673
|
+
},
|
|
674
|
+
|
|
675
|
+
getIdsRelated(relatedItems, master) {
|
|
676
|
+
if (relatedItems) {
|
|
677
|
+
return Promise.all(relatedItems.map(async relatedItem => {
|
|
678
|
+
try {
|
|
679
|
+
const query = {
|
|
680
|
+
related_id: relatedItem.refId,
|
|
681
|
+
related_type: relatedItem.ref,
|
|
682
|
+
field: relatedItem.field,
|
|
683
|
+
master,
|
|
684
|
+
};
|
|
685
|
+
const model = strapi.query('navigations_items_related', 'navigation');
|
|
686
|
+
const entity = await model
|
|
687
|
+
.findOne(query);
|
|
688
|
+
if (!entity) {
|
|
689
|
+
const newEntity = {
|
|
690
|
+
master,
|
|
691
|
+
order: 1,
|
|
692
|
+
field: relatedItem.field,
|
|
693
|
+
related_id: relatedItem.refId,
|
|
694
|
+
related_type: relatedItem.ref,
|
|
695
|
+
};
|
|
696
|
+
return model.create(newEntity).then(({ id }) => id);
|
|
697
|
+
}
|
|
698
|
+
return entity.id;
|
|
699
|
+
} catch (e) {
|
|
700
|
+
console.error(e);
|
|
701
|
+
}
|
|
702
|
+
}));
|
|
703
|
+
}
|
|
704
|
+
},
|
|
705
|
+
|
|
706
|
+
removeRelated(relatedItems, master) {
|
|
707
|
+
return Promise.all(relatedItems.map(relatedItem => {
|
|
708
|
+
const model = strapi.query('navigations_items_related', 'navigation');
|
|
709
|
+
const entityToRemove = {
|
|
710
|
+
master,
|
|
711
|
+
field: relatedItem.field,
|
|
712
|
+
related_id: relatedItem.refId,
|
|
713
|
+
related_type: relatedItem.ref,
|
|
714
|
+
};
|
|
715
|
+
return model.delete(entityToRemove).then(({ id }) => id);
|
|
716
|
+
}));
|
|
717
|
+
},
|
|
718
|
+
sanitizeTreeStructure(entity) {
|
|
597
719
|
const { masterModel, itemModel } = utilsFunctions.extractMeta(strapi.plugins);
|
|
598
720
|
return sanitizeEntity(
|
|
599
721
|
{
|