strapi-plugin-navigation 1.1.2 → 2.0.0-beta.1

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 (128) hide show
  1. package/README.md +36 -15
  2. package/admin/src/components/EmptyView/index.js +7 -16
  3. package/admin/src/components/Item/ItemCardBadge/index.js +8 -0
  4. package/admin/src/components/Item/ItemCardHeader/Wrapper.js +21 -0
  5. package/admin/src/components/Item/ItemCardHeader/index.js +59 -0
  6. package/admin/src/components/Item/Wrapper.js +39 -0
  7. package/admin/src/components/Item/index.js +76 -124
  8. package/admin/src/components/NavigationItemList/Wrapper.js +22 -0
  9. package/admin/src/components/NavigationItemList/index.js +54 -0
  10. package/admin/src/components/PluginIcon/index.js +6 -0
  11. package/admin/src/index.js +49 -45
  12. package/admin/src/pages/App/index.js +31 -0
  13. package/admin/src/{containers → pages}/DataManagerProvider/actions.js +0 -0
  14. package/admin/src/{containers → pages}/DataManagerProvider/index.js +81 -85
  15. package/admin/src/{containers → pages}/DataManagerProvider/init.js +0 -0
  16. package/admin/src/{containers → pages}/DataManagerProvider/reducer.js +0 -0
  17. package/admin/src/pages/View/components/NavigationContentHeader/index.js +18 -0
  18. package/admin/src/pages/View/components/NavigationHeader/index.js +60 -0
  19. package/admin/src/pages/View/components/NavigationItemForm/index.js +403 -0
  20. package/admin/src/{containers → pages}/View/components/NavigationItemForm/utils/form.js +2 -2
  21. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +40 -0
  22. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +20 -0
  23. package/admin/src/{containers → pages}/View/components/NavigationItemPopup/index.js +16 -16
  24. package/admin/src/pages/View/index.js +209 -0
  25. package/admin/src/{containers → pages}/View/utils/enums.js +0 -0
  26. package/admin/src/{containers → pages}/View/utils/form.js +1 -1
  27. package/admin/src/{containers → pages}/View/utils/index.js +0 -0
  28. package/admin/src/{containers → pages}/View/utils/parsers.js +13 -12
  29. package/admin/src/pluginId.js +4 -3
  30. package/admin/src/translations/en.json +47 -38
  31. package/admin/src/translations/fr.json +7 -1
  32. package/admin/src/utils/getTrad.js +2 -2
  33. package/package.json +13 -5
  34. package/server/bootstrap.js +41 -0
  35. package/server/config.js +8 -0
  36. package/server/content-types/audience/index.js +9 -0
  37. package/{models/audience.js → server/content-types/audience/lifecycle.js} +0 -0
  38. package/{models/audience.settings.json → server/content-types/audience/schema.json} +4 -2
  39. package/server/content-types/index.js +13 -0
  40. package/server/content-types/navigation/index.js +9 -0
  41. package/{models/navigation.js → server/content-types/navigation/lifecycle.js} +0 -0
  42. package/server/content-types/navigation/schema.js +45 -0
  43. package/server/content-types/navigation-item/index.js +9 -0
  44. package/{models/navigationItem.js → server/content-types/navigation-item/lifecycle.js} +0 -0
  45. package/{models/navigationItem.settings.json → server/content-types/navigation-item/schema.json} +16 -12
  46. package/server/content-types/navigations-items-related/index.js +9 -0
  47. package/{models/navigations_items_related.js → server/content-types/navigations-items-related/lifecycle.js} +0 -0
  48. package/{models/navigations_items_related.settings.json → server/content-types/navigations-items-related/schema.json} +4 -2
  49. package/server/controllers/index.js +7 -0
  50. package/{controllers → server/controllers}/navigation.js +7 -39
  51. package/server/routes/admin.js +38 -0
  52. package/server/routes/index.js +3 -0
  53. package/{services → server/services}/__tests__/navigation.test.js +0 -0
  54. package/server/services/index.js +7 -0
  55. package/server/services/navigation.js +463 -0
  56. package/{services → server/services}/utils/constant.js +3 -1
  57. package/server/services/utils/functions.js +103 -0
  58. package/strapi-admin.js +1 -0
  59. package/strapi-server.js +18 -0
  60. package/__mocks__/helpers/another-plugin/blog-post.settings.json +0 -31
  61. package/__mocks__/helpers/another-plugin/pages.settings.json +0 -28
  62. package/__mocks__/helpers/blog-post.settings.json +0 -31
  63. package/__mocks__/helpers/home-page.settings.json +0 -4
  64. package/__mocks__/helpers/my-homepage.settings.json +0 -27
  65. package/__mocks__/helpers/pages.settings.json +0 -27
  66. package/__mocks__/helpers/strapi.js +0 -101
  67. package/admin/src/assets/images/icon-cross-blue.svg +0 -1
  68. package/admin/src/assets/images/icon_remove.svg +0 -19
  69. package/admin/src/components/Container/index.js +0 -7
  70. package/admin/src/components/Input/index.js +0 -41
  71. package/admin/src/components/Item/CardItem.js +0 -46
  72. package/admin/src/components/Item/CardItemLevelAdd.js +0 -41
  73. package/admin/src/components/Item/CardItemLevelWrapper.js +0 -27
  74. package/admin/src/components/Item/CardItemPath.js +0 -9
  75. package/admin/src/components/Item/CardItemRestore.js +0 -19
  76. package/admin/src/components/Item/CardItemTitle.js +0 -5
  77. package/admin/src/components/Item/CardWrapper.js +0 -78
  78. package/admin/src/components/ItemFooter/CardItemError.js +0 -11
  79. package/admin/src/components/ItemFooter/CardItemRelation.js +0 -18
  80. package/admin/src/components/ItemFooter/CardItemRelationStatus.js +0 -17
  81. package/admin/src/components/ItemFooter/CardItemType.js +0 -18
  82. package/admin/src/components/ItemFooter/Wrapper.js +0 -26
  83. package/admin/src/components/ItemFooter/index.js +0 -66
  84. package/admin/src/components/ItemOrdering/CardOrderingButton.js +0 -24
  85. package/admin/src/components/ItemOrdering/Wrapper.js +0 -24
  86. package/admin/src/components/ItemOrdering/index.js +0 -36
  87. package/admin/src/components/List/Container.js +0 -34
  88. package/admin/src/components/List/ListLevelRoot.js +0 -18
  89. package/admin/src/components/List/index.js +0 -81
  90. package/admin/src/components/Option/OptionButton.js +0 -18
  91. package/admin/src/components/Option/OptionSet.js +0 -14
  92. package/admin/src/components/Option/Wrapper.js +0 -15
  93. package/admin/src/components/Option/index.js +0 -47
  94. package/admin/src/components/Search/index.js +0 -86
  95. package/admin/src/components/Select/ClearIndicator.js +0 -15
  96. package/admin/src/components/Select/DropdownIndicator.js +0 -39
  97. package/admin/src/components/Select/ErrorMessage.js +0 -10
  98. package/admin/src/components/Select/IndicatorSeparator.js +0 -3
  99. package/admin/src/components/Select/MultiValueContainer.js +0 -43
  100. package/admin/src/components/Select/StyledOption.js +0 -11
  101. package/admin/src/components/Select/index.js +0 -68
  102. package/admin/src/components/Select/utils/styles.js +0 -92
  103. package/admin/src/containers/App/Wrapper.js +0 -14
  104. package/admin/src/containers/App/index.js +0 -34
  105. package/admin/src/containers/DetailsView/Wrapper.js +0 -21
  106. package/admin/src/containers/DetailsView/index.js +0 -111
  107. package/admin/src/containers/Initializer/index.js +0 -26
  108. package/admin/src/containers/ListView/Footer.js +0 -56
  109. package/admin/src/containers/ListView/components.js +0 -138
  110. package/admin/src/containers/ListView/index.js +0 -54
  111. package/admin/src/containers/View/FadedWrapper.js +0 -51
  112. package/admin/src/containers/View/HeaderForm.js +0 -9
  113. package/admin/src/containers/View/HeaderFormCell.js +0 -25
  114. package/admin/src/containers/View/Wrapper.js +0 -17
  115. package/admin/src/containers/View/components/NavigationItemForm/ModalFooter.js +0 -45
  116. package/admin/src/containers/View/components/NavigationItemForm/index.js +0 -427
  117. package/admin/src/containers/View/components/NavigationItemPopup/MediumPopup.js +0 -6
  118. package/admin/src/containers/View/index.js +0 -240
  119. package/admin/src/lifecycles.js +0 -3
  120. package/admin/src/permissions.js +0 -14
  121. package/config/functions/bootstrap.js +0 -138
  122. package/config/routes.json +0 -60
  123. package/config/schema.graphql.js +0 -204
  124. package/examples/audit-log-integrations.js.md +0 -38
  125. package/models/navigation.settings.json +0 -43
  126. package/public/assets/preview.png +0 -0
  127. package/services/navigation.js +0 -730
  128. package/services/utils/functions.js +0 -186
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Strapi - Navigation plugin
1
+ # Strapi v4 - Navigation plugin - BETA
2
2
 
