strapi-plugin-navigation 2.0.0-beta.1 → 2.0.0-beta.5
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 +62 -104
- package/admin/src/components/Item/ItemCardHeader/index.js +2 -2
- package/admin/src/components/Item/index.js +3 -1
- package/admin/src/components/NavigationItemList/index.js +2 -0
- package/admin/src/components/Search/index.js +49 -0
- package/admin/src/pages/DataManagerProvider/index.js +6 -9
- package/admin/src/pages/DataManagerProvider/reducer.js +58 -69
- package/admin/src/pages/View/index.js +16 -4
- package/admin/src/pages/View/utils/parsers.js +1 -1
- package/admin/src/pluginId.js +2 -2
- package/package.json +7 -3
- package/server/config/index.js +8 -0
- package/server/controllers/navigation.js +21 -0
- package/server/graphql/index.js +23 -0
- package/server/graphql/queries/index.js +17 -0
- package/server/graphql/queries/render-navigation-child.js +16 -0
- package/server/graphql/queries/render-navigation.js +15 -0
- package/server/graphql/resolvers-config.js +4 -0
- package/server/graphql/types/content-types-name-fields.js +8 -0
- package/server/graphql/types/content-types.js +16 -0
- package/server/graphql/types/create-navigation-item.js +17 -0
- package/server/graphql/types/create-navigation-related.js +8 -0
- package/server/graphql/types/create-navigation.js +7 -0
- package/server/graphql/types/index.js +15 -0
- package/server/graphql/types/navigation-config.js +9 -0
- package/server/graphql/types/navigation-details.js +10 -0
- package/server/graphql/types/navigation-item.js +29 -0
- package/server/graphql/types/navigation-related.js +23 -0
- package/server/graphql/types/navigation-render-type.js +4 -0
- package/server/graphql/types/navigation.js +9 -0
- package/server/register.js +5 -0
- package/server/routes/client.js +21 -0
- package/server/routes/index.js +2 -1
- package/server/services/navigation.js +272 -6
- package/server/services/utils/functions.js +84 -2
- package/strapi-server.js +3 -1
package/README.md
CHANGED
|
@@ -1,34 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<p
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>Strapi v4 - Navigation plugin - BETA</h1>
|
|
3
|
+
<p>Create consumable navigation with a simple and straigthforward visual builder.</p>
|
|
4
4
|
<a href="https://www.npmjs.org/package/strapi-plugin-navigation">
|
|
5
|
-
<img src="https://img.shields.io/
|
|
5
|
+
<img src="https://img.shields.io/github/package-json/v/VirtusLab-Open-Source/strapi-plugin-navigation/feat%252Fstrapi-v4-support?label=npm" alt="NPM Version" />
|
|
6
6
|
</a>
|
|
7
7
|
<a href="https://www.npmjs.org/package/strapi-plugin-navigation">
|
|
8
8
|
<img src="https://img.shields.io/npm/dm/strapi-plugin-navigation.svg" alt="Monthly download on NPM" />
|
|
9
9
|
</a>
|
|
10
10
|
<a href="https://circleci.com/gh/VirtusLab/strapi-plugin-navigation">
|
|
11
|
-
<img src="https://circleci.com/gh/VirtusLab/strapi-plugin-navigation.svg?style=shield" alt="CircleCI" />
|
|
11
|
+
<img src="https://circleci.com/gh/VirtusLab-Open-Source/strapi-plugin-navigation/tree/feat%2Fstrapi-v4-support.svg?style=shield" alt="CircleCI" />
|
|
12
12
|
</a>
|
|
13
13
|
<a href="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation">
|
|
14
|
-
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=
|
|
14
|
+
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=feat%2Fstrapi-v4-support" alt="codecov.io" />
|
|
15
15
|
</a>
|
|
16
|
-
</
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Strapi Navigation Plugin provides a website navigation / menu builder feature for [Strapi Headless CMS](https://github.com/strapi/strapi) admin panel. Navigation has the possibility to control the audience and can be consumed by the website with different output structure renderers:
|
|
19
21
|
|
|
20
22
|
- Flat
|
|
21
23
|
- Tree (nested)
|
|
22
24
|
- RFR (ready for handling by Redux First Router)
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
## ✨ Features
|
|
27
|
+
|
|
28
|
+
- **Navigation Public API:** Simple and ready for use API endpoint for consuming the navigation structure you've created
|
|
29
|
+
- **Visual builder:** Elegant and easy to use visual builder
|
|
30
|
+
- **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
|
|
31
|
+
- **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
|
|
32
|
+
- **[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
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## ⚙️ Versions
|
|
25
36
|
|
|
26
37
|
- **Stable** - [v1.1.2](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
|
|
27
38
|
- **Beta** - v4 support - [v2.0.0-beta.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/feat/strapi-v4-support)
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
## ⏳ Installation
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
It's recommended to use **yarn** to install this plugin within your Strapi project. [You can install yarn with these docs](https://yarnpkg.com/lang/en/docs/install/).
|
|
32
43
|
|
|
33
44
|
```bash
|
|
34
45
|
yarn add strapi-plugin-navigation@latest
|
|
@@ -49,87 +60,53 @@ yarn develop --watch-admin
|
|
|
49
60
|
|
|
50
61
|
The **UI Navigation** plugin should appear in the **Plugins** section of Strapi sidebar after you run app again.
|
|
51
62
|
|
|
52
|
-
|
|
53
63
|
Enjoy 🎉
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
## 🖐 Requirements
|
|
56
66
|
|
|
57
|
-
Complete installation requirements are exact same as for Strapi itself and can be found in the documentation under <a href="https://strapi.io/
|
|
67
|
+
Complete installation requirements are exact same as for Strapi itself and can be found in the documentation under <a href="https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/installation/cli.html#preparing-the-installation">Installation Requirements</a>.
|
|
58
68
|
|
|
59
69
|
**Supported Strapi versions**:
|
|
60
70
|
|
|
61
|
-
- Strapi v4.0.
|
|
62
|
-
|
|
63
|
-
(This plugin is not working with v3.x and not may work with the older Strapi v4 versions, but these are not tested nor officially supported at this time.)
|
|
64
|
-
|
|
65
|
-
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
66
|
-
|
|
67
|
-
## Features
|
|
68
|
-
|
|
69
|
-
- **Navigation Public API:** Simple and ready for use API endpoint for getting the navigation structure you've created
|
|
70
|
-
- **Visual builder:** Elegant and easy to use visual builder
|
|
71
|
-
- **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
|
|
72
|
-
- **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
|
|
73
|
-
- **[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
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
## Content Type model relation to Navigation Item
|
|
77
|
-
|
|
78
|
-
To enable Content Type to work with Navigation Item, you've to add following field to your model `*.settings.json`:
|
|
71
|
+
- Strapi v4.0.5 (recently tested)
|
|
72
|
+
- Strapi v4.x
|
|
79
73
|
|
|
80
|
-
|
|
81
|
-
"navigation": {
|
|
82
|
-
"model": "navigationitem",
|
|
83
|
-
"plugin": "navigation",
|
|
84
|
-
"via": "related",
|
|
85
|
-
"configurable": false,
|
|
86
|
-
"hidden": true
|
|
87
|
-
}
|
|
88
|
-
```
|
|
74
|
+
_This plugin is not working with v3.x._
|
|
89
75
|
|
|
90
|
-
|
|
76
|
+
It may or may not work with the older Strapi v4 versions, these are not tested nor officially supported at this time.
|
|
91
77
|
|
|
92
|
-
|
|
93
|
-
"attributes": {
|
|
94
|
-
...,
|
|
95
|
-
"navigation": {
|
|
96
|
-
"model": "navigationitem",
|
|
97
|
-
"plugin": "navigation",
|
|
98
|
-
"via": "related",
|
|
99
|
-
"configurable": false,
|
|
100
|
-
"hidden": true
|
|
101
|
-
},
|
|
102
|
-
...
|
|
103
|
-
},
|
|
104
|
-
```
|
|
78
|
+
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
105
79
|
|
|
106
|
-
## Configuration
|
|
107
|
-
|
|
80
|
+
## 🔧 Configuration
|
|
81
|
+
Config for this plugin is stored as a part of `config/plugins.js` or `config/<env>/plugins.js` file. You can use 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.
|
|
108
82
|
|
|
109
83
|
```js
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
84
|
+
module.exports = ({ env }) => ({
|
|
85
|
+
// ...
|
|
86
|
+
navigation: {
|
|
87
|
+
enabled: true,
|
|
88
|
+
config: {
|
|
89
|
+
additionalFields: ['audience'],
|
|
90
|
+
contentTypes: ['api::page.page'],
|
|
91
|
+
contentTypesNameFields: {
|
|
92
|
+
'api::page.page': ['title']
|
|
93
|
+
},
|
|
94
|
+
allowedLevels: 2,
|
|
95
|
+
gql: {...},
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
123
99
|
```
|
|
124
100
|
|
|
125
101
|
### Properties
|
|
126
102
|
- `additionalFields` - Additional fields: 'audience', more in the future
|
|
127
103
|
- `allowedLevels` - Maximum level for which your're able to mark item as "Menu attached"
|
|
128
|
-
- `
|
|
104
|
+
- `contentTypes` - UIDs of related content types
|
|
105
|
+
- `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`
|
|
129
106
|
- `gql` - If you're using GraphQL that's the right place to put all necessary settings. More **[ here ](#gql-configuration)**
|
|
130
107
|
|
|
131
108
|
## GQL Configuration
|
|
132
|
-
To properly configure GQL to work with navigation you should provide `gql` prop
|
|
109
|
+
Using navigation with GraphQL requires both plugins to be installed and working. You can find instalation 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:
|
|
133
110
|
|
|
134
111
|
```gql
|
|
135
112
|
master: Int
|
|
@@ -137,11 +114,11 @@ items: [NavigationItem]
|
|
|
137
114
|
related: NavigationRelated
|
|
138
115
|
```
|
|
139
116
|
|
|
140
|
-
as follows:
|
|
117
|
+
This prop should look as follows:
|
|
141
118
|
|
|
142
119
|
```js
|
|
143
120
|
gql: {
|
|
144
|
-
navigationItemRelated: '
|
|
121
|
+
navigationItemRelated: ['<your GQL related content types>'],
|
|
145
122
|
},
|
|
146
123
|
```
|
|
147
124
|
|
|
@@ -149,10 +126,10 @@ for example:
|
|
|
149
126
|
|
|
150
127
|
```js
|
|
151
128
|
gql: {
|
|
152
|
-
|
|
129
|
+
navigationItemRelated: ['Page', 'UploadFile'],
|
|
153
130
|
},
|
|
154
131
|
```
|
|
155
|
-
where `
|
|
132
|
+
where `Page` and `UploadFile` are your type names for the **Content Types** you're referring by navigation items relations.
|
|
156
133
|
|
|
157
134
|
|
|
158
135
|
## Public API Navigation Item model
|
|
@@ -225,13 +202,13 @@ where `Pages` and `UploadFile` are your types to the **Content Types** you're re
|
|
|
225
202
|
|
|
226
203
|
### Render
|
|
227
204
|
|
|
228
|
-
`GET <host>/navigation/render/<idOrSlug>?type=<type>`
|
|
205
|
+
`GET <host>/api/navigation/render/<idOrSlug>?type=<type>`
|
|
229
206
|
|
|
230
207
|
Return a rendered navigation structure depends on passed type (`tree`, `rfr` or nothing to render as `flat/raw`).
|
|
231
208
|
|
|
232
209
|
*Note: The ID of navigation by default is `1`, that's for future extensions and multi-navigation feature.*
|
|
233
210
|
|
|
234
|
-
**Example URL**: `https://localhost:1337/navigation/render/1`
|
|
211
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1`
|
|
235
212
|
|
|
236
213
|
**Example response body**
|
|
237
214
|
|
|
@@ -260,7 +237,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
|
|
|
260
237
|
]
|
|
261
238
|
```
|
|
262
239
|
|
|
263
|
-
**Example URL**: `https://localhost:1337/navigation/render/1?type=tree`
|
|
240
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?type=tree`
|
|
264
241
|
|
|
265
242
|
**Example response body**
|
|
266
243
|
|
|
@@ -296,7 +273,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
|
|
|
296
273
|
]
|
|
297
274
|
```
|
|
298
275
|
|
|
299
|
-
**Example URL**: `https://localhost:1337/navigation/render/1?type=rfr`
|
|
276
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?type=rfr`
|
|
300
277
|
|
|
301
278
|
**Example response body**
|
|
302
279
|
|
|
@@ -387,30 +364,11 @@ For collection types it will be read from content type's attribute name `templat
|
|
|
387
364
|
|
|
388
365
|
For single types a global name of this content type will be used as a template name or it can be set manually with an option named `templateName`.
|
|
389
366
|
|
|
390
|
-
##
|
|
391
|
-
If you would like to use the [Strapi Molecules Audit Log](https://github.com/VirtusLab/strapi-molecules/tree/master/packages/strapi-plugin-audit-log) plugin you've to first install and then add in you `config/middleware.js` following section enable it:
|
|
392
|
-
```js
|
|
393
|
-
{
|
|
394
|
-
'audit-log': {
|
|
395
|
-
enabled: true,
|
|
396
|
-
exclude: [],
|
|
397
|
-
map: [
|
|
398
|
-
{
|
|
399
|
-
pluginName: 'navigation',
|
|
400
|
-
serviceName: 'navigation',
|
|
401
|
-
Class: Navigation,
|
|
402
|
-
},
|
|
403
|
-
]
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
As a last step you've to provide the Navigation class to let Audit Log use it. To not provide external & hard dependencies we've added the example of class code in the `examples/audit-log-integration.js` .
|
|
408
|
-
|
|
409
|
-
## Examples
|
|
367
|
+
## 🧩 Examples
|
|
410
368
|
|
|
411
369
|
Live example of plugin usage can be found in the [VirtusLab Strapi Examples](https://github.com/VirtusLab/strapi-examples/tree/master/strapi-plugin-navigation) repository.
|
|
412
370
|
|
|
413
|
-
## Q&A
|
|
371
|
+
## 💬 Q&A
|
|
414
372
|
|
|
415
373
|
### Content Types
|
|
416
374
|
|
|
@@ -418,11 +376,11 @@ Live example of plugin usage can be found in the [VirtusLab Strapi Examples](htt
|
|
|
418
376
|
|
|
419
377
|
**A:** As an authors of the plugin we're not supporting any editing of mentioned content types via built-in Strapi Content Manager. Plugin delivers highly customized & extended functionality which might be covered only by dedicated editor UI accessible via **Plugins Section > UI Navigation**. Only issues that has been recognized there, are in the scope of support we've providing.
|
|
420
378
|
|
|
421
|
-
## Contributing
|
|
379
|
+
## 🤝 Contributing
|
|
422
380
|
|
|
423
381
|
Feel free to fork and make a Pull Request to this plugin project. All the input is warmly welcome!
|
|
424
382
|
|
|
425
|
-
## Community support
|
|
383
|
+
## 👨💻 Community support
|
|
426
384
|
|
|
427
385
|
For general help using Strapi, please refer to [the official Strapi documentation](https://strapi.io/documentation/). For additional help, you can use one of these channels to ask a question:
|
|
428
386
|
|
|
@@ -430,6 +388,6 @@ For general help using Strapi, please refer to [the official Strapi documentatio
|
|
|
430
388
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
431
389
|
- [GitHub](https://github.com/VirtusLab/strapi-plugin-navigation/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
432
390
|
|
|
433
|
-
## License
|
|
391
|
+
## 📝 License
|
|
434
392
|
|
|
435
393
|
[MIT License](LICENSE.md) Copyright (c) 2021 [VirtusLab Sp. z o.o.](https://virtuslab.com/) & [Strapi Solutions](https://strapi.io/).
|
|
@@ -12,7 +12,7 @@ import Wrapper from './Wrapper';
|
|
|
12
12
|
import ItemCardBadge from '../ItemCardBadge';
|
|
13
13
|
import { getTrad } from "../../../translations";
|
|
14
14
|
|
|
15
|
-
const ItemCardHeader = ({ title, path, icon, removed, isPublished, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
15
|
+
const ItemCardHeader = ({ title, path, icon, removed, isExternal, isPublished, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
16
16
|
const badgeColor = isPublished ? 'success' : 'secondary';
|
|
17
17
|
const { formatMessage } = useIntl();
|
|
18
18
|
|
|
@@ -36,7 +36,7 @@ const ItemCardHeader = ({ title, path, icon, removed, isPublished, onItemRemove,
|
|
|
36
36
|
>
|
|
37
37
|
{formatMessage(getTrad("navigation.item.badge.removed"))}
|
|
38
38
|
</ItemCardBadge>
|
|
39
|
-
: <ItemCardBadge
|
|
39
|
+
: !isExternal && <ItemCardBadge
|
|
40
40
|
borderColor={`${badgeColor}200`}
|
|
41
41
|
backgroundColor={`${badgeColor}100`}
|
|
42
42
|
textColor={`${badgeColor}600`}
|
|
@@ -31,6 +31,7 @@ const Item = (props) => {
|
|
|
31
31
|
onItemRestore,
|
|
32
32
|
onItemEdit,
|
|
33
33
|
error,
|
|
34
|
+
displayChildren,
|
|
34
35
|
} = props;
|
|
35
36
|
|
|
36
37
|
const {
|
|
@@ -48,7 +49,7 @@ const Item = (props) => {
|
|
|
48
49
|
const isPublished = relatedRef && relatedRef?.publishedAt;
|
|
49
50
|
const isNextMenuAllowedLevel = isNumber(allowedLevels) ? level < (allowedLevels - 1) : true;
|
|
50
51
|
const isMenuAllowedLevel = isNumber(allowedLevels) ? level < allowedLevels : true;
|
|
51
|
-
const hasChildren = !isEmpty(item.items) && !isExternal;
|
|
52
|
+
const hasChildren = !isEmpty(item.items) && !isExternal && !displayChildren;
|
|
52
53
|
const absolutePath = isExternal ? undefined : `${levelPath === '/' ? '' : levelPath}/${path === '/' ? '' : path}`;
|
|
53
54
|
|
|
54
55
|
return (
|
|
@@ -60,6 +61,7 @@ const Item = (props) => {
|
|
|
60
61
|
path={isExternal ? externalPath : absolutePath}
|
|
61
62
|
icon={isExternal ? <EarthIcon /> : <LinkIcon />}
|
|
62
63
|
isPublished={isPublished}
|
|
64
|
+
isExternal={isExternal}
|
|
63
65
|
onItemRemove={() => onItemRemove(item)}
|
|
64
66
|
onItemEdit={() => onItemEdit({
|
|
65
67
|
...item,
|
|
@@ -15,6 +15,7 @@ const List = ({
|
|
|
15
15
|
onItemLevelAdd,
|
|
16
16
|
onItemRemove,
|
|
17
17
|
onItemRestore,
|
|
18
|
+
displayFlat,
|
|
18
19
|
}) => (
|
|
19
20
|
<Wrapper level={level}>
|
|
20
21
|
{items.map((item, n) => {
|
|
@@ -34,6 +35,7 @@ const List = ({
|
|
|
34
35
|
onItemRemove={onItemRemove}
|
|
35
36
|
onItemEdit={onItemEdit}
|
|
36
37
|
error={error}
|
|
38
|
+
displayChildren={displayFlat}
|
|
37
39
|
/>
|
|
38
40
|
);
|
|
39
41
|
})}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import { IconButton } from '@strapi/design-system/IconButton';
|
|
4
|
+
import { Searchbar, SearchForm } from '@strapi/design-system/Searchbar';
|
|
5
|
+
import SearchIcon from "@strapi/icons/Search";
|
|
6
|
+
import { getTradId } from '../../translations';
|
|
7
|
+
|
|
8
|
+
const Search = ({ value, setValue }) => {
|
|
9
|
+
const [isOpen, setIsOpen] = useState(!!value);
|
|
10
|
+
const wrapperRef = useRef(null);
|
|
11
|
+
const { formatMessage } = useIntl();
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (isOpen) {
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
wrapperRef.current.querySelector('input').focus();
|
|
17
|
+
}, 0);
|
|
18
|
+
}
|
|
19
|
+
}, [isOpen]);
|
|
20
|
+
|
|
21
|
+
if (isOpen) {
|
|
22
|
+
return (
|
|
23
|
+
<div ref={wrapperRef}>
|
|
24
|
+
<SearchForm>
|
|
25
|
+
<Searchbar
|
|
26
|
+
name="searchbar"
|
|
27
|
+
onClear={() => setValue('')}
|
|
28
|
+
value={value}
|
|
29
|
+
size="S"
|
|
30
|
+
onChange={(e) => setValue(e.target.value)}
|
|
31
|
+
clearLabel="Clearing the search"
|
|
32
|
+
placeholder={formatMessage({
|
|
33
|
+
id: getTradId('popup.item.form.audience.placeholder'),
|
|
34
|
+
defaultMessage: 'Type to start searching...',
|
|
35
|
+
})}
|
|
36
|
+
>
|
|
37
|
+
Search for navigation items
|
|
38
|
+
</Searchbar>
|
|
39
|
+
</SearchForm>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
} else {
|
|
43
|
+
return (
|
|
44
|
+
<IconButton icon={<SearchIcon />} onClick={() => setIsOpen(!isOpen)} />
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default Search;
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
LoadingIndicatorPage,
|
|
9
9
|
useNotification,
|
|
10
10
|
useAppInfos,
|
|
11
|
-
useStrapiApp,
|
|
12
11
|
} from "@strapi/helper-plugin";
|
|
13
12
|
import DataManagerContext from "../../contexts/DataManagerContext";
|
|
14
13
|
import getTrad from "../../utils/getTrad";
|
|
@@ -39,7 +38,7 @@ const DataManagerProvider = ({ children }) => {
|
|
|
39
38
|
const toggleNotification = useNotification();
|
|
40
39
|
const { autoReload } = useAppInfos();
|
|
41
40
|
const { formatMessage } = useIntl();
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
const {
|
|
44
43
|
items,
|
|
45
44
|
config,
|
|
@@ -54,10 +53,8 @@ const DataManagerProvider = ({ children }) => {
|
|
|
54
53
|
isLoadingForAdditionalDataToBeSet,
|
|
55
54
|
isLoadingForSubmit,
|
|
56
55
|
error
|
|
57
|
-
} = reducerState
|
|
56
|
+
} = reducerState;
|
|
58
57
|
const { pathname } = useLocation();
|
|
59
|
-
const { getPlugin } = useStrapiApp();
|
|
60
|
-
const { apis } = getPlugin(pluginId);
|
|
61
58
|
const formatMessageRef = useRef();
|
|
62
59
|
formatMessageRef.current = formatMessage;
|
|
63
60
|
|
|
@@ -164,7 +161,7 @@ const DataManagerProvider = ({ children }) => {
|
|
|
164
161
|
}
|
|
165
162
|
}, [autoReload]);
|
|
166
163
|
|
|
167
|
-
const getContentTypeItems = async ({ modelUID, query }
|
|
164
|
+
const getContentTypeItems = async ({ modelUID, query }) => {
|
|
168
165
|
dispatch({
|
|
169
166
|
type: GET_CONTENT_TYPE_ITEMS,
|
|
170
167
|
});
|
|
@@ -174,7 +171,7 @@ const DataManagerProvider = ({ children }) => {
|
|
|
174
171
|
if (query) {
|
|
175
172
|
queryParams.append('_q', query);
|
|
176
173
|
}
|
|
177
|
-
|
|
174
|
+
|
|
178
175
|
const contentTypeItems = await request(`${url}?${queryParams.toString()}`, {
|
|
179
176
|
method: "GET",
|
|
180
177
|
signal,
|
|
@@ -229,7 +226,7 @@ const DataManagerProvider = ({ children }) => {
|
|
|
229
226
|
dispatch({
|
|
230
227
|
type: SUBMIT_NAVIGATION,
|
|
231
228
|
});
|
|
232
|
-
|
|
229
|
+
|
|
233
230
|
const nagivationId = payload.id ? `/${payload.id}` : "";
|
|
234
231
|
const method = payload.id ? "PUT" : "POST";
|
|
235
232
|
const navigation = await request(`/${pluginId}${nagivationId}`, {
|
|
@@ -309,4 +306,4 @@ DataManagerProvider.propTypes = {
|
|
|
309
306
|
children: PropTypes.node.isRequired,
|
|
310
307
|
};
|
|
311
308
|
|
|
312
|
-
export default memo(DataManagerProvider);
|
|
309
|
+
export default memo(DataManagerProvider);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import produce from 'immer';
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
4
|
GET_LIST_DATA,
|
|
4
5
|
GET_LIST_DATA_SUCCEEDED,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
SUBMIT_NAVIGATION_ERROR,
|
|
19
20
|
} from './actions';
|
|
20
21
|
|
|
21
|
-
const initialState =
|
|
22
|
+
const initialState = {
|
|
22
23
|
items: [],
|
|
23
24
|
activeItem: undefined,
|
|
24
25
|
changedActiveItem: undefined,
|
|
@@ -31,106 +32,94 @@ const initialState = fromJS({
|
|
|
31
32
|
isLoadingForAdditionalDataToBeSet: false,
|
|
32
33
|
isLoadingForSubmit: false,
|
|
33
34
|
error: undefined,
|
|
34
|
-
}
|
|
35
|
+
};
|
|
35
36
|
|
|
36
|
-
const reducer = (state, action) => {
|
|
37
|
+
const reducer = (state, action) => produce(state, draftState => {
|
|
37
38
|
switch (action.type) {
|
|
38
39
|
case GET_CONFIG: {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
draftState.isLoadingForDetailsDataToBeSet = true;
|
|
41
|
+
draftState.config = {};
|
|
42
|
+
break;
|
|
42
43
|
}
|
|
43
44
|
case GET_CONFIG_SUCCEEDED: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
draftState.isLoadingForDetailsDataToBeSet = false;
|
|
46
|
+
draftState.config = action.config;
|
|
47
|
+
break;
|
|
47
48
|
}
|
|
48
49
|
case GET_LIST_DATA: {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
draftState.items = [];
|
|
51
|
+
draftState.isLoadingForDataToBeSet = true;
|
|
52
|
+
break;
|
|
52
53
|
}
|
|
53
54
|
case GET_LIST_DATA_SUCCEEDED: {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
draftState.items = action.items;
|
|
56
|
+
draftState.isLoading = false;
|
|
57
|
+
draftState.isLoadingForDataToBeSet = false;
|
|
58
|
+
break;
|
|
58
59
|
}
|
|
59
60
|
case GET_NAVIGATION_DATA: {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
draftState.activeItem = undefined;
|
|
62
|
+
draftState.changedActiveItem = undefined;
|
|
63
|
+
draftState.isLoadingForDetailsDataToBeSet = true;
|
|
64
|
+
break;
|
|
64
65
|
}
|
|
65
66
|
case GET_NAVIGATION_DATA_SUCCEEDED: {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const activeItem = action.activeItem || {};
|
|
68
|
+
draftState.activeItem = activeItem;
|
|
69
|
+
draftState.changedActiveItem = activeItem;
|
|
70
|
+
draftState.isLoadingForDetailsDataToBeSet = false;
|
|
71
|
+
break;
|
|
71
72
|
}
|
|
72
73
|
case CHANGE_NAVIGATION_DATA: {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
case RESET_NAVIGATION_DATA: {
|
|
83
|
-
const { activeItem = {} } = action;
|
|
84
|
-
return state.update("changedActiveItem", () => activeItem);
|
|
74
|
+
draftState.changedActiveItem = action.changedActiveItem;
|
|
75
|
+
draftState.navigationPopupOpened = action.forceClosePopups ? false : state.navigationPopupOpened;
|
|
76
|
+
draftState.navigationItemPopupOpened = action.forceClosePopups ? false : state.navigationItemPopupOpened;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case RESET_NAVIGATION_DATA : {
|
|
80
|
+
draftState.changedActiveItem = action.activeItem || {};
|
|
81
|
+
break;
|
|
85
82
|
}
|
|
86
83
|
case GET_CONTENT_TYPE_ITEMS: {
|
|
87
|
-
|
|
84
|
+
draftState.isLoadingForAdditionalDataToBeSet = true;
|
|
85
|
+
break;
|
|
88
86
|
}
|
|
89
87
|
case GET_CONTENT_TYPE_ITEMS_SUCCEEDED: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
fromJS(action.contentTypeItems),
|
|
94
|
-
);
|
|
88
|
+
draftState.isLoadingForAdditionalDataToBeSet = false;
|
|
89
|
+
draftState.config.contentTypeItems = action.contentTypeItems;
|
|
90
|
+
break;
|
|
95
91
|
}
|
|
96
92
|
case CHANGE_NAVIGATION_POPUP_VISIBILITY: {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
() => action.navigationPopupOpened,
|
|
100
|
-
);
|
|
93
|
+
draftState.navigationPopupOpened = action.navigationPopupOpened;
|
|
94
|
+
break;
|
|
101
95
|
}
|
|
102
96
|
case CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY: {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
() => action.navigationItemPopupOpened,
|
|
106
|
-
);
|
|
97
|
+
draftState.navigationItemPopupOpened = action.navigationItemPopupOpened;
|
|
98
|
+
break;
|
|
107
99
|
}
|
|
108
100
|
case SUBMIT_NAVIGATION: {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
draftState.isLoadingForSubmit = true;
|
|
102
|
+
draftState.error = undefined;
|
|
103
|
+
break;
|
|
112
104
|
}
|
|
113
105
|
case SUBMIT_NAVIGATION_SUCCEEDED: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
.update(
|
|
119
|
-
'isLoadingForSubmit',
|
|
120
|
-
() => false,
|
|
121
|
-
);
|
|
106
|
+
draftState.activeItem = action.navigation || {};
|
|
107
|
+
draftState.changedActiveItem = action.navigation || {};
|
|
108
|
+
draftState.isLoadingForSubmit = false;
|
|
109
|
+
break;
|
|
122
110
|
}
|
|
123
111
|
case SUBMIT_NAVIGATION_ERROR: {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
112
|
+
draftState.isLoadingForSubmit = false;
|
|
113
|
+
draftState.error = action.error;
|
|
114
|
+
break;
|
|
127
115
|
}
|
|
128
|
-
case RELOAD_PLUGIN:
|
|
116
|
+
case RELOAD_PLUGIN: {
|
|
129
117
|
return initialState;
|
|
118
|
+
}
|
|
130
119
|
default:
|
|
131
|
-
return
|
|
120
|
+
return draftState;
|
|
132
121
|
}
|
|
133
|
-
};
|
|
122
|
+
});
|
|
134
123
|
|
|
135
124
|
export default reducer;
|
|
136
125
|
export { initialState };
|