strapi-plugin-navigation 2.0.0 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -5
- package/__mocks__/strapi.js +30 -19
- package/admin/src/components/ConfirmationDialog/index.js +56 -0
- package/admin/src/components/Item/ItemCardBadge/index.js +1 -1
- package/admin/src/components/Item/ItemCardHeader/index.js +6 -12
- package/admin/src/components/Item/index.js +8 -10
- package/admin/src/components/RestartAlert/index.js +8 -0
- package/admin/src/hooks/useAllContentTypes.js +13 -0
- package/admin/src/hooks/useNavigationConfig.js +58 -0
- package/admin/src/index.js +24 -1
- package/admin/src/pages/SettingsPage/index.js +311 -0
- package/admin/src/pages/View/components/NavigationItemForm/index.js +36 -9
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +3 -6
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +2 -4
- package/admin/src/pages/View/components/NavigationItemPopup/index.js +2 -4
- package/admin/src/translations/en.json +48 -8
- package/admin/src/translations/fr.json +4 -4
- package/admin/src/utils/api.js +51 -0
- package/admin/src/utils/index.js +20 -0
- package/package.json +5 -5
- package/server/bootstrap.js +30 -1
- package/server/controllers/navigation.js +30 -5
- package/server/graphql/index.js +3 -4
- package/server/graphql/queries/render-navigation.js +4 -3
- package/server/graphql/types/content-types-name-fields.js +4 -2
- package/server/graphql/types/navigation-related.js +2 -2
- package/server/routes/admin.js +24 -1
- package/server/services/__tests__/functions.test.js +48 -0
- package/server/services/__tests__/navigation.test.js +26 -4
- package/server/services/navigation.js +56 -16
- package/server/services/utils/functions.js +41 -0
- package/strapi-server.js +0 -2
- package/yarn-error.log +5263 -0
- package/.circleci/config.yml +0 -48
- package/.eslintrc +0 -35
- package/.github/pull_request_template.md +0 -13
- package/.github/stale.yml +0 -15
- package/.nvmrc +0 -1
- package/codecov.yml +0 -3
- package/public/assets/logo.png +0 -0
- package/public/assets/preview.png +0 -0
- package/server/register.js +0 -5
package/README.md
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
<a href="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation">
|
|
17
17
|
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=master" alt="codecov.io" />
|
|
18
18
|
</a>
|
|
19
|
+
<a href="https://sharing.clickup.com/tl/xhcmx-43/strapiv-4-navigation-roadmap">
|
|
20
|
+
<img src="https://img.shields.io/website?down_message=roadmap&label=product&up_message=roadmap&url=https%3A%2F%2Fsharing.clickup.com%2Ftl%2Fxhcmx-43%2Fstrapiv-4-navigation-roadmap" />
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://sharing.clickup.com/b/6-169004201-2/strapiv-4-navigation-board">
|
|
23
|
+
<img src="https://img.shields.io/website?down_message=board&label=product&up_color=blue&up_message=board&url=https%3A%2F%2Fsharing.clickup.com%2Fb%2F6-169004201-2%2Fstrapiv-4-navigation-board" />
|
|
24
|
+
</a>
|
|
19
25
|
</div>
|
|
20
26
|
|
|
21
27
|
---
|
|
@@ -35,10 +41,10 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
|
|
|
35
41
|
- **Navigation Public API:** Simple and ready for use API endpoint for consuming the navigation structure you've created
|
|
36
42
|
- **Visual builder:** Elegant and easy to use visual builder
|
|
37
43
|
- **Any Content Type relation:** Navigation can by linked to any of your Content Types by default. Simply, you're controlling it and also limiting available content types by configuration props
|
|
44
|
+
- **Multiple navigations:** Create as many Navigation containers as you want, setup them and use in the consumer application
|
|
38
45
|
- **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
|
|
39
46
|
- **[Audit log](https://github.com/VirtusLab/strapi-molecules/tree/master/packages/strapi-plugin-audit-log):** integration with Strapi Molecules Audit Log plugin that provides changes track record
|
|
40
47
|
|
|
41
|
-
|
|
42
48
|
## ⚙️ Versions
|
|
43
49
|
|
|
44
50
|
- **Strapi v4** - (current) - [v2.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
|
|
@@ -75,7 +81,7 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
75
81
|
|
|
76
82
|
**Supported Strapi versions**:
|
|
77
83
|
|
|
78
|
-
- Strapi v4.0
|
|
84
|
+
- Strapi v4.1.0 (recently tested)
|
|
79
85
|
- Strapi v4.x
|
|
80
86
|
|
|
81
87
|
> This plugin is designed for **Strapi v4** and is not working with v3.x. To get version for **Strapi v3** install version [v1.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/strapi-v3).
|
|
@@ -83,7 +89,20 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
83
89
|
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
84
90
|
|
|
85
91
|
## 🔧 Configuration
|
|
86
|
-
|
|
92
|
+
|
|
93
|
+
### In `v2.0.3` and newer
|
|
94
|
+
|
|
95
|
+
Version `2.0.3` introduces the intuitive **Settings** page which you can easily access via `Strapi Settings -> Section: Navigation Plugin -> Configuration`. On the dedicated page, you will be able to set up all crucial properties which drive the plugin and customize each individual collection for which **Navigation plugin** should be enabled.
|
|
96
|
+
|
|
97
|
+
> *Note*
|
|
98
|
+
> The default configuration for your plugin is fetched from `config/plugins.js` or, if the file is not there, directly from the plugin itself. If you would like to customize the default state to which you might revert, please follow the next section.
|
|
99
|
+
|
|
100
|
+
### In `v2.0.2` and older + default configuration state for `v2.0.3` and newer
|
|
101
|
+
|
|
102
|
+
Config for this plugin is stored as a part of the `config/plugins.js` or `config/<env>/plugins.js` file. You can use the following snippet to make sure that the config structure is correct. If you've got already configurations for other plugins stores by this way, you can use the `navigation` along with them.
|
|
103
|
+
|
|
104
|
+
> *Note v2.0.3 and newer only*
|
|
105
|
+
> Changing this file will not automatically change plugin configuration. To synchronize plugin's config with plugins.js file, it is necessary to restore configuration through the settings page
|
|
87
106
|
|
|
88
107
|
```js
|
|
89
108
|
module.exports = ({ env }) => ({
|
|
@@ -105,13 +124,16 @@ Config for this plugin is stored as a part of `config/plugins.js` or `config/<en
|
|
|
105
124
|
|
|
106
125
|
### Properties
|
|
107
126
|
- `additionalFields` - Additional fields: 'audience', more in the future
|
|
108
|
-
- `allowedLevels` - Maximum level for which
|
|
127
|
+
- `allowedLevels` - Maximum level for which you're able to mark item as "Menu attached"
|
|
109
128
|
- `contentTypes` - UIDs of related content types
|
|
110
129
|
- `contentTypesNameFields` - Definition of content type title fields like `'api::<collection name>.<content type name>': ['field_name_1', 'field_name_2']`, if not set titles are pulled from fields like `['title', 'subject', 'name']`. **TIP** - Proper content type uid you can find in the URL of Content Manager where you're managing relevant entities like: `admin/content-manager/collectionType/< THE UID HERE >?page=1&pageSize=10&sort=Title:ASC&plugins[i18n][locale]=en`
|
|
111
130
|
- `gql` - If you're using GraphQL that's the right place to put all necessary settings. More **[ here ](#gql-configuration)**
|
|
112
131
|
|
|
113
132
|
## 🔧 GQL Configuration
|
|
114
|
-
Using navigation with GraphQL requires both plugins to be installed and working. You can find
|
|
133
|
+
Using navigation with GraphQL requires both plugins to be installed and working. You can find installation guide for GraphQL plugin **[here](https://docs.strapi.io/developer-docs/latest/plugins/graphql.html#graphql)**. To properly configure GQL to work with navigation you should provide `gql` prop. This should contain union types that will be used to define GQL response format for your data while fetching:
|
|
134
|
+
|
|
135
|
+
> **Important!**
|
|
136
|
+
> If you're using `config/plugins.js` to configure your plugins , please put `navigation` property before `graphql`. Otherwise types are not going to be properly added to GraphQL Schema. That's because of dynamic types which base on plugin configuration which are added on `bootstrap` stage, not `register`. This is not valid if you're using `graphql` plugin without any custom configuration, so most of cases in real.
|
|
115
137
|
|
|
116
138
|
```gql
|
|
117
139
|
master: Int
|
|
@@ -211,6 +233,20 @@ For any role different than **Super Admin**, to access the **Navigation panel**
|
|
|
211
233
|
|
|
212
234
|
## 🕸️ Public API specification
|
|
213
235
|
|
|
236
|
+
### Query Params
|
|
237
|
+
|
|
238
|
+
- `type` - Enum value representing structure type of returned navigation
|
|
239
|
+
|
|
240
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?type=FLAT`
|
|
241
|
+
|
|
242
|
+
- `menu` - Boolean value for querying only navigation items that are attached to menu should be rendered eg.
|
|
243
|
+
|
|
244
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?menu=true`
|
|
245
|
+
|
|
246
|
+
- `path` - String value for querying navigation items by its path
|
|
247
|
+
|
|
248
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?path=/home/about-us`
|
|
249
|
+
|
|
214
250
|
### Render
|
|
215
251
|
|
|
216
252
|
`GET <host>/api/navigation/render/<idOrSlug>?type=<type>`
|
|
@@ -389,6 +425,15 @@ Live example of plugin usage can be found in the [VirtusLab Strapi Examples](htt
|
|
|
389
425
|
|
|
390
426
|
## 🤝 Contributing
|
|
391
427
|
|
|
428
|
+
<div>
|
|
429
|
+
<a href="https://sharing.clickup.com/tl/xhcmx-43/strapiv-4-navigation-roadmap">
|
|
430
|
+
<img src="https://img.shields.io/website?down_message=roadmap&label=product&up_message=roadmap&url=https%3A%2F%2Fsharing.clickup.com%2Ftl%2Fxhcmx-43%2Fstrapiv-4-navigation-roadmap" />
|
|
431
|
+
</a>
|
|
432
|
+
<a href="https://sharing.clickup.com/b/6-169004201-2/strapiv-4-navigation-board">
|
|
433
|
+
<img src="https://img.shields.io/website?down_message=board&label=product&up_color=blue&up_message=board&url=https%3A%2F%2Fsharing.clickup.com%2Fb%2F6-169004201-2%2Fstrapiv-4-navigation-board" />
|
|
434
|
+
</a>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
392
437
|
Feel free to fork and make a Pull Request to this plugin project. All the input is warmly welcome!
|
|
393
438
|
|
|
394
439
|
## 👨💻 Community support
|
package/__mocks__/strapi.js
CHANGED
|
@@ -44,18 +44,18 @@ const itemModelMock = {
|
|
|
44
44
|
},
|
|
45
45
|
parent: null,
|
|
46
46
|
}),
|
|
47
|
-
findMany: async ({where}) => [{
|
|
47
|
+
findMany: async ({ where }) => [{
|
|
48
48
|
id: 1,
|
|
49
49
|
title: "home",
|
|
50
50
|
type: "INTERNAL",
|
|
51
|
-
path: "
|
|
51
|
+
path: "home",
|
|
52
52
|
externalPath: null,
|
|
53
53
|
uiRouterKey: "home",
|
|
54
54
|
menuAttached: true,
|
|
55
55
|
order: 1,
|
|
56
56
|
createdAt: "2021-12-31T10:04:54.812Z",
|
|
57
57
|
updatedAt: "2022-01-14T13:36:29.430Z",
|
|
58
|
-
master: 1,
|
|
58
|
+
master: 1,
|
|
59
59
|
related: {
|
|
60
60
|
id: 1,
|
|
61
61
|
related_id: "1",
|
|
@@ -117,22 +117,22 @@ const pageModelMock = {
|
|
|
117
117
|
}
|
|
118
118
|
}),
|
|
119
119
|
findMany: async ({ where }) => [{
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
120
|
+
"id": 1,
|
|
121
|
+
"attributes": {
|
|
122
|
+
"title": "Page nr 1",
|
|
123
|
+
"createdAt": "2022-01-19T08:22:31.244Z",
|
|
124
|
+
"updatedAt": "2022-01-19T08:22:31.244Z",
|
|
125
|
+
"publishedAt": null
|
|
126
|
+
}
|
|
127
|
+
}, {
|
|
128
|
+
"id": 2,
|
|
129
|
+
"attributes": {
|
|
130
|
+
"title": "Page nr 2",
|
|
131
|
+
"createdAt": "2022-01-19T08:22:50.821Z",
|
|
132
|
+
"updatedAt": "2022-01-19T08:22:50.821Z",
|
|
133
|
+
"publishedAt": null
|
|
134
|
+
}
|
|
135
|
+
}]
|
|
136
136
|
|
|
137
137
|
};
|
|
138
138
|
|
|
@@ -186,6 +186,17 @@ const strapiFactory = (plugins, contentTypes) => ({
|
|
|
186
186
|
findMany: () => [],
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
},
|
|
190
|
+
store: ({ type, name }) => {
|
|
191
|
+
if (type === 'plugin' && name === 'navigation') {
|
|
192
|
+
return {
|
|
193
|
+
get: ({ key }) => key === 'config' ? {
|
|
194
|
+
...require('../server/config').default,
|
|
195
|
+
contentTypes: ['api::pages.pages']
|
|
196
|
+
} : null,
|
|
197
|
+
set: () => null,
|
|
198
|
+
}
|
|
199
|
+
}
|
|
189
200
|
}
|
|
190
201
|
});
|
|
191
202
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Entity Details
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { Button } from '@strapi/design-system/Button';
|
|
10
|
+
import { Dialog, DialogBody, DialogFooter } from '@strapi/design-system/Dialog';
|
|
11
|
+
import { Flex } from '@strapi/design-system/Flex';
|
|
12
|
+
import { Stack } from '@strapi/design-system/Stack';
|
|
13
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
14
|
+
import { ExclamationMarkCircle, Check } from '@strapi/icons';
|
|
15
|
+
import { getMessage } from '../../utils';
|
|
16
|
+
|
|
17
|
+
const ConfirmationDialog = ({
|
|
18
|
+
isVisible = false,
|
|
19
|
+
isActionAsync = false,
|
|
20
|
+
children,
|
|
21
|
+
onConfirm,
|
|
22
|
+
onCancel,
|
|
23
|
+
header,
|
|
24
|
+
labelCancel,
|
|
25
|
+
labelConfirm,
|
|
26
|
+
iconConfirm
|
|
27
|
+
}) => (
|
|
28
|
+
<Dialog onClose={onCancel} title={header || getMessage('components.confirmation.dialog.header', 'Confirmation')} isOpen={isVisible}>
|
|
29
|
+
<DialogBody icon={<ExclamationMarkCircle />}>
|
|
30
|
+
<Stack size={2}>
|
|
31
|
+
<Flex justifyContent="center">
|
|
32
|
+
<Typography id="dialog-confirm-description">{children || getMessage('components.confirmation.dialog.description')}</Typography>
|
|
33
|
+
</Flex>
|
|
34
|
+
</Stack>
|
|
35
|
+
</DialogBody>
|
|
36
|
+
<DialogFooter startAction={<Button onClick={onCancel} variant="tertiary" disabled={isActionAsync}>
|
|
37
|
+
{labelCancel || getMessage('components.confirmation.dialog.button.cancel', 'Cancel')}
|
|
38
|
+
</Button>} endAction={<Button onClick={onConfirm} variant="danger-light" startIcon={iconConfirm || <Check />} disabled={isActionAsync}>
|
|
39
|
+
{labelConfirm || getMessage('components.confirmation.dialog.button.confirm', 'Confirm')}
|
|
40
|
+
</Button>} />
|
|
41
|
+
</Dialog>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
ConfirmationDialog.propTypes = {
|
|
45
|
+
isVisible: PropTypes.bool,
|
|
46
|
+
isActionAsync: PropTypes.bool,
|
|
47
|
+
children: PropTypes.string.isRequired,
|
|
48
|
+
header: PropTypes.string,
|
|
49
|
+
labelCancel: PropTypes.string,
|
|
50
|
+
labelConfirm: PropTypes.string,
|
|
51
|
+
iconConfirm: PropTypes.object,
|
|
52
|
+
onConfirm: PropTypes.func.isRequired,
|
|
53
|
+
onCancel: PropTypes.func.isRequired,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default ConfirmationDialog;
|
|
@@ -5,7 +5,7 @@ const ItemCardBadge = styled(Badge)`
|
|
|
5
5
|
border: 1px solid ${({ theme, borderColor }) => theme.colors[borderColor]};
|
|
6
6
|
|
|
7
7
|
${ props => props.small && `
|
|
8
|
-
padding:
|
|
8
|
+
padding: ${props.theme.spaces[1]};
|
|
9
9
|
margin: 0px ${props.theme.spaces[3]};
|
|
10
10
|
vertical-align: middle;
|
|
11
11
|
|
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl';
|
|
3
2
|
|
|
4
3
|
import { Flex } from '@strapi/design-system/Flex';
|
|
5
4
|
import { IconButton } from '@strapi/design-system/IconButton';
|
|
6
5
|
import { Typography } from '@strapi/design-system/Typography';
|
|
7
6
|
import { Icon } from '@strapi/design-system/Icon';
|
|
8
|
-
import
|
|
9
|
-
import TrashIcon from '@strapi/icons/Trash';
|
|
10
|
-
import RefreshIcon from '@strapi/icons/Refresh';
|
|
7
|
+
import { Pencil, Trash, Refresh } from '@strapi/icons/';
|
|
11
8
|
|
|
12
9
|
import Wrapper from './Wrapper';
|
|
13
10
|
import ItemCardBadge from '../ItemCardBadge';
|
|
14
|
-
import {
|
|
11
|
+
import { getMessage } from '../../../utils';
|
|
15
12
|
|
|
16
13
|
const ItemCardHeader = ({ title, path, icon, removed, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
17
|
-
|
|
18
|
-
const { formatMessage } = useIntl();
|
|
19
|
-
|
|
20
14
|
return (
|
|
21
15
|
<Wrapper>
|
|
22
16
|
<Flex alignItems="center">
|
|
@@ -35,14 +29,14 @@ const ItemCardHeader = ({ title, path, icon, removed, onItemRemove, onItemEdit,
|
|
|
35
29
|
backgroundColor={`danger100`}
|
|
36
30
|
textColor={`danger600`}
|
|
37
31
|
>
|
|
38
|
-
{
|
|
32
|
+
{getMessage("components.navigationItem.badge.removed")}
|
|
39
33
|
</ItemCardBadge>)
|
|
40
34
|
}
|
|
41
35
|
|
|
42
|
-
<IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<
|
|
36
|
+
<IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<Pencil />} />
|
|
43
37
|
{removed ?
|
|
44
|
-
<IconButton onClick={onItemRestore} label="Restore" icon={<
|
|
45
|
-
<IconButton onClick={onItemRemove} label="Remove" icon={<
|
|
38
|
+
<IconButton onClick={onItemRestore} label="Restore" icon={<Refresh />} /> :
|
|
39
|
+
<IconButton onClick={onItemRemove} label="Remove" icon={<Trash />} />
|
|
46
40
|
}
|
|
47
41
|
</Flex>
|
|
48
42
|
</Wrapper>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { isEmpty, isNumber
|
|
4
|
-
import { useIntl } from "react-intl";
|
|
3
|
+
import { isEmpty, isNumber } from 'lodash';
|
|
5
4
|
|
|
6
5
|
import { Box } from '@strapi/design-system/Box';
|
|
7
6
|
import { Card, CardBody } from '@strapi/design-system/Card';
|
|
@@ -10,17 +9,16 @@ import { Flex } from '@strapi/design-system/Flex';
|
|
|
10
9
|
import { Link } from '@strapi/design-system/Link';
|
|
11
10
|
import { TextButton } from '@strapi/design-system/TextButton';
|
|
12
11
|
import { Typography } from '@strapi/design-system/Typography';
|
|
13
|
-
|
|
14
12
|
import { ArrowRight, Link as LinkIcon, Earth, Plus } from '@strapi/icons';
|
|
15
13
|
|
|
16
14
|
import { navigationItemType } from '../../pages/View/utils/enums';
|
|
17
15
|
import ItemCardHeader from './ItemCardHeader';
|
|
18
16
|
import List from '../NavigationItemList';
|
|
19
17
|
import Wrapper from './Wrapper';
|
|
20
|
-
import { getTrad } from '../../translations';
|
|
21
18
|
import { extractRelatedItemLabel } from '../../pages/View/utils/parsers';
|
|
22
19
|
import ItemCardBadge from './ItemCardBadge';
|
|
23
20
|
import { ItemCardRemovedOverlay } from './ItemCardRemovedOverlay';
|
|
21
|
+
import { getMessage } from '../../utils';
|
|
24
22
|
|
|
25
23
|
const Item = (props) => {
|
|
26
24
|
const {
|
|
@@ -50,7 +48,6 @@ const Item = (props) => {
|
|
|
50
48
|
menuAttached,
|
|
51
49
|
} = item;
|
|
52
50
|
|
|
53
|
-
const { formatMessage } = useIntl();
|
|
54
51
|
const { contentTypes, contentTypesNameFields } = config;
|
|
55
52
|
const isExternal = type === navigationItemType.EXTERNAL;
|
|
56
53
|
const isPublished = relatedRef && relatedRef?.publishedAt;
|
|
@@ -97,7 +94,7 @@ const Item = (props) => {
|
|
|
97
94
|
onClick={(e) => onItemLevelAdd(e, viewId, isNextMenuAllowedLevel, absolutePath, menuAttached)}
|
|
98
95
|
>
|
|
99
96
|
<Typography variant="pi" fontWeight="bold" textColor={removed ? "neutral600" : "primary600"}>
|
|
100
|
-
{
|
|
97
|
+
{getMessage("components.navigationItem.action.newItem")}
|
|
101
98
|
</Typography>
|
|
102
99
|
</TextButton>
|
|
103
100
|
{ relatedItemLabel && (<Box>
|
|
@@ -108,9 +105,11 @@ const Item = (props) => {
|
|
|
108
105
|
className="action"
|
|
109
106
|
small
|
|
110
107
|
>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
{getMessage({
|
|
109
|
+
id: `components.navigationItem.badge.${isPublished ? 'published' : 'draft'}`, props: {
|
|
110
|
+
type: relatedTypeLabel
|
|
111
|
+
}
|
|
112
|
+
})}
|
|
114
113
|
</ItemCardBadge>
|
|
115
114
|
<Typography variant="pi" fontWeight="bold" textColor="neutral600">
|
|
116
115
|
{ relatedItemLabel }
|
|
@@ -150,7 +149,6 @@ Item.propTypes = {
|
|
|
150
149
|
uiRouterKey: PropTypes.string,
|
|
151
150
|
path: PropTypes.string,
|
|
152
151
|
externalPath: PropTypes.string,
|
|
153
|
-
audience: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
|
|
154
152
|
related: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
155
153
|
menuAttached: PropTypes.bool
|
|
156
154
|
}).isRequired,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useQuery } from 'react-query';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { fetchAllContentTypes } from '../utils/api';
|
|
4
|
+
|
|
5
|
+
const useAllContentTypes = () => {
|
|
6
|
+
const toggleNotification = useNotification();
|
|
7
|
+
const { isLoading, data } = useQuery('contentTypes', () =>
|
|
8
|
+
fetchAllContentTypes(toggleNotification)
|
|
9
|
+
);
|
|
10
|
+
return { data, isLoading, };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default useAllContentTypes;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useQuery, useQueryClient } from 'react-query';
|
|
2
|
+
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
import { fetchNavigationConfig, restartStrapi, restoreNavigationConfig, updateNavigationConfig } from '../utils/api';
|
|
4
|
+
import { getTrad } from '../translations';
|
|
5
|
+
|
|
6
|
+
const useNavigationConfig = () => {
|
|
7
|
+
const queryClient = useQueryClient();
|
|
8
|
+
const toggleNotification = useNotification();
|
|
9
|
+
const { isLoading, data, err } = useQuery('navigationConfig', () =>
|
|
10
|
+
fetchNavigationConfig(toggleNotification)
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const handleError = (type) => {
|
|
14
|
+
toggleNotification({
|
|
15
|
+
type: 'warning',
|
|
16
|
+
message: getTrad(`pages.settings.notification.${type}.error`),
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const handleSuccess = async (type) => {
|
|
21
|
+
await queryClient.invalidateQueries('navigationConfig');
|
|
22
|
+
toggleNotification({
|
|
23
|
+
type: 'success',
|
|
24
|
+
message: getTrad(`pages.settings.notification.${type}.success`),
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const submitMutation = async (...args) => {
|
|
29
|
+
try {
|
|
30
|
+
await updateNavigationConfig(...args);
|
|
31
|
+
await handleSuccess('submit');
|
|
32
|
+
} catch (e) {
|
|
33
|
+
handleError('submit');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const restoreMutation = async (...args) => {
|
|
38
|
+
try {
|
|
39
|
+
await restoreNavigationConfig(...args);
|
|
40
|
+
await handleSuccess('restore');
|
|
41
|
+
} catch (e) {
|
|
42
|
+
handleError('restore');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const restartMutation = async (...args) => {
|
|
47
|
+
try {
|
|
48
|
+
await restartStrapi(...args);
|
|
49
|
+
await handleSuccess('restart');
|
|
50
|
+
} catch (e) {
|
|
51
|
+
handleError('restart');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { data, isLoading, err, submitMutation, restoreMutation, restartMutation };
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default useNavigationConfig;
|
package/admin/src/index.js
CHANGED
|
@@ -3,11 +3,34 @@ import pluginPkg from '../../package.json';
|
|
|
3
3
|
import pluginId from './pluginId';
|
|
4
4
|
import pluginPermissions from './permissions';
|
|
5
5
|
import NavigationIcon from './components/icons/navigation';
|
|
6
|
-
|
|
6
|
+
import { getTrad } from './translations';
|
|
7
7
|
const name = pluginPkg.strapi.name;
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
10
|
register(app) {
|
|
11
|
+
app.createSettingSection(
|
|
12
|
+
{
|
|
13
|
+
id: pluginId,
|
|
14
|
+
intlLabel: { id: getTrad('pages.settings.section.title'), defaultMessage: 'Navigation Plugin' },
|
|
15
|
+
},
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
intlLabel: {
|
|
19
|
+
id: getTrad('pages.settings.section.subtitle'),
|
|
20
|
+
defaultMessage: 'Configuration',
|
|
21
|
+
},
|
|
22
|
+
id: 'navigation',
|
|
23
|
+
to: `/settings/${pluginId}`,
|
|
24
|
+
Component: async () => {
|
|
25
|
+
const component = await import(
|
|
26
|
+
/* webpackChunkName: "navigation-settings" */ './pages/SettingsPage'
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return component;
|
|
30
|
+
},
|
|
31
|
+
permissions: pluginPermissions.access,
|
|
32
|
+
}
|
|
33
|
+
]);
|
|
11
34
|
app.addMenuLink({
|
|
12
35
|
to: `/plugins/${pluginId}`,
|
|
13
36
|
icon: NavigationIcon,
|