strapi-plugin-navigation 2.0.9 → 2.0.12

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.
@@ -0,0 +1,8 @@
1
+ import styled from 'styled-components';
2
+ import { Alert } from '@strapi/design-system/Alert';
3
+
4
+ export const PermanentAlert = styled(Alert)`
5
+ button {
6
+ display: none;
7
+ }
8
+ `;
@@ -18,7 +18,7 @@ justify-content: center;
18
18
  height: ${32 / 16}rem;
19
19
  width: ${32 / 16}rem;
20
20
 
21
- cursor: pointer;
21
+ cursor: move;
22
22
  padding: ${({ theme }) => theme.spaces[2]};
23
23
  border-radius: ${({ theme }) => theme.borderRadius};
24
24
  background: ${({ theme }) => theme.colors.neutral0};
@@ -122,6 +122,13 @@ const Item = (props) => {
122
122
  previewRef: dragPreview(previewRef),
123
123
  }
124
124
 
125
+ const contentTypeUid = relatedRef?.__collectionUid;
126
+ const contentType = contentTypes.find(_ => _.uid === contentTypeUid) || {};
127
+ const generatePreviewUrl = entity => {
128
+ const { isSingle } = contentType;
129
+ return `/content-manager/${ isSingle ? 'singleType' : 'collectionType'}/${entity?.__collectionUid}${!isSingle ? '/' + entity?.id : ''}`
130
+ }
131
+
125
132
  return (
126
133
  <Wrapper level={level} isLast={isLast} style={{ opacity: isDragging ? 0.2 : 1 }} ref={refs ? refs.dropRef : null} >
127
134
  <Card style={{ width: "728px", zIndex: 1, position: "relative", overflow: 'hidden' }}>
@@ -179,9 +186,9 @@ const Item = (props) => {
179
186
  </ItemCardBadge>}
180
187
  <Typography variant="omega" textColor='neutral600'>{relatedTypeLabel}&nbsp;/&nbsp;</Typography>
181
188
  <Typography variant="omega" textColor='neutral800'>{relatedItemLabel}</Typography>
182
- <Link
183
- to={`/content-manager/collectionType/${relatedRef?.__collectionUid}/${relatedRef?.id}`}
184
- endIcon={<ArrowRight />}>&nbsp;</Link>
189
+ { contentType?.visible && (<Link
190
+ to={generatePreviewUrl(relatedRef)}
191
+ endIcon={<ArrowRight />}>&nbsp;</Link>) }
185
192
  </Flex>)
186
193
  }
187
194
  </Flex>
@@ -22,7 +22,7 @@ import { ToggleInput } from '@strapi/design-system/ToggleInput';
22
22
  import { NumberInput } from '@strapi/design-system/NumberInput';
23
23
  import { Select, Option } from '@strapi/design-system/Select';
24
24
  import { Tooltip } from '@strapi/design-system/Tooltip';
25
- import { Check, Refresh, Play, Information } from '@strapi/icons';
25
+ import { Check, Refresh, Play, Information, ExclamationMarkCircle } from '@strapi/icons';
26
26
 
27
27
  import permissions from '../../permissions';
28
28
  import useNavigationConfig from '../../hooks/useNavigationConfig';
@@ -31,6 +31,8 @@ import { navigationItemAdditionalFields } from '../View/utils/enums';
31
31
  import ConfirmationDialog from '../../components/ConfirmationDialog';
32
32
  import RestartAlert from '../../components/RestartAlert';
33
33
  import { getMessage } from '../../utils';
34
+ import { isContentTypeEligible, resolveGlobalLikeId } from './utils/functions';
35
+ import { PermanentAlert } from '../../components/Alert/styles';
34
36
 
35
37
  const SettingsPage = () => {
36
38
  const { lockApp, unlockApp } = useOverlayBlocker();
@@ -56,7 +58,7 @@ const SettingsPage = () => {
56
58
  additionalFields: audienceFieldChecked ? [navigationItemAdditionalFields.AUDIENCE] : [],
57
59
  allowedLevels: allowedLevels,
58
60
  gql: {
59
- navigationItemRelated: selectedContentTypes.map(uid => allContentTypes.find(ct => ct.uid === uid).info.displayName.replace(/\s+/g, ''))
61
+ navigationItemRelated: selectedContentTypes.map(uid => resolveGlobalLikeId(uid)),
60
62
  }
61
63
  });