3
3
  <p align="center">
4
4
  <a href="https://www.npmjs.org/package/strapi-plugin-navigation">
@@ -21,7 +21,10 @@ A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provid
21
21
  - Tree (nested)
22
22
  - RFR (ready for handling by Redux First Router)
23
23
 
24
- <img src="public/assets/preview.png" alt="UI preview" />
24
+ ### Versions
25
+
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)
25
28
 
26
29
  ### ⏳ Installation
27
30
 
@@ -55,10 +58,9 @@ Complete installation requirements are exact same as for Strapi itself and can b
55
58
 
56
59
  **Supported Strapi versions**:
57
60
 
58
- - Strapi v3.6.8 (recently tested)
59
- - Strapi v3.x
61
+ - Strapi v4.0.2 (recently tested)
60
62
 
61
- (This plugin may work with the older Strapi versions, but these are not tested nor officially supported at this time.)
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.)
62
64
 
63
65
  **We recommend always using the latest version of Strapi to start your new projects**.
64
66
 
@@ -73,22 +75,40 @@ Complete installation requirements are exact same as for Strapi itself and can b
73
75
 
74
76
  ## Content Type model relation to Navigation Item
75
77
 
76
- We can define in `config/plugins.js`
77
- ```js
78
- navigation: {
79
- ...
80
- relatedContentTypes: [
81
- 'application::pages.pages'
82
- ],
83
- ...
84
- },
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
+ },
85
104
  ```
