strapi-plugin-navigation 2.0.0-beta.5 → 2.0.2
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 +65 -22
- package/__mocks__/pages.settings.json +25 -0
- package/__mocks__/strapi.js +207 -0
- package/admin/src/components/ConfirmationDialog/index.js +56 -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 +13 -26
- package/admin/src/components/Item/ItemCardRemovedOverlay/index.js +12 -0
- package/admin/src/components/Item/index.js +67 -25
- package/admin/src/components/NavigationItemList/index.js +8 -0
- package/admin/src/components/RestartAlert/index.js +8 -0
- package/admin/src/components/Search/index.js +21 -23
- package/admin/src/components/icons/navigation.js +14 -0
- package/admin/src/hooks/useAllContentTypes.js +13 -0
- package/admin/src/hooks/useNavigationConfig.js +58 -0
- package/admin/src/index.js +28 -4
- package/admin/src/pages/SettingsPage/index.js +311 -0
- 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 +50 -8
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +3 -6
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +3 -7
- package/admin/src/pages/View/components/NavigationItemPopup/index.js +3 -5
- package/admin/src/pages/View/index.js +31 -17
- package/admin/src/pages/View/utils/parsers.js +10 -4
- package/admin/src/permissions.js +8 -0
- package/admin/src/translations/en.json +53 -10
- 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 +7 -6
- package/permissions.js +11 -0
- package/server/bootstrap.js +35 -5
- package/server/content-types/navigation/schema.json +45 -0
- package/server/content-types/navigation-item/schema.json +1 -1
- package/server/controllers/navigation.js +26 -2
- package/server/graphql/index.js +3 -4
- 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__/navigation.test.js +63 -78
- package/server/services/navigation.js +42 -11
- package/server/services/utils/functions.js +5 -12
- 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/admin/src/components/PluginIcon/index.js +0 -6
- package/codecov.yml +0 -3
- package/server/content-types/navigation/schema.js +0 -45
- package/server/register.js +0 -5
package/README.md
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
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>
|
|
1
4
|
<div align="center">
|
|
2
|
-
<h1>Strapi v4 - Navigation plugin
|
|
3
|
-
<p>Create consumable navigation with a simple and
|
|
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/github/package-json/v/VirtusLab-Open-Source/strapi-plugin-navigation
|
|
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-Open-Source/strapi-plugin-navigation
|
|
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
|
-
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=
|
|
17
|
+
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-navigation/coverage.svg?branch=master" alt="codecov.io" />
|
|
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" />
|
|
15
24
|
</a>
|
|
16
25
|
</div>
|
|
17
26
|
|
|
18
27
|
---
|
|
19
28
|
|
|
29
|
+
<div style="margin: 20px 0" align="center">
|
|
30
|
+
<img style="width: 100%; height: auto;" src="public/assets/preview.png" alt="UI preview" />
|
|
31
|
+
</div>
|
|
32
|
+
|
|
20
33
|
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:
|
|
21
34
|
|
|
22
35
|
- Flat
|
|
@@ -28,14 +41,14 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
|
|
|
28
41
|
- **Navigation Public API:** Simple and ready for use API endpoint for consuming the navigation structure you've created
|
|
29
42
|
- **Visual builder:** Elegant and easy to use visual builder
|
|
30
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
|
|
31
45
|
- **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
|
|
32
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
|
|
33
47
|
|
|
34
|
-
|
|
35
48
|
## ⚙️ Versions
|
|
36
49
|
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
50
|
+
- **Strapi v4** - (current) - [v2.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation)
|
|
51
|
+
- **Strapi v3** - [v1.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/strapi-v3)
|
|
39
52
|
|
|
40
53
|
## ⏳ Installation
|
|
41
54
|
|
|
@@ -68,17 +81,28 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
68
81
|
|
|
69
82
|
**Supported Strapi versions**:
|
|
70
83
|
|
|
71
|
-
- Strapi v4.0.
|
|
84
|
+
- Strapi v4.0.7 (recently tested)
|
|
72
85
|
- Strapi v4.x
|
|
73
86
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
It may or may not work with the older Strapi v4 versions, these are not tested nor officially supported at this time.
|
|
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).
|
|
77
88
|
|
|
78
89
|
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
79
90
|
|
|
80
91
|
## 🔧 Configuration
|
|
81
|
-
|
|
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
|
|
82
106
|
|
|
83
107
|
```js
|
|
84
108
|
module.exports = ({ env }) => ({
|
|
@@ -100,13 +124,16 @@ Config for this plugin is stored as a part of `config/plugins.js` or `config/<en
|
|
|
100
124
|
|
|
101
125
|
### Properties
|
|
102
126
|
- `additionalFields` - Additional fields: 'audience', more in the future
|
|
103
|
-
- `allowedLevels` - Maximum level for which
|
|
127
|
+
- `allowedLevels` - Maximum level for which you're able to mark item as "Menu attached"
|
|
104
128
|
- `contentTypes` - UIDs of related content types
|
|
105
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`
|
|
106
130
|
- `gql` - If you're using GraphQL that's the right place to put all necessary settings. More **[ here ](#gql-configuration)**
|
|
107
131
|
|
|
108
|
-
## GQL Configuration
|
|
109
|
-
Using navigation with GraphQL requires both plugins to be installed and working. You can find
|
|
132
|
+
## 🔧 GQL Configuration
|
|
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.
|
|
110
137
|
|
|
111
138
|
```gql
|
|
112
139
|
master: Int
|
|
@@ -131,8 +158,14 @@ gql: {
|
|
|
131
158
|
```
|
|
132
159
|
where `Page` and `UploadFile` are your type names for the **Content Types** you're referring by navigation items relations.
|
|
133
160
|
|
|
161
|
+
## 👤 RBAC
|
|
162
|
+
Plugin provides granular permissions based on Strapi RBAC functionality.
|
|
163
|
+
|
|
164
|
+
### Mandatory permissions
|
|
165
|
+
For any role different than **Super Admin**, to access the **Navigation panel** you must set following permissions:
|
|
166
|
+
- _Plugins_ -> _Navigation_ -> _Read_ - gives you the access to **Navigation Panel**
|
|
134
167
|
|
|
135
|
-
##
|
|
168
|
+
## Base Navigation Item model
|
|
136
169
|
|
|
137
170
|
### Flat
|
|
138
171
|
```
|
|
@@ -146,8 +179,8 @@ where `Page` and `UploadFile` are your type names for the **Content Types** you'
|
|
|
146
179
|
"menuAttached": false,
|
|
147
180
|
"parent": 8, // Parent Navigation Item 'id', null in case of root level
|
|
148
181
|
"master": 1, // Navigation 'id'
|
|
149
|
-
"
|
|
150
|
-
"
|
|
182
|
+
"createdAt": "2020-09-29T13:29:19.086Z",
|
|
183
|
+
"updatedAt": "2020-09-29T13:29:19.128Z",
|
|
151
184
|
"related": [ <Content Type model > ],
|
|
152
185
|
"audience": []
|
|
153
186
|
}
|
|
@@ -198,7 +231,7 @@ where `Page` and `UploadFile` are your type names for the **Content Types** you'
|
|
|
198
231
|
}
|
|
199
232
|
```
|
|
200
233
|
|
|
201
|
-
## Public API specification
|
|
234
|
+
## 🕸️ Public API specification
|
|
202
235
|
|
|
203
236
|
### Render
|
|
204
237
|
|
|
@@ -378,16 +411,26 @@ Live example of plugin usage can be found in the [VirtusLab Strapi Examples](htt
|
|
|
378
411
|
|
|
379
412
|
## 🤝 Contributing
|
|
380
413
|
|
|
414
|
+
<div>
|
|
415
|
+
<a href="https://sharing.clickup.com/tl/xhcmx-43/strapiv-4-navigation-roadmap">
|
|
416
|
+
<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" />
|
|
417
|
+
</a>
|
|
418
|
+
<a href="https://sharing.clickup.com/b/6-169004201-2/strapiv-4-navigation-board">
|
|
419
|
+
<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" />
|
|
420
|
+
</a>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
381
423
|
Feel free to fork and make a Pull Request to this plugin project. All the input is warmly welcome!
|
|
382
424
|
|
|
383
425
|
## 👨💻 Community support
|
|
384
426
|
|
|
385
427
|
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:
|
|
386
428
|
|
|
387
|
-
- [
|
|
429
|
+
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace. Find us by `[VirtusLab]` prefix and DM.
|
|
388
430
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
389
431
|
- [GitHub](https://github.com/VirtusLab/strapi-plugin-navigation/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
432
|
+
- [E-mail](mailto:strapi@virtuslab.com) - we will respond back as soon as possible
|
|
390
433
|
|
|
391
434
|
## 📝 License
|
|
392
435
|
|
|
393
|
-
[MIT License](LICENSE.md) Copyright (c)
|
|
436
|
+
[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,207 @@
|
|
|
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
|
+
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
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const setupStrapi = () => {
|
|
204
|
+
Object.defineProperty(global, 'strapi', { value: strapiFactory(plugins, contentTypes) });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = { setupStrapi };
|
|
@@ -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;
|
|
@@ -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: ${props.theme.spaces[1]};
|
|
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;
|
|
@@ -1,25 +1,20 @@
|
|
|
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
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import RefreshIcon from '@strapi/icons/Refresh';
|
|
6
|
+
import { Icon } from '@strapi/design-system/Icon';
|
|
7
|
+
import { Pencil, Trash, Refresh } from '@strapi/icons/';
|
|
10
8
|
|
|
11
9
|
import Wrapper from './Wrapper';
|
|
12
10
|
import ItemCardBadge from '../ItemCardBadge';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
const ItemCardHeader = ({ title, path, icon, removed, isExternal, isPublished, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
16
|
-
const badgeColor = isPublished ? 'success' : 'secondary';
|
|
17
|
-
const { formatMessage } = useIntl();
|
|
11
|
+
import { getMessage } from '../../../utils';
|
|
18
12
|
|
|
13
|
+
const ItemCardHeader = ({ title, path, icon, removed, onItemRemove, onItemEdit, onItemRestore }) => {
|
|
19
14
|
return (
|
|
20
15
|
<Wrapper>
|
|
21
16
|
<Flex alignItems="center">
|
|
22
|
-
{icon}
|
|
17
|
+
<Icon as={icon} />
|
|
23
18
|
<Typography variant="omega" fontWeight="bold">
|
|
24
19
|
{title}
|
|
25
20
|
</Typography>
|
|
@@ -27,29 +22,21 @@ const ItemCardHeader = ({ title, path, icon, removed, isExternal, isPublished, o
|
|
|
27
22
|
{path}
|
|
28
23
|
</Typography>
|
|
29
24
|
</Flex>
|
|
30
|
-
<Flex alignItems="center">
|
|
31
|
-
{removed
|
|
32
|
-
<ItemCardBadge
|
|
25
|
+
<Flex alignItems="center" style={{ zIndex: 2 }}>
|
|
26
|
+
{removed &&
|
|
27
|
+
(<ItemCardBadge
|
|
33
28
|
borderColor={`danger200`}
|
|
34
29
|
backgroundColor={`danger100`}
|
|
35
30
|
textColor={`danger600`}
|
|
36
31
|
>
|
|
37
|
-
{
|
|
38
|
-
</ItemCardBadge>
|
|
39
|
-
: !isExternal && <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>
|
|
32
|
+
{getMessage("components.navigationItem.badge.removed")}
|
|
33
|
+
</ItemCardBadge>)
|
|
47
34
|
}
|
|
48
35
|
|
|
49
|
-
<IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<
|
|
36
|
+
<IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<Pencil />} />
|
|
50
37
|
{removed ?
|
|
51
|
-
<IconButton onClick={onItemRestore} label="Restore" icon={<
|
|
52
|
-
<IconButton onClick={onItemRemove} label="Remove" icon={<
|
|
38
|
+
<IconButton onClick={onItemRestore} label="Restore" icon={<Refresh />} /> :
|
|
39
|
+
<IconButton onClick={onItemRemove} label="Remove" icon={<Trash />} />
|
|
53
40
|
}
|
|
54
41
|
</Flex>
|
|
55
42
|
</Wrapper>
|