62
64
 
@@ -108,8 +110,24 @@ const SettingsPage = () => {
108
110
  )
109
111
  }
110
112
 
111
- const allContentTypes = !isLoading && Object.values(allContentTypesData).filter(item => item.uid.includes('api::'));
112
- const selectedContentTypes = navigationConfigData?.contentTypes.map(item => item.uid);
113
+ const configContentTypes = navigationConfigData?.contentTypes || [];
114
+
115
+ const allContentTypes = !isLoading && Object.values(allContentTypesData).filter(({ uid }) => isContentTypeEligible(uid, {
116
+ allowedContentTypes: navigationConfigData?.allowedContentTypes,
117
+ restrictedContentTypes: navigationConfigData?.restrictedContentTypes,
118
+ })).map(ct => {
119
+ const type = configContentTypes.find(_ => _.uid === ct.uid);
120
+ if (type) {
121
+ const { available, isSingle } = type;
122
+ return {
123
+ ...ct,
124
+ available,
125
+ isSingle,
126
+ };
127
+ }
128
+ return ct;
129
+ });
130
+ const selectedContentTypes = configContentTypes.map(item => item.uid);
113
131
  const audienceFieldChecked = navigationConfigData?.additionalFields.includes(navigationItemAdditionalFields.AUDIENCE);
114
132
  const allowedLevels = navigationConfigData?.allowedLevels || 2;
115
133
  const nameFields = navigationConfigData?.contentTypesNameFields || {}
@@ -184,7 +202,7 @@ const SettingsPage = () => {
184
202
  <Information aria-hidden={true} />
185
203
  </Tooltip>}>