86
105
 
87
106
  ## Configuration
88
- To setup the plugin properly we recommend to put following snippet as part of `config/plugins.js` or `config/<env>/plugins.js` file. If you've got already configurations for other plugins stores by this way, use just the `navigation` part within exising `plugins` item.
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.
89
108
 
90
109
  ```js
91
110
  ...
111
+ plugins: {
92
112
  navigation: {
93
113
  additionalFields: ['audience'],
94
114
  allowedLevels: 2,
@@ -98,6 +118,7 @@ To setup the plugin properly we recommend to put following snippet as part of `c
98
118
  },
99
119
  gql: { ... }
100
120
  },
121
+ },
101
122
  ...
102
123
  ```
103
124
 
@@ -1,7 +1,6 @@
1
1
  import styled from "styled-components";
2
- import { Button } from "@buffetjs/styles";
3
-
4
- import { colors } from "strapi-helper-plugin";
2
+ import { Box } from '@strapi/design-system/Box';
3
+ import { Button } from "@strapi/design-system/Button";
5
4
 
6
5
  const EmptyView = styled.div`
7
6
  display: flex;
@@ -11,24 +10,16 @@ const EmptyView = styled.div`
11
10
  justify-content: center;
12
11
  padding-left: 2rem;
13
12
  padding-right: 2rem;
14
- padding-bottom: ${(props) => (props.fixPosition ? "8rem" : 0)};
13
+ padding-bottom: "8rem" };
15
14
 
16
15
  font-size: 2rem;
17
16
  font-weight: 600;
18
- color: ${colors.leftMenu.grey};
17
+ color: ${({ theme }) => theme.colors.neutral600};
19
18
  text-align: center;
20
19
 
21
- svg {
22
- margin-bottom: 1rem;
23
- }
24
-
25
- ${Button} {
26
- margin-top: 2rem;
27
-
28
- svg {
29
- margin-bottom: 0;
30
- }
31
- }
20
+ > {
21
+ margin: 1rem;
22
+ }
32
23
  `;
33
24
 
34
25
  export default EmptyView;
