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.
Files changed (56) hide show
  1. package/README.md +82 -112
  2. package/__mocks__/pages.settings.json +25 -0
  3. package/__mocks__/strapi.js +196 -0
  4. package/admin/src/components/EmptyView/index.js +2 -1
  5. package/admin/src/components/Item/ItemCardBadge/index.js +15 -1
  6. package/admin/src/components/Item/ItemCardHeader/index.js +8 -15
  7. package/admin/src/components/Item/ItemCardRemovedOverlay/index.js +12 -0
  8. package/admin/src/components/Item/index.js +68 -22
  9. package/admin/src/components/NavigationItemList/index.js +10 -0
  10. package/admin/src/components/Search/index.js +47 -0
  11. package/admin/src/components/icons/navigation.js +14 -0
  12. package/admin/src/index.js +4 -3
  13. package/admin/src/pages/View/components/NavigationHeader/index.js +41 -35
  14. package/admin/src/pages/View/components/NavigationHeader/styles.js +13 -0
  15. package/admin/src/pages/View/components/NavigationItemForm/index.js +17 -2
  16. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +2 -4
  17. package/admin/src/pages/View/components/NavigationItemPopup/index.js +1 -1
  18. package/admin/src/pages/View/index.js +45 -19
  19. package/admin/src/pages/View/utils/parsers.js +11 -5
  20. package/admin/src/permissions.js +8 -0
  21. package/admin/src/translations/en.json +8 -5
  22. package/package.json +9 -4
  23. package/permissions.js +11 -0
  24. package/public/assets/logo.png +0 -0
  25. package/public/assets/preview.png +0 -0
  26. package/server/bootstrap.js +5 -4
  27. package/server/config/index.js +8 -0
  28. package/server/content-types/navigation/schema.json +45 -0
  29. package/server/content-types/navigation-item/schema.json +1 -1
  30. package/server/controllers/navigation.js +21 -0
  31. package/server/graphql/index.js +23 -0
  32. package/server/graphql/queries/index.js +17 -0
  33. package/server/graphql/queries/render-navigation-child.js +16 -0
  34. package/server/graphql/queries/render-navigation.js +15 -0
  35. package/server/graphql/resolvers-config.js +4 -0
  36. package/server/graphql/types/content-types-name-fields.js +8 -0
  37. package/server/graphql/types/content-types.js +16 -0
  38. package/server/graphql/types/create-navigation-item.js +17 -0
  39. package/server/graphql/types/create-navigation-related.js +8 -0
  40. package/server/graphql/types/create-navigation.js +7 -0
  41. package/server/graphql/types/index.js +15 -0
  42. package/server/graphql/types/navigation-config.js +9 -0
  43. package/server/graphql/types/navigation-details.js +10 -0
  44. package/server/graphql/types/navigation-item.js +29 -0
  45. package/server/graphql/types/navigation-related.js +23 -0
  46. package/server/graphql/types/navigation-render-type.js +4 -0
  47. package/server/graphql/types/navigation.js +9 -0
  48. package/server/register.js +5 -0
  49. package/server/routes/client.js +21 -0
  50. package/server/routes/index.js +2 -1
  51. package/server/services/__tests__/navigation.test.js +63 -78
  52. package/server/services/navigation.js +276 -10
  53. package/server/services/utils/functions.js +89 -14
  54. package/strapi-server.js +3 -1
  55. package/admin/src/components/PluginIcon/index.js +0 -6
  56. package/server/content-types/navigation/schema.js +0 -45
package/README.md CHANGED
@@ -1,34 +1,52 @@
1
- # Strapi v4 - Navigation plugin - BETA
2
-
3
- <p align="center">
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/npm/v/strapi-plugin-navigation/latest.svg" alt="NPM Version" />
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
- </p>
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
- A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provides navigation / menu builder feature with their possibility to control the audience and different output structure renderers:
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
- ### Versions
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
- - **Stable** - [v1.1.2](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
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
- ### Installation
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
- (Use **yarn** to install this plugin within your Strapi project (recommended). [Install yarn with these docs](https://yarnpkg.com/lang/en/docs/install/).)
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
- ### 🖐 Requirements
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/documentation/v3.x/installation/cli.html#step-1-make-sure-requirements-are-met">Installation Requirements</a>.
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.2 (recently tested)
78
+ - Strapi v4.0.7 (recently tested)
79
+ - Strapi v4.x
62
80
 
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.)
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
- ## 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`:
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
- plugins: {
112
- navigation: {
113
- additionalFields: ['audience'],
114
- allowedLevels: 2,
115
- contentTypesNameFields: {
116
- 'blog_posts': ['altTitle'],
117
- 'pages': ['title'],
118
- },
119
- gql: { ... }
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
- - `contentTypesNameFields` - Definition of content type title fields like `'content_type_name': ['field_name_1', 'field_name_2']`, if not set titles are pulled from fields like `['title', 'subject', 'name']`
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 which should contain union types which will be used for define GQL response format for your data while fetching:
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: 'union NavigationRelated = <your GQL related entities>',
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
- navigationItemRelated: 'union NavigationRelated = Pages | UploadFile',
134
+ navigationItemRelated: ['Page', 'UploadFile'],
153
135
  },
154
136
  ```
155
- where `Pages` and `UploadFile` are your types to the **Content Types** you're referring by navigation items relations.
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
- ## Public API Navigation Item model
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
- "created_at": "2020-09-29T13:29:19.086Z",
173
- "updated_at": "2020-09-29T13:29:19.128Z",
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
- ## Audit log
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
- - [Slack](http://slack.strapi.io) We're present on official Strapi slack workspace. Look for @cyp3r and DM.
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) 2021 [VirtusLab Sp. z o.o.](https://virtuslab.com/) &amp; [Strapi Solutions](https://strapi.io/).
405
+ [MIT License](LICENSE.md) Copyright (c) [VirtusLab Sp. z o.o.](https://virtuslab.com/) &amp; [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 };
@@ -10,7 +10,8 @@ const EmptyView = styled.div`
10
10
  justify-content: center;
11
11
  padding-left: 2rem;
12
12
  padding-right: 2rem;
13
- padding-bottom: "8rem" };
13
+ padding-bottom: 8rem;
14
+
14
15
 
15
16
  font-size: 2rem;
16
17
  font-weight: 600;
@@ -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, isPublished, onItemRemove, onItemEdit, onItemRestore }) => {
16
- const badgeColor = isPublished ? 'success' : 'secondary';
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 />} />
@@ -0,0 +1,12 @@
1
+ import styled from "styled-components";
2
+
3
+ export const ItemCardRemovedOverlay = styled.div`
4
+ width: 100%;
5
+ height: 100%;
6
+ position: absolute;
7
+ left: 0;
8
+ right: 0;
9
+ z-index: 1;
10
+
11
+ background: rgba(255,255,255,.75);
12
+ `;