186
204
  {orderBy(values.selectedContentTypes).map(uid => {
187
- const { attributes, info: { displayName } } = allContentTypes.find(item => item.uid == uid);
205
+ const { attributes, info: { displayName }, available, isSingle } = allContentTypes.find(item => item.uid == uid);
188
206
  const stringAttributes = Object.keys(attributes).filter(_ => attributes[_].type === 'string');
189
207
  const relationAttributes = Object.keys(attributes).filter(_ => attributes[_].type === 'relation');
190
208
  const key = `collectionSettings-${uid}`;
@@ -194,10 +212,14 @@ const SettingsPage = () => {
194
212
  key={key}
195
213
  id={key}
196
214
  size="S">
197
- <AccordionToggle title={displayName} togglePosition="left" />
215
+ <AccordionToggle title={displayName} togglePosition="left" startIcon={(isSingle && !available) && (<ExclamationMarkCircle aria-hidden={true} />)} />
198
216
  <AccordionContent>
199
217
  <Box padding={6}>
200
218
  <Stack spacing={4}>
219
+ { (isSingle && !available) && (
220
+ <PermanentAlert title={getMessage('pages.settings.form.contentTypesSettings.initializationWarning.title')} variant="danger" onClose={(e) => e.preventDefault()}>
221
+ { getMessage('pages.settings.form.contentTypesSettings.initializationWarning.content') }
222
+ </PermanentAlert>)}
201
223
  <Select
202
224
  name={`collectionSettings-${uid}-entryLabel`}
203
225
  label={getMessage('pages.settings.form.nameField.label')}
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ const { capitalize } = require("lodash");
4
+
5
+ const UID_REGEX = /^(?<type>[a-z0-9-]+)\:{2}(?<api>[a-z0-9-]+)\.{1}(?<contentType>[a-z0-9-]+)$/i;
6
+
7
+ const splitTypeUid = (uid = '') => {
8
+ return uid.split(UID_REGEX).filter((s) => s && s.length > 0);
9
+ };
10
+
11
+ module.exports = {
12
+ resolveGlobalLikeId(uid = '') {
13
+ const parse = (str) => str.split('-')
14
+ .map(_ => capitalize(_))
15
+ .join('');
16
+
17
+ const [type, scope, contentTypeName] = splitTypeUid(uid);
18
+ if (type === 'api') {
19
+ return parse(contentTypeName);
20
+ }
21
+ return `${parse(scope)}${parse(contentTypeName)}`;
22
+ },
23
+
24
+ isContentTypeEligible(uid = '', config = {}) {
25
+ const { allowedContentTypes = [], restrictedContentTypes = []} = config;
26
+ const isOneOfAllowedType = allowedContentTypes.filter(_ => uid.includes(_) || (uid === _)).length > 0;
27
+ const isNoneOfRestricted = restrictedContentTypes.filter(_ => uid.includes(_) || (uid === _)).length === 0;
28
+ return uid && isOneOfAllowedType && isNoneOfRestricted;
29
+ },
30
+ }
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useMemo, useState, useCallback } from 'react';
2
- import { debounce, find, get, isEmpty, isEqual, isNil, isString } from 'lodash';
2
+ import { debounce, find, get, first, isEmpty, isEqual, isNil, isString } from 'lodash';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Formik } from 'formik'
5
5
  import slugify from 'slugify';
@@ -75,11 +75,11 @@ const NavigationItemForm = ({
75
75
 
76
76
  const sanitizePayload = (payload = {}) => {
77
77
  const { onItemClick, onItemLevelAddClick, related, relatedType, menuAttached, type, ...purePayload } = payload;
78
- const relatedId = related
78
+ const relatedId = related;
79
+ const singleRelatedItem = isSingleSelected ? first(contentTypeEntities) : undefined;
79
80
  const relatedCollectionType = relatedType;
80
- const title = isSingleSelected ?
81
- relatedTypeSelectOptions.find(v => v.key == relatedType).label :
82
- payload.title || relatedSelectOptions.find(v => v.key == relatedId)?.label;
81
+ const title = payload.title;
82
+
83
83
  return {
84
84
  ...purePayload,
85
85
  title,
@@ -90,6 +90,7 @@ const NavigationItemForm = ({
90
90
  related: type === navigationItemType.INTERNAL ? relatedId : undefined,
91
91
  relatedType: type === navigationItemType.INTERNAL ? relatedCollectionType : undefined,
92
92
  isSingle: isSingleSelected,
93
+ singleRelatedItem,
93
94
  uiRouterKey: generateUiRouterKey(title, relatedId, relatedCollectionType),
94
95
  };
95
96
  };
@@ -136,6 +137,7 @@ const NavigationItemForm = ({
136
137
  return undefined;
137
138
  };
138
139
 
140
+ const initialRelatedTypeSelected = data?.relatedType?.value;
139
141
  const relatedTypeSelectValue = form.relatedType;
140
142
  const relatedSelectValue = form.related;
141
143
 
@@ -221,6 +223,9 @@ const NavigationItemForm = ({
221
223
  () => contentTypes
222
224
  .filter((contentType) => {
223
225
  if (contentType.isSingle) {
226
+ if (relatedTypeSelectValue && [relatedTypeSelectValue, initialRelatedTypeSelected].includes(contentType.uid)) {
227
+ return true;
228
+ }
224
229
  return !usedContentTypesData.some((_) => _.__collectionUid === contentType.uid && _.__collectionUid !== form.relatedType);
225
230
  }
226
231
  return true;
@@ -236,7 +241,7 @@ const NavigationItemForm = ({
236
241
  value: get(item, 'uid'),
237
242
  label: get(item, 'label', get(item, 'name')),
238
243
  })),
239
- [contentTypes, usedContentTypesData],
244
+ [contentTypes, usedContentTypesData, relatedTypeSelectValue],
240
245
  );
241
246
 
242
247
  const thereAreNoMoreContentTypes = isEmpty(relatedSelectOptions) && !contentTypeSearchQuery;
@@ -25,6 +25,7 @@ export const transformItemToRESTPayload = (
25
25
  audience = [],
26
26
  items = [],
27
27
  collapsed,
28
+ isSingle
28
29
  } = item;
29
30
  const isExternal = type === navigationItemType.EXTERNAL;
30
31
  const isWrapper = type === navigationItemType.WRAPPER;
@@ -37,7 +38,7 @@ export const transformItemToRESTPayload = (
37
38
  find(contentTypes,
38
39
  ct => ct.uid === relatedType) :
39
40
  undefined;
40
- const itemAttachedToMenu = menuAttached && parentAttachedToMenu
41
+ const itemAttachedToMenu = menuAttached && parentAttachedToMenu;
41
42
  return {
42
43
  id,
43
44
  parent,
@@ -59,7 +60,7 @@ export const transformItemToRESTPayload = (
59
60
  ? undefined
60
61
  : [
61
62
  {
62
- refId: relatedId,
63
+ refId: isSingle && !relatedId ? 1 : relatedId,
63
64
  ref: relatedContentType ? relatedContentType.uid : relatedType,
64
65
  field: relatedContentType && relatedContentType.relatedField ? relatedContentType.relatedField : 'navigation',
65
66
  },
@@ -89,10 +90,12 @@ const linkRelations = (item, config) => {
89
90
 
90
91
  if (isSingle && relatedType) {
91
92
  const relatedContentType = contentTypes.find(_ => relatedType === _.uid) || {};
93
+ const { singleRelatedItem = {} } = item;
92
94
  return {
93
95
  ...item,
94
96
  relatedType,
95
97
  relatedRef: {
98
+ ...singleRelatedItem,
96
99
  ...omit(relatedContentType, 'collectionName'),
97
100
  isSingle,
98
101
  __collectionUid: relatedContentType.uid,
@@ -74,9 +74,9 @@
74
74
  "pages.settings.notification.submit.error": "Config update has failed",
75
75
  "pages.settings.notification.restore.error": "Config restore has failed",
76
76
  "pages.settings.notification.restart.error": "Failed to restart your application. Try to do it manually.",
77
- "pages.settings.form.contentTypes.label": "Enable for Collection(s)",
77
+ "pages.settings.form.contentTypes.label": "Enable navigation for",
78
78
  "pages.settings.form.contentTypes.placeholder": "eg. Pages, Posts",
79
- "pages.settings.form.contentTypes.hint": "Content types that can be related with navigation items. This configuration is applicable both for REST & GraphQL",
79
+ "pages.settings.form.contentTypes.hint": "If none is selected, also none of the content types are enabled",
80
80
  "pages.settings.form.allowedLevels.label": "Allowed levels",
81
81
  "pages.settings.form.allowedLevels.placeholder": "eg. 2",
82
82
  "pages.settings.form.allowedLevels.hint": "Maximum level for which you're able to mark item as \"Menu attached\"",
@@ -92,6 +92,8 @@
92
92
  "pages.settings.form.populate.empty": "This content type doesn't have any relation fields",
93
93
  "pages.settings.form.contentTypesSettings.label": "Content types",
94
94
  "pages.settings.form.contentTypesSettings.tooltip": "Custom configuration per content type",
95
+ "pages.settings.form.contentTypesSettings.initializationWarning.title": "Warning",
96
+ "pages.settings.form.contentTypesSettings.initializationWarning.content": "- Content Type hasn't yet been initialized. Initialize it first to be able to use in a Visual Editor.",
95
97
  "components.navigationItem.action.newItem": "Add nested item",
96
98
  "components.navigationItem.badge.removed": "Removed",
97
99
  "components.navigationItem.badge.draft": "Draft",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-navigation",
3
- "version": "2.0.9",
3
+ "version": "2.0.12",
4
4
  "description": "Strapi - Navigation plugin",
5
5
  "strapi": {
6
6
  "name": "navigation",
@@ -25,12 +25,20 @@ module.exports = ({strapi}) => ({
25
25
  },
26
26
 
27
27
  async updateConfig(ctx) {
28
- await getService().updateConfig(ctx.request.body)
28
+ try {
29
+ await getService().updateConfig(ctx.request.body);
30
+ } catch (e) {
31
+ errorHandler(ctx)(e);
32
+ }
29
33
  return ctx.send({ status: 200 });
30
34
  },
31
35
 
32
36
  async restoreConfig(ctx) {
33
- await getService().restoreConfig()
37
+ try {
38
+ await getService().restoreConfig();
39
+ } catch (e) {
40
+ errorHandler(ctx)(e);
41
+ }
34
42
  return ctx.send({ status: 200 })
35
43
  },
36
44
 
@@ -43,7 +51,7 @@ module.exports = ({strapi}) => ({
43
51
  await getService().restart();
44
52
  return ctx.send({ status: 200 });
45
53
  } catch (e) {
46
- errorHandler(ctx, e);
54
+ errorHandler(ctx)(e);
47
55
  }
48
56
  },
49
57
 
@@ -8,7 +8,9 @@ module.exports = ({ strapi, nexus, config }) => {
8
8
  definition(t) {
9
9
  t.members(...related)
10
10
  },
11
- resolveType: (item) => strapi.contentTypes[item.__contentType]?.globalId
11
+ resolveType: (item) => {
12
+ return strapi.contentTypes[item.__contentType]?.globalId
13
+ }
12
14
  });
13
15
  }
14
16
 
@@ -11,16 +11,14 @@ const {
11
11
  toNumber,
12
12
  isString,
13
13
  first,
14
-
15
14
  } = require('lodash');
16
15
  const { validate: isUuid } = require('uuid');
17
16
  const slugify = require('slugify');
18
- const { KIND_TYPES } = require('./utils/constant');
17
+ const { KIND_TYPES, ALLOWED_CONTENT_TYPES, RESTRICTED_CONTENT_TYPES } = require('./utils/constant');
19
18
  const utilsFunctionsFactory = require('./utils/functions');
20
19
  const { renderType } = require('../content-types/navigation/lifecycle');
21
20
  const { type: itemType, additionalFields: configAdditionalFields } = require('../content-types/navigation-item').lifecycle;
22
21
  const { NotFoundError } = require('@strapi/utils').errors
23
- const excludedContentTypes = ['strapi::'];
24
22
  const contentTypesNameFieldsDefaults = ['title', 'subject', 'name'];
25
23
 
26
24
  module.exports = ({ strapi }) => {
@@ -33,7 +31,7 @@ module.exports = ({ strapi }) => {
33
31
  const entities = await strapi
34
32
  .query(masterModel.uid)
35
33
  .findMany({
36
- limit: -1,
34
+ limit: Number.MAX_SAFE_INTEGER,
37
35
  });
38
36
  return entities;
39
37
  },
@@ -50,7 +48,7 @@ module.exports = ({ strapi }) => {
50
48
  where: {
51
49
  master: id,
52
50
  },
53
- limit: -1,
51
+ limit: Number.MAX_SAFE_INTEGER,
54
52
  sort: ['order:asc'],
55
53
  populate: ['related', 'parent', 'audience']
56
54
  });
@@ -67,8 +65,8 @@ module.exports = ({ strapi }) => {
67
65
 
68
66
  // Get plugin config
69
67
  async config(viaSettingsPage = false) {
70
- const { audienceModel, service } = utilsFunctions.extractMeta(strapi.plugins);
71
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
68
+ const { audienceModel } = utilsFunctions.extractMeta(strapi.plugins);
69
+ const pluginStore = await this.getPluginStore()
72
70
  const config = await pluginStore.get({ key: 'config' });
73
71
  const additionalFields = config.additionalFields;
74
72
  const contentTypesNameFields = config.contentTypesNameFields;
@@ -76,9 +74,12 @@ module.exports = ({ strapi }) => {
76
74
  const allowedLevels = config.allowedLevels;
77
75
  const isGQLPluginEnabled = !isNil(strapi.plugin('graphql'));
78
76
 
79
- let extendedResult = {};
77
+ let extendedResult = {
78
+ allowedContentTypes: ALLOWED_CONTENT_TYPES,
79
+ restrictedContentTypes: RESTRICTED_CONTENT_TYPES,
80
+ };
80
81
  const result = {
81
- contentTypes: await service.configContentTypes(),
82
+ contentTypes: await this.configContentTypes(viaSettingsPage),
82
83
  contentTypesNameFields: {
83
84
  default: contentTypesNameFieldsDefaults,
84
85
  ...(isObject(contentTypesNameFields) ? contentTypesNameFields : {}),
@@ -95,9 +96,7 @@ module.exports = ({ strapi }) => {
95
96
  const audienceItems = await strapi
96
97
  .query(audienceModel.uid)
97
98
  .findMany({
98
- paggination: {
99
- limit: -1,
100
- }
99
+ limit: Number.MAX_SAFE_INTEGER,
101
100
  });
102
101
  extendedResult = {
103
102
  ...extendedResult,
@@ -111,7 +110,7 @@ module.exports = ({ strapi }) => {
111
110
  },
112
111
 
113
112
  async updateConfig(newConfig) {
114
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
113
+ const pluginStore = await this.getPluginStore()
115
114
  await pluginStore.set({ key: 'config', value: newConfig });
116
115
  },
117
116
 
@@ -120,7 +119,7 @@ module.exports = ({ strapi }) => {
120
119
  },
121
120
 
122
121
  async setDefaultConfig() {
123
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
122
+ const pluginStore = await this.getPluginStore()
124
123
  const config = await pluginStore.get({ key: 'config' });
125
124
  const pluginDefaultConfig = await strapi.plugin('navigation').config
126
125
 
@@ -140,24 +139,22 @@ module.exports = ({ strapi }) => {
140
139
  },
141
140
 
142
141
  async restoreConfig() {
143
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
142
+ const pluginStore = await this.getPluginStore()
144
143
  await pluginStore.delete({ key: 'config' });
145
144
  await strapi.plugin('navigation').service('navigation').setDefaultConfig();
146
145
  },
147
146
 
148
- async configContentTypes() {
149
- const pluginStore = await strapi.plugin('navigation').service('navigation').getPluginStore()
147
+ async configContentTypes(viaSettingsPage = false) {
148
+ const pluginStore = await this.getPluginStore()
150
149
  const config = await pluginStore.get({ key: 'config' });
151
150
  const eligibleContentTypes =
152
151
  await Promise.all(
153
152
  config.contentTypes
154
- .filter(contentType => !!strapi.contentTypes[contentType])
153
+ .filter(contentType => !!strapi.contentTypes[contentType] && utilsFunctions.isContentTypeEligible(contentType))
155
154
  .map(
156
155
  async (key) => {
157
- if (find(excludedContentTypes, name => key.includes(name))) { // exclude internal content types
158
- return;
159
- }
160
156
  const item = strapi.contentTypes[key];
157
+
161
158
  const { kind, options, uid } = item;
162
159
  const { draftAndPublish } = options;
163
160
 
@@ -179,7 +176,9 @@ module.exports = ({ strapi }) => {
179
176
  return returnType(itemsCountOrBypass !== 0);
180
177
  }
181
178
  const isAvailable = await strapi.query(uid).count();
182
- return isAvailable === 1 ? returnType(true) : undefined;
179
+ return isAvailable === 1 ?
180
+ returnType(true) :
181
+ (viaSettingsPage ? returnType(false) : undefined);
183
182
  }
184
183
  return returnType(true);
185
184
  },
@@ -190,9 +189,10 @@ module.exports = ({ strapi }) => {
190
189
  .map(({ key, available }) => {
191
190
  const item = strapi.contentTypes[key];
192
191
  const relatedField = (item.associations || []).find(_ => _.model === 'navigationitem');
193
- const { uid, options, info, collectionName, modelName, apiName, plugin, kind } = item;
192
+ const { uid, options, info, collectionName, modelName, apiName, plugin, kind, pluginOptions } = item;
193
+ const { visible = true } = pluginOptions['content-manager'] || {};
194
194
  const { name, description } = info;
195
- const { isManaged, hidden, templateName } = options;
195
+ const { hidden, templateName } = options;
196
196
  const findRouteConfig = find(get(strapi.api, `[${modelName}].config.routes`, []),
197
197
  route => route.handler.includes('.find'));
198
198
  const findRoutePath = findRouteConfig && findRouteConfig.path.split('/')[1];
@@ -217,12 +217,12 @@ module.exports = ({ strapi }) => {
217
217
  labelSingular: utilsFunctions.singularize(labelSingular),
218
218
  endpoint,
219
219
  plugin,
220
- available,
221
- visible: (isManaged || isNil(isManaged)) && !hidden,
220
+ available: available && !hidden,
221
+ visible,
222
222
  templateName,
223
223
  };
224
224
  })
225
- .filter((item) => item && item.visible);
225
+ .filter((item) => viaSettingsPage || (item && item.available));
226
226
  },
227
227
 
228
228
  async getRelatedItems(entityItems) {
@@ -395,9 +395,7 @@ module.exports = ({ strapi }) => {
395
395
  master: entity.id,
396
396
  ...itemCriteria,
397
397
  },
398
- paggination: {
399
- limit: -1,
400
- },
398
+ limit: Number.MAX_SAFE_INTEGER,
401
399
  sort: ['order:asc'],
402
400
  populate: ['related', 'audience', 'parent'],
403
401
  });
@@ -424,6 +422,7 @@ module.exports = ({ strapi }) => {
424
422
  id: item.id,
425
423
  title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
426
424
  menuAttached: item.menuAttached,
425
+ order: item.order,
427
426
  path: isExternal ? item.externalPath : parentPath,
428
427
  type: item.type,
429
428
  uiRouterKey: item.uiRouterKey,
@@ -507,7 +506,10 @@ module.exports = ({ strapi }) => {
507
506
  .filter(utilsFunctions.filterOutUnpublished)
508
507
  .map(item => itemParser({
509
508
  ...item,
510
- }, path, field));
509
+ }, path, field))
510
+ .sort((x, y) => {
511
+ return x.order - y.order;
512
+ });
511
513
  },
512
514
 
513
515
  renderRFR({ items, parent = null, parentNavItem = null, contentTypes = [] }) {
@@ -768,7 +770,7 @@ module.exports = ({ strapi }) => {
768
770
  related_id: relatedItem.refId,
769
771
  related_type: relatedItem.ref,
770
772
  };
771
- return model.delete({ where: entityToRemove }).then(({ id }) => id);
773
+ return model.delete({ where: entityToRemove });
772
774
  }));
773
775
  },
774
776
 
@@ -8,5 +8,14 @@ module.exports = {
8
8
 
9
9
  MODEL_TYPES: {
10
10
  CONTENT_TYPE: 'contentType'
11
- }
11
+ },
12
+ ALLOWED_CONTENT_TYPES: [
13
+ 'api::',
14
+ 'plugin::'
15
+ ],
16
+ RESTRICTED_CONTENT_TYPES: [
17
+ 'plugin::users-permissions',
18
+ 'plugin::i18n.locale',
19
+ 'plugin::navigation',
20
+ ],
12
21
  };
@@ -13,7 +13,7 @@ const {
13
13
 
14
14
  const { type: itemType } = require('../../content-types/navigation-item/lifecycle');
15
15
  const { NavigationError } = require('../../../utils/NavigationError');
16
- const { TEMPLATE_DEFAULT } = require('./constant');
16
+ const { TEMPLATE_DEFAULT, ALLOWED_CONTENT_TYPES, RESTRICTED_CONTENT_TYPES } = require('./constant');
17
17
 
18
18
  module.exports = ({ strapi }) => {
19
19
  return {
@@ -216,5 +216,11 @@ module.exports = ({ strapi }) => {
216
216
  }
217
217
  return (item.type !== itemType.INTERNAL) || relatedItem;
218
218
  },
219
+
220
+ isContentTypeEligible(uid = '') {
221
+ const isOneOfAllowedType = ALLOWED_CONTENT_TYPES.filter(_ => uid.includes(_)).length > 0;
222
+ const isNoneOfRestricted = RESTRICTED_CONTENT_TYPES.filter(_ => uid.includes(_) || (uid === _)).length === 0;
223
+ return uid && isOneOfAllowedType && isNoneOfRestricted;
224
+ },
219
225
  };
220
226
  }