@@ -0,0 +1,8 @@
1
+ import styled from "styled-components";
2
+ import { Badge } from '@strapi/design-system/Badge';
3
+
4
+ const ItemCardBadge = styled(Badge)`
5
+ border: 1px solid ${({ theme, borderColor }) => theme.colors[borderColor]}
6
+ `;
7
+
8
+ export default ItemCardBadge;
@@ -0,0 +1,21 @@
1
+ import styled from "styled-components";
2
+ import { CardTitle } from '@strapi/design-system/Card';
3
+
4
+ const CardItemTitle = styled(CardTitle)`
5
+ width: 100%;
6
+
7
+ display: flex;
8
+ flex-direction: row;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+
12
+ color: ${({ theme }) => theme.colors.neutral800};
13
+ font-size: ${({ theme }) => theme.fontSizes[2]};
14
+ font-weight: ${({ theme }) => theme.fontWeights.bold};
15
+
16
+ > div > * {
17
+ margin: 0px ${({ theme }) => theme.spaces[1]};
18
+ }
19
+ `;
20
+
21
+ export default CardItemTitle;
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+
4
+ import { Flex } from '@strapi/design-system/Flex';
5
+ import { IconButton } from '@strapi/design-system/IconButton';
6
+ import { Typography } from '@strapi/design-system/Typography';
7
+ import PencilIcon from '@strapi/icons/Pencil';
8
+ import TrashIcon from '@strapi/icons/Trash';
9
+ import RefreshIcon from '@strapi/icons/Refresh';
10
+
11
+ import Wrapper from './Wrapper';
12
+ import ItemCardBadge from '../ItemCardBadge';
13
+ import { getTrad } from "../../../translations";
14
+
15
+ const ItemCardHeader = ({ title, path, icon, removed, isPublished, onItemRemove, onItemEdit, onItemRestore }) => {
16
+ const badgeColor = isPublished ? 'success' : 'secondary';
17
+ const { formatMessage } = useIntl();
18
+
19
+ return (
20
+ <Wrapper>
21
+ <Flex alignItems="center">
22
+ {icon}
23
+ <Typography variant="omega" fontWeight="bold">
24
+ {title}
25
+ </Typography>
26
+ <Typography variant="omega" fontWeight="bold" textColor='neutral500'>
27
+ {path}
28
+ </Typography>
29
+ </Flex>
30
+ <Flex alignItems="center">
31
+ {removed ?
32
+ <ItemCardBadge
33
+ borderColor={`danger200`}
34
+ backgroundColor={`danger100`}
35
+ textColor={`danger600`}
36
+ >
37
+ {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>
47
+ }
48
+
49
+ <IconButton disabled={removed} onClick={onItemEdit} label="Edit" icon={<PencilIcon />} />
50
+ {removed ?
51
+ <IconButton onClick={onItemRestore} label="Restore" icon={<RefreshIcon />} /> :
52
+ <IconButton onClick={onItemRemove} label="Remove" icon={<TrashIcon />} />
53
+ }
54
+ </Flex>
55
+ </Wrapper>
56
+ );
57
+ }
58
+
59
+ export default ItemCardHeader;
@@ -0,0 +1,39 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div`
4
+ position: relative;
5
+ margin-top: ${({theme}) => theme.spaces[2]};
6
+ margin-left: ${({ theme, level }) => level && theme.spaces[8]}};
7
+
8
+ ${({ level, theme, isLast }) => level && `
9
+ &::before {
10
+ ${!isLast && 'content: "";'}
11
+ display: block;
12
+ top: ${theme.spaces[1]};
13
+ left: -24px;
14
+ position: absolute;
15
+ height: calc(100% + ${theme.spaces[2]});
16
+ width: 19px;
17
+ border: 0px solid transparent;
18
+ border-left: 4px solid ${theme.colors.neutral300};
19
+ }
20
+
21
+ &::after {
22
+ content: "";
23
+ display: block;
24
+ height: 22px;
25
+ width: 19px;
26
+ position: absolute;
27
+ top: ${theme.spaces[1]};
28
+ left: -${theme.spaces[6]};
29
+
30
+ background: transparent;
31
+ border: 4px solid ${theme.colors.neutral300};
32
+ border-top: transparent;
33
+ border-right: transparent;
34
+ border-radius: 0 0 0 100%;
35
+ }
36
+ `};
37
+ `;
38
+
39
+ export default Wrapper;
@@ -1,42 +1,35 @@
1
- import React from 'react';
2
- import { useIntl } from 'react-intl';
3
1
  import PropTypes from 'prop-types';
4
- import { isEmpty, isNil, isNumber } from 'lodash';
5
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
- import { faPlus } from '@fortawesome/free-solid-svg-icons';
7
- import { Button } from '@buffetjs/core';
8
- import CardWrapper from './CardWrapper';
9
- import CardItem from './CardItem';
10
- import ItemFooter from '../ItemFooter';
11
- import { navigationItemType } from '../../containers/View/utils/enums';
12
- import CardItemPath from './CardItemPath';
13
- import CardItemTitle from './CardItemTitle';
14
- import CardItemLevelAdd from './CardItemLevelAdd';
15
- import List from '../List';
16
- import CardItemLevelWrapper from './CardItemLevelWrapper';
17
- import CardItemRestore from './CardItemRestore';
18
- import ItemOrdering from '../ItemOrdering';
2
+ import React from 'react';
3
+ import { isEmpty, isNumber } from 'lodash';
4
+ import { useIntl } from "react-intl";
5
+
6
+ import { Card, CardBody } from '@strapi/design-system/Card';
7
+ import { Divider } from '@strapi/design-system/Divider';
8
+ import { TextButton } from '@strapi/design-system/TextButton';
9
+ import { Typography } from '@strapi/design-system/Typography';
10
+ import PlusIcon from '@strapi/icons/Plus';
11
+ import EarthIcon from '@strapi/icons/Earth';
12
+ import LinkIcon from '@strapi/icons/Link';
13
+
14
+ import { navigationItemType } from '../../pages/View/utils/enums';
15
+ import ItemCardHeader from './ItemCardHeader';
16
+ import List from '../NavigationItemList';
17
+ import Wrapper from './Wrapper';
19
18
  import { getTrad } from '../../translations';
20
- import { extractRelatedItemLabel } from '../../containers/View/utils/parsers';
21
19
 
22
20
  const Item = (props) => {
23
- const { formatMessage } = useIntl();
24
-
25
21
  const {
26
22
  item,
23
+ isLast = false,
27
24
  level = 0,
28
25
  levelPath = '',
29
26
  allowedLevels,
30
- contentTypesNameFields,
31
- contentTypes,
32
27
  relatedRef,
33
- isFirst = false,
34
- isLast = false,
35
28
  isParentAttachedToMenu,
36
- onItemClick,
37
- onItemReOrder,
38
- onItemRestoreClick,
39
- onItemLevelAddClick,
29
+ onItemLevelAdd,
30
+ onItemRemove,
31
+ onItemRestore,
32
+ onItemEdit,
40
33
  error,
41
34
  } = props;
42
35
 
@@ -45,108 +38,71 @@ const Item = (props) => {
45
38
  title,
46
39
  type,
47
40
  path,
48
- relatedType,
49
41
  removed,
50
42
  externalPath,
51
43
  menuAttached,
52
44
  } = item;
53
45
 
54
- const isRelationDefined = !isNil(relatedRef);
55
-
56
- const formatRelationName = () =>
57
- isRelationDefined ? extractRelatedItemLabel(relatedRef, contentTypesNameFields) : '';
58
-
59
- const footerProps = {
60
- contentTypes,
61
- type: type || navigationItemType.INTERNAL,
62
- removed,
63
- menuAttached,
64
- relatedRef,
65
- relatedType,
66
- attachButtons: !(isFirst && isLast),
67
- formatRelationName,
68
- };
69
-
70
- const cardTitle = isRelationDefined && !title ? formatRelationName() : title;
46
+ const { formatMessage } = useIntl();
47
+ const isExternal = type === navigationItemType.EXTERNAL;
48
+ const isPublished = relatedRef && relatedRef?.publishedAt;
71
49
  const isNextMenuAllowedLevel = isNumber(allowedLevels) ? level < (allowedLevels - 1) : true;
72
50
  const isMenuAllowedLevel = isNumber(allowedLevels) ? level < allowedLevels : true;
73
- const isExternal = item.type === navigationItemType.EXTERNAL;
74
- const absolutePath = isExternal ? undefined : `${levelPath === '/' ? '' : levelPath}/${path === '/' ? '' : path}`;
75
51
  const hasChildren = !isEmpty(item.items) && !isExternal;
76
-
77
- const handleReOrder = (e, moveBy = 0) => onItemReOrder(e, {
78
- ...item,
79
- relatedRef,
80
- }, moveBy);
81
-
82
- const hasError = error?.parentId === item.parent && error?.errorTitles.includes(cardTitle);
52
+ const absolutePath = isExternal ? undefined : `${levelPath === '/' ? '' : levelPath}/${path === '/' ? '' : path}`;
83
53
 
84
54
  return (
85
- <CardWrapper
86
- level={level}
87
- error={hasError}
88
- >
89
- <CardItem
90
- hasChildren={hasChildren}
91
- removed={removed}
92
- hasError={hasError}
93
- onClick={(e) =>
94
- removed ? null : onItemClick(e, {
95
- ...item,
96
- isMenuAllowedLevel,
97
- isParentAttachedToMenu,
98
- }, levelPath)
99
- }
100
- >
101
- {removed && (<CardItemRestore>
102
- <Button
103
- onClick={e => onItemRestoreClick(e, item)}
104
- color="secondary"
105
- label={formatMessage(getTrad('popup.item.form.button.restore'))}
55
+ <Wrapper level={level} isLast={isLast}>
56
+ <Card style={{ width: "728px", zIndex: 1, position: "relative" }}>
57
+ <CardBody>
58
+ <ItemCardHeader
59
+ title={title}
60
+ path={isExternal ? externalPath : absolutePath}
61
+ icon={isExternal ? <EarthIcon /> : <LinkIcon />}
62
+ isPublished={isPublished}
63
+ onItemRemove={() => onItemRemove(item)}
64
+ onItemEdit={() => onItemEdit({
65
+ ...item,
66
+ isMenuAllowedLevel,
67
+ isParentAttachedToMenu,
68
+ }, levelPath, isParentAttachedToMenu)}
69
+ onItemRestore={() => onItemRestore(item)}
70
+ removed={removed}
106
71
  />
107
- </CardItemRestore>)}
108
- <CardItemTitle>{cardTitle}</CardItemTitle>
109
- <CardItemPath>
110
- {isExternal ? externalPath : absolutePath}
111
- </CardItemPath>
112
- <ItemFooter {...footerProps} />
113
- <ItemOrdering
114
- isFirst={isFirst}
115
- isLast={isLast}
116
- onChangeOrder={handleReOrder}
117
- />
118
- </CardItem>
119
- {!(isExternal || removed) && (
120
- <CardItemLevelAdd
121
- color={isNextMenuAllowedLevel ? 'primary' : 'secondary'}
122
- icon={<FontAwesomeIcon icon={faPlus} size="3x" />}
123
- onClick={(e) => onItemLevelAddClick(e, viewId, isNextMenuAllowedLevel, levelPath, menuAttached)}
124
- menuLevel={isNextMenuAllowedLevel}
125
- />
126
- )}
127
- {hasChildren && !removed && (
128
- <List
129
- items={item.items}
130
- onItemClick={onItemClick}
131
- onItemReOrder={onItemReOrder}
132
- onItemRestoreClick={onItemRestoreClick}
133
- onItemLevelAddClick={onItemLevelAddClick}
134
- as={CardItemLevelWrapper}
135
- level={level + 1}
136
- levelPath={absolutePath}
137
- allowedLevels={allowedLevels}
138
- isParentAttachedToMenu={menuAttached}
139
- contentTypesNameFields={contentTypesNameFields}
140
- contentTypes={contentTypes}
141
- error={error}
142
- />
143
- )}
144
- </CardWrapper>
72
+ </CardBody>
73
+ <Divider />
74
+ <CardBody style={{ margin: '8px' }}>
75
+ <TextButton
76
+ disabled={removed}
77
+ startIcon={<PlusIcon />}
78
+ onClick={(e) => onItemLevelAdd(e, viewId, isNextMenuAllowedLevel, absolutePath, menuAttached)}
79
+ >
80
+ <Typography variant="pi" fontWeight="bold" textColor={removed ? "neutral600" : "primary600"}>
81
+ {formatMessage(getTrad("navigation.item.action.newItem"))}
82
+ </Typography>
83
+ </TextButton>
84
+ </CardBody>
85
+ </Card>
86
+ {hasChildren && !removed && <List
87
+ onItemLevelAdd={onItemLevelAdd}
88
+ onItemRemove={onItemRemove}
89
+ onItemEdit={onItemEdit}
90
+ onItemRestore={onItemRestore}
91
+ error={error}
92
+ allowedLevels={allowedLevels}
93
+ isParentAttachedToMenu={true}
94
+ items={item.items}
95
+ level={level + 1}
96
+ levelPath={absolutePath}
97
+ />
98
+ }
99
+ </Wrapper>
100
+
145
101
  );
146
102
  };
147
103
 
148
104
  Item.propTypes = {
149
- item: PropTypes.objectOf({
105
+ item: PropTypes.shape({
150
106
  title: PropTypes.string,
151
107
  type: PropTypes.string,
152
108
  uiRouterKey: PropTypes.string,
@@ -154,19 +110,15 @@ Item.propTypes = {
154
110
  externalPath: PropTypes.string,
155
111
  audience: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
156
112
  related: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
157
- menuAttached: PropTypes.bool,
113
+ menuAttached: PropTypes.bool
158
114
  }).isRequired,
159
115
  relatedRef: PropTypes.object,
160
- contentTypes: PropTypes.array,
161
- contentTypesNameFields: PropTypes.object.isRequired,
162
116
  level: PropTypes.number,
163
117
  levelPath: PropTypes.string,
164
- isFirst: PropTypes.bool,
165
- isLast: PropTypes.bool,
166
118
  isParentAttachedToMenu: PropTypes.bool,
167
- onItemClick: PropTypes.func.isRequired,
168
- onItemRestoreClick: PropTypes.func.isRequired,
169
- onItemLevelAddClick: PropTypes.func.isRequired,
119
+ onItemRestore: PropTypes.func.isRequired,
120
+ onItemLevelAdd: PropTypes.func.isRequired,
121
+ onItemRemove: PropTypes.func.isRequired,
170
122
  };
171
123
 
172
- export default Item;
124
+ export default Item;
@@ -0,0 +1,22 @@
1
+ import styled from 'styled-components';
2
+
3
+ const Wrapper = styled.div`
4
+ position: relative;
5
+ ${({ level, theme }) => level && `
6
+ &::before {
7
+ content: "";
8
+ display: block;
9
+ height: ${theme.spaces[3]};
10
+ width: 19px;
11
+
12
+ position: absolute;
13
+ top: -${theme.spaces[2]};
14
+ left: ${theme.spaces[4]};
15
+
16
+ border: 0px solid transparent;
17
+ border-left: 4px solid ${theme.colors.neutral300};
18
+ }
19
+ `};
20
+ `;
21
+
22
+ export default Wrapper;
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import PropTypes from "prop-types";
3
+
4
+ import Item from "../Item";
5
+ import Wrapper from "./Wrapper";
6
+
7
+ const List = ({
8
+ allowedLevels,
9
+ error,
10
+ isParentAttachedToMenu = false,
11
+ items,
12
+ level = 0,
13
+ levelPath = '',
14
+ onItemEdit,
15
+ onItemLevelAdd,
16
+ onItemRemove,
17
+ onItemRestore,
18
+ }) => (
19
+ <Wrapper level={level}>
20
+ {items.map((item, n) => {
21
+ const { relatedRef, ...itemProps } = item
22
+ return (
23
+ <Item
24
+ key={`list-item-${item.viewId || n}`}
25
+ item={itemProps}
26
+ isLast={n === items.length - 1}
27
+ relatedRef={relatedRef}
28
+ level={level}
29
+ levelPath={levelPath}
30
+ isParentAttachedToMenu={isParentAttachedToMenu}
31
+ allowedLevels={allowedLevels}
32
+ onItemRestore={onItemRestore}
33
+ onItemLevelAdd={onItemLevelAdd}
34
+ onItemRemove={onItemRemove}
35
+ onItemEdit={onItemEdit}
36
+ error={error}
37
+ />
38
+ );
39
+ })}
40
+ </Wrapper>
41
+ );
42
+
43
+ List.propTypes = {
44
+ allowedLevels: PropTypes.number,
45
+ isParentAttachedToMenu: PropTypes.bool,
46
+ items: PropTypes.array,
47
+ level: PropTypes.number,
48
+ onItemLevelAdd: PropTypes.func.isRequired,
49
+ onItemRemove: PropTypes.func.isRequired,
50
+ onItemRestore: PropTypes.func.isRequired,
51
+ onItemRestore: PropTypes.func.isRequired,
52
+ };
53
+
54
+ export default List;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import Puzzle from '@strapi/icons/Puzzle';
3
+
4
+ const PluginIcon = () => <Puzzle />;
5
+
6
+ export default PluginIcon;