strapi-plugin-navigation 2.0.0-beta.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -112
- package/__mocks__/pages.settings.json +25 -0
- package/__mocks__/strapi.js +196 -0
- package/admin/src/components/EmptyView/index.js +2 -1
- package/admin/src/components/Item/ItemCardBadge/index.js +15 -1
- package/admin/src/components/Item/ItemCardHeader/index.js +8 -15
- package/admin/src/components/Item/ItemCardRemovedOverlay/index.js +12 -0
- package/admin/src/components/Item/index.js +68 -22
- package/admin/src/components/NavigationItemList/index.js +10 -0
- package/admin/src/components/Search/index.js +47 -0
- package/admin/src/components/icons/navigation.js +14 -0
- package/admin/src/index.js +4 -3
- package/admin/src/pages/View/components/NavigationHeader/index.js +41 -35
- package/admin/src/pages/View/components/NavigationHeader/styles.js +13 -0
- package/admin/src/pages/View/components/NavigationItemForm/index.js +17 -2
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +2 -4
- package/admin/src/pages/View/components/NavigationItemPopup/index.js +1 -1
- package/admin/src/pages/View/index.js +45 -19
- package/admin/src/pages/View/utils/parsers.js +11 -5
- package/admin/src/permissions.js +8 -0
- package/admin/src/translations/en.json +8 -5
- package/package.json +9 -4
- package/permissions.js +11 -0
- package/public/assets/logo.png +0 -0
- package/public/assets/preview.png +0 -0
- package/server/bootstrap.js +5 -4
- package/server/config/index.js +8 -0
- package/server/content-types/navigation/schema.json +45 -0
- package/server/content-types/navigation-item/schema.json +1 -1
- 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/__tests__/navigation.test.js +63 -78
- package/server/services/navigation.js +276 -10
- package/server/services/utils/functions.js +89 -14
- package/strapi-server.js +3 -1
- package/admin/src/components/PluginIcon/index.js +0 -6
- package/server/content-types/navigation/schema.js +0 -45
package/README.md
CHANGED
|
@@ -1,34 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<div align="center" width="150px">
|
|
2
|
+
<img style="width: 150px; height: auto;" src="public/assets/logo.png" alt="Logo - Strapi Navigation plugin" />
|
|
3
|
+
</div>
|
|
4
|
+
<div align="center">
|
|
5
|
+
<h1>Strapi v4 - Navigation plugin</h1>
|
|
6
|
+
<p>Create consumable navigation with a simple and straightforward visual builder</p>
|
|
4
7
|
<a href="https://www.npmjs.org/package/strapi-plugin-navigation">
|
|
5
|
-
<img src="https://img.shields.io/
|
|
8
|
+
<img alt="GitHub package.json version" src="https://img.shields.io/github/package-json/v/VirtusLab-Open-Source/strapi-plugin-navigation?label=npm&logo=npm">
|
|
6
9
|
</a>
|
|
7
10
|
<a href="https://www.npmjs.org/package/strapi-plugin-navigation">
|
|
8
11
|
<img src="https://img.shields.io/npm/dm/strapi-plugin-navigation.svg" alt="Monthly download on NPM" />
|
|
9
12
|
</a>
|
|
10
13
|
<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" />
|
|
14
|
+
<img src="https://circleci.com/gh/VirtusLab-Open-Source/strapi-plugin-navigation.svg?style=shield" alt="CircleCI" />
|
|
12
15
|
</a>
|
|
13
16
|
<a href="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation">
|
|
14
17
|
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=master" alt="codecov.io" />
|
|
15
18
|
</a>
|
|
16
|
-
</
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<div style="margin: 20px 0" align="center">
|
|
24
|
+
<img style="width: 100%; height: auto;" src="public/assets/preview.png" alt="UI preview" />
|
|
25
|
+
</div>
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
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
28
|
|
|
20
29
|
- Flat
|
|
21
30
|
- Tree (nested)
|
|
22
31
|
- RFR (ready for handling by Redux First Router)
|
|
23
32
|
|
|
24
|
-
|
|
33
|
+
## ✨ Features
|
|
34
|
+
|
|
35
|
+
- **Navigation Public API:** Simple and ready for use API endpoint for consuming the navigation structure you've created
|
|
36
|
+
- **Visual builder:** Elegant and easy to use visual builder
|
|
37
|
+
- **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
|
|
38
|
+
- **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
|
|
39
|
+
- **[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
|
+
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
- **Beta** - v4 support - [v2.0.0-beta.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/feat/strapi-v4-support)
|
|
42
|
+
## ⚙️ Versions
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
- **Strapi v4** - (current) - [v2.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
|
|
45
|
+
- **Strapi v3** - [v1.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/strapi-v3)
|
|
30
46
|
|
|
31
|
-
|
|
47
|
+
## ⏳ Installation
|
|
48
|
+
|
|
49
|
+
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
50
|
|
|
33
51
|
```bash
|
|
34
52
|
yarn add strapi-plugin-navigation@latest
|
|
@@ -49,87 +67,51 @@ yarn develop --watch-admin
|
|
|
49
67
|
|
|
50
68
|
The **UI Navigation** plugin should appear in the **Plugins** section of Strapi sidebar after you run app again.
|
|
51
69
|
|
|
52
|
-
|
|
53
70
|
Enjoy 🎉
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
## 🖐 Requirements
|
|
56
73
|
|
|
57
|
-
Complete installation requirements are exact same as for Strapi itself and can be found in the documentation under <a href="https://strapi.io/
|
|
74
|
+
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
75
|
|
|
59
76
|
**Supported Strapi versions**:
|
|
60
77
|
|
|
61
|
-
- Strapi v4.0.
|
|
78
|
+
- Strapi v4.0.7 (recently tested)
|
|
79
|
+
- Strapi v4.x
|
|
62
80
|
|
|
63
|
-
|
|
81
|
+
> 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).
|
|
64
82
|
|
|
65
83
|
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
66
84
|
|
|
67
|
-
##
|
|
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`:
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
"navigation": {
|
|
82
|
-
"model": "navigationitem",
|
|
83
|
-
"plugin": "navigation",
|
|
84
|
-
"via": "related",
|
|
85
|
-
"configurable": false,
|
|
86
|
-
"hidden": true
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
inside the `attributes` section like in example below:
|
|
91
|
-
|
|
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
|
-
```
|
|
105
|
-
|
|
106
|
-
## Configuration
|
|
107
|
-
To setup the plugin properly we recommend to put following snippet as part of `config/custom.js` or `config/<env>/custom.js` file. If you've got already configurations for other plugins stores by this way, use just the `navigation` part within exising `plugins` item.
|
|
85
|
+
## 🔧 Configuration
|
|
86
|
+
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
87
|
|
|
109
88
|
```js
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
89
|
+
module.exports = ({ env }) => ({
|
|
90
|
+
// ...
|
|
91
|
+
navigation: {
|
|
92
|
+
enabled: true,
|
|
93
|
+
config: {
|
|
94
|
+
additionalFields: ['audience'],
|
|
95
|
+
contentTypes: ['api::page.page'],
|
|
96
|
+
contentTypesNameFields: {
|
|
97
|
+
'api::page.page': ['title']
|
|
98
|
+
},
|
|
99
|
+
allowedLevels: 2,
|
|
100
|
+
gql: {...},
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
123
104
|
```
|
|
124
105
|
|
|
125
106
|
### Properties
|
|
126
107
|
- `additionalFields` - Additional fields: 'audience', more in the future
|
|
127
108
|
- `allowedLevels` - Maximum level for which your're able to mark item as "Menu attached"
|
|
128
|
-
- `
|
|
109
|
+
- `contentTypes` - UIDs of related content types
|
|
110
|
+
- `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
111
|
- `gql` - If you're using GraphQL that's the right place to put all necessary settings. More **[ here ](#gql-configuration)**
|
|
130
112
|
|
|
131
|
-
## GQL Configuration
|
|
132
|
-
To properly configure GQL to work with navigation you should provide `gql` prop
|
|
113
|
+
## 🔧 GQL Configuration
|
|
114
|
+
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
115
|
|
|
134
116
|
```gql
|
|
135
117
|
master: Int
|
|
@@ -137,11 +119,11 @@ items: [NavigationItem]
|
|
|
137
119
|
related: NavigationRelated
|
|
138
120
|
```
|
|
139
121
|
|
|
140
|
-
as follows:
|
|
122
|
+
This prop should look as follows:
|
|
141
123
|
|
|
142
124
|
```js
|
|
143
125
|
gql: {
|
|
144
|
-
navigationItemRelated: '
|
|
126
|
+
navigationItemRelated: ['<your GQL related content types>'],
|
|
145
127
|
},
|
|
146
128
|
```
|
|
147
129
|
|
|
@@ -149,13 +131,19 @@ for example:
|
|
|
149
131
|
|
|
150
132
|
```js
|
|
151
133
|
gql: {
|
|
152
|
-
|
|
134
|
+
navigationItemRelated: ['Page', 'UploadFile'],
|
|
153
135
|
},
|
|
154
136
|
```
|
|
155
|
-
where `
|
|
137
|
+
where `Page` and `UploadFile` are your type names for the **Content Types** you're referring by navigation items relations.
|
|
138
|
+
|
|
139
|
+
## 👤 RBAC
|
|
140
|
+
Plugin provides granular permissions based on Strapi RBAC functionality.
|
|
156
141
|
|
|
142
|
+
### Mandatory permissions
|
|
143
|
+
For any role different than **Super Admin**, to access the **Navigation panel** you must set following permissions:
|
|
144
|
+
- _Plugins_ -> _Navigation_ -> _Read_ - gives you the access to **Navigation Panel**
|
|
157
145
|
|
|
158
|
-
##
|
|
146
|
+
## Base Navigation Item model
|
|
159
147
|
|
|
160
148
|
### Flat
|
|
161
149
|
```
|
|
@@ -169,8 +157,8 @@ where `Pages` and `UploadFile` are your types to the **Content Types** you're re
|
|
|
169
157
|
"menuAttached": false,
|
|
170
158
|
"parent": 8, // Parent Navigation Item 'id', null in case of root level
|
|
171
159
|
"master": 1, // Navigation 'id'
|
|
172
|
-
"
|
|
173
|
-
"
|
|
160
|
+
"createdAt": "2020-09-29T13:29:19.086Z",
|
|
161
|
+
"updatedAt": "2020-09-29T13:29:19.128Z",
|
|
174
162
|
"related": [ <Content Type model > ],
|
|
175
163
|
"audience": []
|
|
176
164
|
}
|
|
@@ -221,17 +209,17 @@ where `Pages` and `UploadFile` are your types to the **Content Types** you're re
|
|
|
221
209
|
}
|
|
222
210
|
```
|
|
223
211
|
|
|
224
|
-
## Public API specification
|
|
212
|
+
## 🕸️ Public API specification
|
|
225
213
|
|
|
226
214
|
### Render
|
|
227
215
|
|
|
228
|
-
`GET <host>/navigation/render/<idOrSlug>?type=<type>`
|
|
216
|
+
`GET <host>/api/navigation/render/<idOrSlug>?type=<type>`
|
|
229
217
|
|
|
230
218
|
Return a rendered navigation structure depends on passed type (`tree`, `rfr` or nothing to render as `flat/raw`).
|
|
231
219
|
|
|
232
220
|
*Note: The ID of navigation by default is `1`, that's for future extensions and multi-navigation feature.*
|
|
233
221
|
|
|
234
|
-
**Example URL**: `https://localhost:1337/navigation/render/1`
|
|
222
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1`
|
|
235
223
|
|
|
236
224
|
**Example response body**
|
|
237
225
|
|
|
@@ -260,7 +248,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
|
|
|
260
248
|
]
|
|
261
249
|
```
|
|
262
250
|
|
|
263
|
-
**Example URL**: `https://localhost:1337/navigation/render/1?type=tree`
|
|
251
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?type=tree`
|
|
264
252
|
|
|
265
253
|
**Example response body**
|
|
266
254
|
|
|
@@ -296,7 +284,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
|
|
|
296
284
|
]
|
|
297
285
|
```
|
|
298
286
|
|
|
299
|
-
**Example URL**: `https://localhost:1337/navigation/render/1?type=rfr`
|
|
287
|
+
**Example URL**: `https://localhost:1337/api/navigation/render/1?type=rfr`
|
|
300
288
|
|
|
301
289
|
**Example response body**
|
|
302
290
|
|
|
@@ -387,30 +375,11 @@ For collection types it will be read from content type's attribute name `templat
|
|
|
387
375
|
|
|
388
376
|
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
377
|
|
|
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
|
|
378
|
+
## 🧩 Examples
|
|
410
379
|
|
|
411
380
|
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
381
|
|
|
413
|
-
## Q&A
|
|
382
|
+
## 💬 Q&A
|
|
414
383
|
|
|
415
384
|
### Content Types
|
|
416
385
|
|
|
@@ -418,18 +387,19 @@ Live example of plugin usage can be found in the [VirtusLab Strapi Examples](htt
|
|
|
418
387
|
|
|
419
388
|
**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
389
|
|
|
421
|
-
## Contributing
|
|
390
|
+
## 🤝 Contributing
|
|
422
391
|
|
|
423
392
|
Feel free to fork and make a Pull Request to this plugin project. All the input is warmly welcome!
|
|
424
393
|
|
|
425
|
-
## Community support
|
|
394
|
+
## 👨💻 Community support
|
|
426
395
|
|
|
427
396
|
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
397
|
|
|
429
|
-
- [
|
|
398
|
+
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace. Find us by `[VirtusLab]` prefix and DM.
|
|
430
399
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
431
400
|
- [GitHub](https://github.com/VirtusLab/strapi-plugin-navigation/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
401
|
+
- [E-mail](mailto:strapi@virtuslab.com) - we will respond back as soon as possible
|
|
432
402
|
|
|
433
|
-
## License
|
|
403
|
+
## 📝 License
|
|
434
404
|
|
|
435
|
-
[MIT License](LICENSE.md) Copyright (c)
|
|
405
|
+
[MIT License](LICENSE.md) Copyright (c) [VirtusLab Sp. z o.o.](https://virtuslab.com/) & [Strapi Solutions](https://strapi.io/).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "collectionType",
|
|
3
|
+
"collectionName": "pages",
|
|
4
|
+
"info": {
|
|
5
|
+
"singularName": "page",
|
|
6
|
+
"pluralName": "pages",
|
|
7
|
+
"displayName": "Page",
|
|
8
|
+
"name": "page"
|
|
9
|
+
},
|
|
10
|
+
"options": {
|
|
11
|
+
"increments": true,
|
|
12
|
+
"timestamps": true,
|
|
13
|
+
"searchable": true,
|
|
14
|
+
"previewable": true,
|
|
15
|
+
"draftAndPublish": false
|
|
16
|
+
},
|
|
17
|
+
"pluginOptions": {},
|
|
18
|
+
"attributes": {
|
|
19
|
+
"title": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"required": true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const { isMatch } = require('lodash');
|
|
2
|
+
|
|
3
|
+
const masterModelMock = {
|
|
4
|
+
findOne: () => ({
|
|
5
|
+
id: 1,
|
|
6
|
+
name: "Main navigation",
|
|
7
|
+
slug: "main-navigation",
|
|
8
|
+
visible: true,
|
|
9
|
+
createdAt: "2021-12-30T14:05:50.276Z",
|
|
10
|
+
updatedAt: "2021-12-30T14:05:50.276Z",
|
|
11
|
+
}),
|
|
12
|
+
findMany: () => [{
|
|
13
|
+
id: 1,
|
|
14
|
+
name: "Main navigation",
|
|
15
|
+
slug: "main-navigation",
|
|
16
|
+
visible: true,
|
|
17
|
+
createdAt: "2021-12-30T14:05:50.276Z",
|
|
18
|
+
updatedAt: "2021-12-30T14:05:50.276Z",
|
|
19
|
+
}],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const itemModelMock = {
|
|
23
|
+
findOne: async () => ({
|
|
24
|
+
id: 1,
|
|
25
|
+
title: "home",
|
|
26
|
+
type: "INTERNAL",
|
|
27
|
+
path: "home1",
|
|
28
|
+
externalPath: null,
|
|
29
|
+
uiRouterKey: "home",
|
|
30
|
+
menuAttached: true,
|
|
31
|
+
order: 1,
|
|
32
|
+
createdAt: "2021-12-31T10:04:54.812Z",
|
|
33
|
+
updatedAt: "2022-01-14T13:36:29.430Z",
|
|
34
|
+
related: {
|
|
35
|
+
id: 1,
|
|
36
|
+
related_id: "1",
|
|
37
|
+
related_type: "api::pages.pages",
|
|
38
|
+
field: "navigation",
|
|
39
|
+
order: 1,
|
|
40
|
+
master: "3",
|
|
41
|
+
createdAt: "2021-12-31T10:04:54.800Z",
|
|
42
|
+
updatedAt: "2021-12-31T10:04:54.800Z",
|
|
43
|
+
navigationItemId: 56,
|
|
44
|
+
},
|
|
45
|
+
parent: null,
|
|
46
|
+
}),
|
|
47
|
+
findMany: async ({where}) => [{
|
|
48
|
+
id: 1,
|
|
49
|
+
title: "home",
|
|
50
|
+
type: "INTERNAL",
|
|
51
|
+
path: "home1",
|
|
52
|
+
externalPath: null,
|
|
53
|
+
uiRouterKey: "home",
|
|
54
|
+
menuAttached: true,
|
|
55
|
+
order: 1,
|
|
56
|
+
createdAt: "2021-12-31T10:04:54.812Z",
|
|
57
|
+
updatedAt: "2022-01-14T13:36:29.430Z",
|
|
58
|
+
master: 1,
|
|
59
|
+
related: {
|
|
60
|
+
id: 1,
|
|
61
|
+
related_id: "1",
|
|
62
|
+
related_type: "api::pages.pages",
|
|
63
|
+
field: "navigation",
|
|
64
|
+
order: 1,
|
|
65
|
+
master: "3",
|
|
66
|
+
createdAt: "2021-12-31T10:04:54.800Z",
|
|
67
|
+
updatedAt: "2021-12-31T10:04:54.800Z",
|
|
68
|
+
navigationItemId: 56,
|
|
69
|
+
},
|
|
70
|
+
parent: null,
|
|
71
|
+
}, {
|
|
72
|
+
id: 2,
|
|
73
|
+
title: "side",
|
|
74
|
+
type: "INTERNAL",
|
|
75
|
+
path: "side",
|
|
76
|
+
externalPath: null,
|
|
77
|
+
uiRouterKey: "side",
|
|
78
|
+
menuAttached: false,
|
|
79
|
+
order: 1,
|
|
80
|
+
createdAt: "2021-12-31T10:04:54.824Z",
|
|
81
|
+
updatedAt: "2021-12-31T12:47:20.508Z",
|
|
82
|
+
master: 1,
|
|
83
|
+
related: {
|
|
84
|
+
id: 2,
|
|
85
|
+
related_id: "2",
|
|
86
|
+
related_type: "api::pages.pages",
|
|
87
|
+
field: "navigation",
|
|
88
|
+
order: 1,
|
|
89
|
+
master: "3",
|
|
90
|
+
createdAt: "2021-12-31T10:04:54.823Z",
|
|
91
|
+
updatedAt: "2021-12-31T10:04:54.823Z",
|
|
92
|
+
navigationItemId: 57,
|
|
93
|
+
},
|
|
94
|
+
parent: {
|
|
95
|
+
id: 1,
|
|
96
|
+
title: "home",
|
|
97
|
+
type: "INTERNAL",
|
|
98
|
+
path: "home1",
|
|
99
|
+
externalPath: null,
|
|
100
|
+
uiRouterKey: "home",
|
|
101
|
+
menuAttached: true,
|
|
102
|
+
order: 1,
|
|
103
|
+
createdAt: "2021-12-31T10:04:54.812Z",
|
|
104
|
+
updatedAt: "2022-01-14T13:36:29.430Z",
|
|
105
|
+
},
|
|
106
|
+
}].filter(item => isMatch(item, where)),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const pageModelMock = {
|
|
110
|
+
findOne: async ({ where }) => ({
|
|
111
|
+
"id": 1,
|
|
112
|
+
"attributes": {
|
|
113
|
+
"title": "Page nr 1",
|
|
114
|
+
"createdAt": "2022-01-19T08:22:31.244Z",
|
|
115
|
+
"updatedAt": "2022-01-19T08:22:31.244Z",
|
|
116
|
+
"publishedAt": null
|
|
117
|
+
}
|
|
118
|
+
}),
|
|
119
|
+
findMany: async ({ where }) => [{
|
|
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
|
+
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const plugins = (strapi) => ({
|
|
140
|
+
navigation: {
|
|
141
|
+
get services() { return require('../server/services') },
|
|
142
|
+
service: (key) => (require('../server/services'))[key]({ strapi }),
|
|
143
|
+
get contentTypes() { return require('../server/content-types') },
|
|
144
|
+
contentType: (key) => preparePluginContentType(require('../server/content-types')[key].schema, 'navigation'),
|
|
145
|
+
config: (key) => ({
|
|
146
|
+
...require('../server/config').default,
|
|
147
|
+
contentTypes: ['api::pages.pages'],
|
|
148
|
+
})[key],
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const contentTypes = {
|
|
153
|
+
'api::pages.pages': {
|
|
154
|
+
...require('./pages.settings.json'),
|
|
155
|
+
uid: 'api::pages.pages',
|
|
156
|
+
modelName: 'page',
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const preparePluginContentType = (schema, plugin) => {
|
|
161
|
+
const { name } = schema.info;
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
...schema,
|
|
165
|
+
uid: `plugin::${plugin}.${name}`,
|
|
166
|
+
modelName: name,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const strapiFactory = (plugins, contentTypes) => ({
|
|
171
|
+
get plugins() { return plugins(strapi) },
|
|
172
|
+
plugin: (name) => plugins(strapi)[name],
|
|
173
|
+
get contentTypes() { return contentTypes },
|
|
174
|
+
contentType: (key) => contentTypes[key],
|
|
175
|
+
query: (model) => {
|
|
176
|
+
switch (model) {
|
|
177
|
+
case 'plugin::navigation.navigation':
|
|
178
|
+
return masterModelMock;
|
|
179
|
+
case 'plugin::navigation.navigation-item':
|
|
180
|
+
return itemModelMock;
|
|
181
|
+
case 'api::pages.pages':
|
|
182
|
+
return pageModelMock;
|
|
183
|
+
default:
|
|
184
|
+
return {
|
|
185
|
+
findOne: () => ({}),
|
|
186
|
+
findMany: () => [],
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const setupStrapi = () => {
|
|
193
|
+
Object.defineProperty(global, 'strapi', { value: strapiFactory(plugins, contentTypes) });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = { setupStrapi };
|
|
@@ -2,7 +2,21 @@ import styled from "styled-components";
|
|
|
2
2
|
import { Badge } from '@strapi/design-system/Badge';
|
|
3
3
|
|
|
4
4
|
const ItemCardBadge = styled(Badge)`
|
|
5
|
-
border: 1px solid ${({ theme, borderColor }) => theme.colors[borderColor]}
|
|
5
|
+
border: 1px solid ${({ theme, borderColor }) => theme.colors[borderColor]};
|
|
6
|
+
|
|
7
|
+
${ props => props.small && `
|
|
8
|
+
padding: 0 4px;
|
|
9
|
+
margin: 0px ${props.theme.spaces[3]};
|
|
10
|
+
vertical-align: middle;
|
|
11
|
+
|
|
12
|
+
cursor: default;
|
|
13
|
+
|
|
14
|
+
span {
|
|
15
|
+
font-size: .55rem;
|
|
16
|
+
line-height: 1;
|
|
17
|
+
vertical-align: middle;
|
|
18
|
+
}
|
|
19
|
+
`}
|
|
6
20
|
`;
|
|
7
21
|
|
|
8
22
|
export default ItemCardBadge;
|
|
@@ -4,6 +4,7 @@ import { useIntl } from 'react-intl';
|
|
|
4
4
|
import { Flex } from '@strapi/design-system/Flex';
|
|
5
5
|
import { IconButton } from '@strapi/design-system/IconButton';
|
|
6
6
|
import { Typography } from '@strapi/design-system/Typography';
|
|
7
|
+
import { Icon } from '@strapi/design-system/Icon';
|
|
7
8
|
import PencilIcon from '@strapi/icons/Pencil';
|
|
8
9
|
import TrashIcon from '@strapi/icons/Trash';
|
|
9
10
|
import RefreshIcon from '@strapi/icons/Refresh';
|
|
@@ -12,14 +13,14 @@ import Wrapper from './Wrapper';
|
|
|
12
13
|
import ItemCardBadge from '../ItemCardBadge';
|
|
13
14
|
import { getTrad } from "../../../translations";
|
|
14
15
|
|
|
15
|
-
const ItemCardHeader = ({ title, path, icon, removed,
|
|
16
|
-
|
|
16
|
+
const ItemCardHeader = ({ title, path, icon, removed, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
17
|
+
|
|
17
18
|
const { formatMessage } = useIntl();
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<Wrapper>
|
|
21
22
|
<Flex alignItems="center">
|
|
22
|
-
{icon}
|
|
23
|
+
<Icon as={icon} />
|
|
23
24
|
<Typography variant="omega" fontWeight="bold">
|
|
24
25
|
{title}
|
|
25
26
|
</Typography>
|
|
@@ -27,23 +28,15 @@ const ItemCardHeader = ({ title, path, icon, removed, isPublished, onItemRemove,
|
|
|
27
28
|
{path}
|
|
28
29
|
</Typography>
|
|
29
30
|
</Flex>
|
|
30
|
-
<Flex alignItems="center">
|
|
31
|
-
{removed
|
|
32
|
-
<ItemCardBadge
|
|
31
|
+
<Flex alignItems="center" style={{ zIndex: 2 }}>
|
|
32
|
+
{removed &&
|
|
33
|
+
(<ItemCardBadge
|
|
33
34
|
borderColor={`danger200`}
|
|
34
35
|
backgroundColor={`danger100`}
|
|
35
36
|
textColor={`danger600`}
|
|
36
37
|
>
|
|
37
38
|
{formatMessage(getTrad("navigation.item.badge.removed"))}
|
|
38
|
-
</ItemCardBadge>
|
|
39
|
-
: <ItemCardBadge
|
|
40
|
-
borderColor={`${badgeColor}200`}
|
|
41
|
-
backgroundColor={`${badgeColor}100`}
|
|
42
|
-
textColor={`${badgeColor}600`}
|
|
43
|
-
className="action"
|
|
44
|
-
>
|
|
45
|
-
{formatMessage(getTrad(`navigation.item.badge.${isPublished ? 'published' : 'draft'}`))}
|
|
46
|
-
</ItemCardBadge>
|
|
39
|
+
</ItemCardBadge>)
|
|
47
40
|
}
|
|
48
41
|
|
|
49
42
|
<IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<PencilIcon />} />
|