strapi-plugin-navigation 2.0.12 → 2.0.13

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 CHANGED
@@ -36,6 +36,21 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
36
36
  - Tree (nested)
37
37
  - RFR (ready for handling by Redux First Router)
38
38
 
39
+ ### Table of Contents
40
+ 1. [✨ Features](#-features)
41
+ 2. [⏳ Installation](#-installation)
42
+ 3. [🖐 Requirements](#-requirements)
43
+ 4. [🔧 Basic Configuration](#-configuration)
44
+ - [Settings page](#in-v203-and-newer)
45
+ - [Plugin file](#in-v202-and-older--default-configuration-state-for-v203-and-newer)
46
+ 5. [🔧 GraphQL Configuration](#-gql-configuration)
47
+ 6. [🕸️ Public API specification](#%EF%B8%8F-public-api-specification)
48
+ - [REST API](#rest-api)
49
+ - [GraphQL API](#graphql-api)
50
+ 8. [💬 FAQ](#-faq)
51
+ 9. [🤝 Contributing](#-contributing)
52
+ 10. [👨‍💻 Community support](#-community-support)
53
+
39
54
  ## ✨ Features
40
55
 
41
56
  - **Navigation Public API:** Simple and ready for use API endpoint for consuming the navigation structure you've created
@@ -43,6 +58,7 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
43
58
  - **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
59
  - **Different types of navigation items:** Create navigation with items linked to internal types, to external links or wrapper elements to keep structure clean
45
60
  - **Multiple navigations:** Create as many Navigation containers as you want, setup them and use in the consumer application
61
+ - **Light / Dark mode compatible:** By design we're supporting Strapi ☀️ Light / 🌙 Dark modes
46
62
  - **Customizable:** Possibility to customize the options like: available Content Types, Maximum level for "attach to menu", Additional fields (audience)
47
63
  - **[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
48
64
 
@@ -53,13 +69,23 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
53
69
 
54
70
  ## ⏳ Installation
55
71
 
72
+ ### Via Strapi Markerplace
73
+
74
+ As a ✅ **verified** plugin by Strapi team we're available on the [**Strapi Marketplace**](https://market.strapi.io/plugins/strapi-plugin-navigation) as well as **In-App Marketplace** where you can follow the installation instructions.
75
+
76
+ <div style="margin: 20px 0" align="center">
77
+ <img style="width: 100%; height: auto;" src="public/assets/marketplace.png" alt="Strapi In-App Marketplace" />
78
+ </div>
79
+
80
+ ### Via command line
81
+
56
82
  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/).
57
83
 
58
84
  ```bash
59
85
  yarn add strapi-plugin-navigation@latest
60
86
  ```
61
87
 
62
- After successful installation you've to build a fresh package that includes plugin UI. To archive that simply use:
88
+ After successful installation you've to re-build your Strapi instance. To archive that simply use:
63
89
 
64
90
  ```bash
65
91
  yarn build
@@ -74,7 +100,9 @@ yarn develop --watch-admin
74
100
 
75
101
  The **UI Navigation** plugin should appear in the **Plugins** section of Strapi sidebar after you run app again.
76
102
 
77
- Enjoy 🎉
103
+ As a next step you must configure your the plugin by the way you want to. See [**Configuration**](#🔧-configuration) section.
104
+
105
+ All done. Enjoy 🎉
78
106
 
79
107
  ## 🖐 Requirements
80
108
 
@@ -82,7 +110,7 @@ Complete installation requirements are exact same as for Strapi itself and can b
82
110
 
83
111
  **Supported Strapi versions**:
84
112
 
85
- - Strapi v4.1.5 (recently tested)
113
+ - Strapi v4.1.8 (recently tested)
86
114
  - Strapi v4.x
87
115
 
88
116
  > 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).
@@ -91,9 +119,17 @@ Complete installation requirements are exact same as for Strapi itself and can b
91
119
 
92
120
  ## 🔧 Configuration
93
121
 
122
+ To start your journey with **Navigation plugin** you must first setup it using the dedicated Settings page (`v2.0.3` and newer) or for any version, put your configuration in `config/plugins.js`. Anyway we're recommending the click-through option where your configuration is going to be properly validated.
123
+
94
124
  ### In `v2.0.3` and newer
95
125
 
96
- 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.
126
+ Version `2.0.3` introduces the intuitive **Settings** page which you can easily access via `Strapi Settings -> Section: Navigation Plugin -> Configuration`.
127
+
128
+ 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.
129
+
130
+ <div style="margin: 20px 0" align="center">
131
+ <img style="width: 100%; height: auto;" src="public/assets/configuration.png" alt="Plugin configuration" />
132
+ </div>
97
133
 
98
134
  > *Note*
99
135
  > 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.
@@ -169,7 +205,7 @@ For any role different than **Super Admin**, to access the **Navigation panel**
169
205
  ## Base Navigation Item model
170
206
 
171
207
  ### Flat
172
- ```
208
+ ```json
173
209
  {
174
210
  "id": 1,
175
211
  "title": "News",
@@ -182,13 +218,13 @@ For any role different than **Super Admin**, to access the **Navigation panel**
182
218
  "master": 1, // Navigation 'id'
183
219
  "createdAt": "2020-09-29T13:29:19.086Z",
184
220
  "updatedAt": "2020-09-29T13:29:19.128Z",
185
- "related": [ <Content Type model > ],
221
+ "related": {/*<Content Type model >*/ },
186
222
  "audience": []
187
223
  }
188
224
  ```
189
225
 
190
226
  ### Tree
191
- ```
227
+ ```json
192
228
  {
193
229
  "title": "News",
194
230
  "menuAttached": true,
@@ -198,7 +234,7 @@ For any role different than **Super Admin**, to access the **Navigation panel**
198
234
  "slug": "benefits",
199
235
  "external": false,
200
236
  "related": {
201
- <Content Type model >
237
+ // <Content Type model >
202
238
  },
203
239
  "items": [
204
240
  {
@@ -209,13 +245,13 @@ For any role different than **Super Admin**, to access the **Navigation panel**
209
245
  "uiRouterKey": "generic",
210
246
  "external": true
211
247
  },
212
- < Tree Navigation Item models >
248
+ // < Tree Navigation Item models >
213
249
  ]
214
250
  }
215
251
  ```
216
252
 
217
253
  ### RFR
218
- ```
254
+ ```json
219
255
  {
220
256
  "id": "News",
221
257
  "title": "News",
@@ -234,33 +270,41 @@ For any role different than **Super Admin**, to access the **Navigation panel**
234
270
 
235
271
  ## 🕸️ Public API specification
236
272
 
237
- ### Query Params
273
+ Plugin supports both **REST API** and **GraphQL API** exposed by Strapi.
238
274
 
239
- - `type` - Enum value representing structure type of returned navigation
275
+ **Query Params**
240
276
 
241
- **Example URL**: `https://localhost:1337/api/navigation/render/1?type=FLAT`
277
+ - `navigationIdOrSlug` - ID or slug for which your navigation structure is generated like for REST API:
242
278
 
243
- - `menu` - Boolean value for querying only navigation items that are attached to menu should be rendered eg.
279
+ > `https://localhost:1337/api/navigation/render/1`
280
+ > `https://localhost:1337/api/navigation/render/main-menu`
244
281
 
245
- **Example URL**: `https://localhost:1337/api/navigation/render/1?menu=true`
282
+ - `type` - Enum value representing structure type of returned navigation:
283
+ > `https://localhost:1337/api/navigation/render/1?type=FLAT`
246
284
 
247
- - `path` - String value for querying navigation items by its path
285
+ - `menu` (`menuOnly` for GQL) - Boolean value for querying only navigation items that are attached to menu should be rendered eg.
286
+ > `https://localhost:1337/api/navigation/render/1?menu=true`
248
287
 
249
- **Example URL**: `https://localhost:1337/api/navigation/render/1?path=/home/about-us`
288
+ - `path` - String value for querying navigation items by its path:
289
+ > `https://localhost:1337/api/navigation/render/1?path=/home/about-us`
250
290
 
251
- ### Render
291
+ ### REST API
292
+
293
+ > **Important!**
294
+ > Version `v2.0.13` introduced breaking change!
295
+ > All responses have changed their structure. Related field will now be of type ContentType instead of Array\<ContentType\>
252
296
 
253
- `GET <host>/api/navigation/render/<idOrSlug>?type=<type>`
297
+ `GET <host>/api/navigation/render/<navigationIdOrSlug>?type=<type>`
254
298
 
255
299
  Return a rendered navigation structure depends on passed type (`tree`, `rfr` or nothing to render as `flat/raw`).
256
300
 
257
- *Note: The ID of navigation by default is `1`, that's for future extensions and multi-navigation feature.*
301
+ > The ID of navigation by default is `1`, if you've got defined multiple navigations you must work with their IDs or Slugs to fetch.
258
302
 
259
303
  **Example URL**: `https://localhost:1337/api/navigation/render/1`
260
304
 
261
305
  **Example response body**
262
306
 
263
- ```
307
+ ```json
264
308
  [
265
309
  {
266
310
  "id": 1,
@@ -274,14 +318,14 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
274
318
  "master": 1,
275
319
  "created_at": "2020-09-29T13:29:19.086Z",
276
320
  "updated_at": "2020-09-29T13:29:19.128Z",
277
- "related": [{
321
+ "related": {
278
322
  "__contentType": "Page",
279
323
  "id": 1,
280
324
  "title": "News",
281
- ...
282
- }]
325
+ // ...
326
+ }
283
327
  },
284
- ...
328
+ // ...
285
329
  ]
286
330
  ```
287
331
 
@@ -289,7 +333,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
289
333
 
290
334
  **Example response body**
291
335
 
292
- ```
336
+ ```json
293
337
  [
294
338
  {
295
339
  "title": "News",
@@ -303,7 +347,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
303
347
  "__contentType": "Page",
304
348
  "id": 1,
305
349
  "title": "News",
306
- ...
350
+ // ...
307
351
  },
308
352
  "items": [
309
353
  {
@@ -314,10 +358,10 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
314
358
  "uiRouterKey": "generic",
315
359
  "external": true
316
360
  },
317
- ...
361
+ // ...
318
362
  ]
319
363
  },
320
- ...
364
+ // ...
321
365
  ]
322
366
  ```
323
367
 
@@ -325,7 +369,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
325
369
 
326
370
  **Example response body**
327
371
 
328
- ```
372
+ ```json
329
373
  {
330
374
  "pages": {
331
375
  "News": {
@@ -370,7 +414,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
370
414
  "parent": "Community",
371
415
  "menuAttached": false
372
416
  },
373
- ...
417
+ // ...
374
418
  },
375
419
  "nav": {
376
420
  "root": [
@@ -389,7 +433,7 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
389
433
  "type": "external",
390
434
  "url": "http://example.com"
391
435
  },
392
- ...
436
+ // ...
393
437
  ],
394
438
  "Community": [
395
439
  {
@@ -397,10 +441,98 @@ Return a rendered navigation structure depends on passed type (`tree`, `rfr` or
397
441
  "type": "internal",
398
442
  "page": "Highlights"
399
443
  },
400
- ...
444
+ // ...
401
445
  ],
402
- ...
446
+ // ...
447
+ }
448
+ }
449
+ ```
450
+
451
+ ### GraphQL API
452
+
453
+ Same as [**REST API**](#rest-api) returns a rendered navigation structure depends on passed type (`tree`, `rfr` or nothing to render as `flat/raw`).
454
+
455
+ **Example request**
456
+
457
+ ```graphql
458
+ query {
459
+ renderNavigation(
460
+ navigationIdOrSlug: "main-navigation"
461
+ type: TREE
462
+ menuOnly: false
463
+ ) {
464
+ id
465
+ title
466
+ path
467
+ related {
468
+ __typename
469
+
470
+ ... on Page {
471
+ Title
472
+ }
473
+
474
+ ... on WithFlowType {
475
+ Name
476
+ }
477
+ }
478
+ items {
479
+ id
480
+ title
481
+ path
482
+ related {
483
+ __typename
484
+
485
+ ... on Page {
486
+ Title
487
+ }
488
+
489
+ ... on WithFlowType {
490
+ Name
491
+ }
492
+ }
403
493
  }
494
+ }
495
+ }
496
+ ```
497
+
498
+ **Example response**
499
+
500
+ ```json
501
+ {
502
+ "data": {
503
+ "renderNavigation": [
504
+ {
505
+ "id": 8,
506
+ "title": "Test page",
507
+ "path": "/test-path",
508
+ "related": {
509
+ "__typename": "WithFlowType",
510
+ "Name": "Test"
511
+ },
512
+ "items": [
513
+ {
514
+ "id": 11,
515
+ "title": "Nested",
516
+ "path": "/test-path/nested-one",
517
+ "related": {
518
+ "__typename": "Page",
519
+ "Title": "Eg. Page title"
520
+ }
521
+ }
522
+ ]
523
+ },
524
+ {
525
+ "id": 10,
526
+ "title": "Another page",
527
+ "path": "/another",
528
+ "related": {
529
+ "__typename": "Page",
530
+ "Title": "dfdfdf"
531
+ },
532
+ "items": []
533
+ }
534
+ ]
535
+ }
404
536
  }
405
537
  ```
406
538
 
@@ -416,13 +548,22 @@ For single types a global name of this content type will be used as a template n
416
548
 
417
549
  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.
418
550
 
419
- ## 💬 Q&A
551
+ ## 💬 FAQ
552
+
553
+ ### GraphQL tricks
420
554
 
421
- ### Content Types
555
+ **Q:** I would like to use GraphQL schemas but I'm not getting renderNavigation query or even proper types as Navigation, NavigationItem etc. What should I do?
422
556
 
423
- **Q:** I've recognized **Navigation Item** and **Navigation** collection types in the Collections sidebar section, but they are not working properly. What should I do?
557
+ **A:** There is a one trick you might try. Strapi by default is ordering plugins by the way which takes `strapi-plugin-graphql` to initialize earlier than other plugins so types might not be injected. If you don't have it yet, please create `config/plugins.js` file and put there at lease following lines:
558
+
559
+ ```js
560
+ module.exports = {
561
+ 'navigation': { enabled: true },
562
+ 'graphql': { enabled: true },
563
+ };
564
+ ```
424
565
 
425
- **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.
566
+ If you already got it, make sure that `navigation` plugin is inserted before `graphql`. That should do the job.
426
567
 
427
568
  ## 🤝 Contributing
428
569
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-navigation",
3
- "version": "2.0.12",
3
+ "version": "2.0.13",
4
4
  "description": "Strapi - Navigation plugin",
5
5
  "strapi": {
6
6
  "name": "navigation",
@@ -17,7 +17,7 @@
17
17
  "test:unit": "jest --verbose --coverage"
18
18
  },
19
19
  "dependencies": {
20
- "@strapi/utils": "^4.1.5",
20
+ "@strapi/utils": "^4.1.8",
21
21
  "uuid": "^8.3.0",
22
22
  "lodash": "^4.17.11",
23
23
  "react": "^16.9.0",
@@ -10,7 +10,7 @@ module.exports = ({ nexus }) =>
10
10
  t.nonNull.string("uiRouterKey")
11
11
  t.nonNull.boolean("menuAttached")
12
12
  t.nonNull.int("order")
13
- t.int("parent")
13
+ t.field("parent", { type: "NavigationItem" })
14
14
  t.int("master")
15
15
  t.list.field("items", { type: 'NavigationItem' })
16
16
  t.field("related", { type: 'NavigationRelated' })
@@ -474,10 +474,10 @@ module.exports = ({ strapi }) => {
474
474
  ...item,
475
475
  audience: item.audience?.map(_ => _.key),
476
476
  title: utilsFunctions.composeItemTitle(item, contentTypesNameFields, contentTypes),
477
- related: item.related?.map(({ localizations, ...item }) => item),
477
+ related: last(item.related?.map(({ localizations, ...item }) => item)),
478
478
  items: null,
479
479
  }));
480
- return isNil(rootPath) ? items : utilsFunctions.filterByPath(publishedItems, rootPath).items;
480
+ return isNil(rootPath) ? publishedItems : utilsFunctions.filterByPath(publishedItems, rootPath).items;
481
481
  }
482
482
  }
483
483
  throw new NotFoundError();