strapi-plugin-navigation 1.1.0 → 2.0.0-beta.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 +7 -5
- package/admin/src/components/EmptyView/index.js +7 -16
- package/admin/src/components/Item/ItemCardBadge/index.js +8 -0
- package/admin/src/components/Item/ItemCardHeader/Wrapper.js +21 -0
- package/admin/src/components/Item/ItemCardHeader/index.js +59 -0
- package/admin/src/components/Item/Wrapper.js +39 -0
- package/admin/src/components/Item/index.js +76 -124
- package/admin/src/components/NavigationItemList/Wrapper.js +22 -0
- package/admin/src/components/NavigationItemList/index.js +54 -0
- package/admin/src/components/PluginIcon/index.js +6 -0
- package/admin/src/index.js +49 -45
- package/admin/src/pages/App/index.js +31 -0
- package/admin/src/{containers → pages}/DataManagerProvider/actions.js +0 -0
- package/admin/src/{containers → pages}/DataManagerProvider/index.js +81 -85
- package/admin/src/{containers → pages}/DataManagerProvider/init.js +0 -0
- package/admin/src/{containers → pages}/DataManagerProvider/reducer.js +0 -0
- package/admin/src/pages/View/components/NavigationContentHeader/index.js +18 -0
- package/admin/src/pages/View/components/NavigationHeader/index.js +60 -0
- package/admin/src/pages/View/components/NavigationItemForm/index.js +403 -0
- package/admin/src/{containers → pages}/View/components/NavigationItemForm/utils/form.js +2 -2
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +40 -0
- package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +20 -0
- package/admin/src/{containers → pages}/View/components/NavigationItemPopup/index.js +16 -16
- package/admin/src/pages/View/index.js +209 -0
- package/admin/src/{containers → pages}/View/utils/enums.js +0 -0
- package/admin/src/{containers → pages}/View/utils/form.js +1 -1
- package/admin/src/{containers → pages}/View/utils/index.js +0 -0
- package/admin/src/{containers → pages}/View/utils/parsers.js +13 -12
- package/admin/src/pluginId.js +3 -2
- package/admin/src/translations/en.json +47 -38
- package/admin/src/translations/fr.json +7 -1
- package/admin/src/utils/getTrad.js +2 -2
- package/package.json +14 -6
- package/server/bootstrap.js +41 -0
- package/server/config.js +8 -0
- package/server/content-types/audience/index.js +9 -0
- package/{models/audience.js → server/content-types/audience/lifecycle.js} +0 -0
- package/{models/audience.settings.json → server/content-types/audience/schema.json} +4 -2
- package/server/content-types/index.js +13 -0
- package/server/content-types/navigation/index.js +9 -0
- package/{models/navigation.js → server/content-types/navigation/lifecycle.js} +0 -0
- package/server/content-types/navigation/schema.js +45 -0
- package/server/content-types/navigation-item/index.js +9 -0
- package/{models/navigationItem.js → server/content-types/navigation-item/lifecycle.js} +0 -0
- package/{models/navigationItem.settings.json → server/content-types/navigation-item/schema.json} +16 -12
- package/server/content-types/navigations-items-related/index.js +9 -0
- package/{models/navigations_items_related.js → server/content-types/navigations-items-related/lifecycle.js} +0 -0
- package/{models/navigations_items_related.settings.json → server/content-types/navigations-items-related/schema.json} +4 -2
- package/server/controllers/index.js +7 -0
- package/{controllers → server/controllers}/navigation.js +7 -39
- package/server/routes/admin.js +38 -0
- package/server/routes/index.js +3 -0
- package/{services → server/services}/__tests__/navigation.test.js +0 -0
- package/server/services/index.js +7 -0
- package/server/services/navigation.js +463 -0
- package/{services → server/services}/utils/constant.js +3 -1
- package/server/services/utils/functions.js +103 -0
- package/strapi-admin.js +1 -0
- package/strapi-server.js +18 -0
- package/__mocks__/helpers/another-plugin/blog-post.settings.json +0 -31
- package/__mocks__/helpers/another-plugin/pages.settings.json +0 -28
- package/__mocks__/helpers/blog-post.settings.json +0 -31
- package/__mocks__/helpers/home-page.settings.json +0 -4
- package/__mocks__/helpers/my-homepage.settings.json +0 -27
- package/__mocks__/helpers/pages.settings.json +0 -27
- package/__mocks__/helpers/strapi.js +0 -101
- package/admin/src/assets/images/icon-cross-blue.svg +0 -1
- package/admin/src/assets/images/icon_remove.svg +0 -19
- package/admin/src/components/Container/index.js +0 -7
- package/admin/src/components/Input/index.js +0 -41
- package/admin/src/components/Item/CardItem.js +0 -46
- package/admin/src/components/Item/CardItemLevelAdd.js +0 -41
- package/admin/src/components/Item/CardItemLevelWrapper.js +0 -27
- package/admin/src/components/Item/CardItemPath.js +0 -9
- package/admin/src/components/Item/CardItemRestore.js +0 -19
- package/admin/src/components/Item/CardItemTitle.js +0 -5
- package/admin/src/components/Item/CardWrapper.js +0 -78
- package/admin/src/components/ItemFooter/CardItemError.js +0 -11
- package/admin/src/components/ItemFooter/CardItemRelation.js +0 -18
- package/admin/src/components/ItemFooter/CardItemRelationStatus.js +0 -17
- package/admin/src/components/ItemFooter/CardItemType.js +0 -18
- package/admin/src/components/ItemFooter/Wrapper.js +0 -26
- package/admin/src/components/ItemFooter/index.js +0 -66
- package/admin/src/components/ItemOrdering/CardOrderingButton.js +0 -24
- package/admin/src/components/ItemOrdering/Wrapper.js +0 -24
- package/admin/src/components/ItemOrdering/index.js +0 -36
- package/admin/src/components/List/Container.js +0 -34
- package/admin/src/components/List/ListLevelRoot.js +0 -18
- package/admin/src/components/List/index.js +0 -81
- package/admin/src/components/Option/OptionButton.js +0 -18
- package/admin/src/components/Option/OptionSet.js +0 -14
- package/admin/src/components/Option/Wrapper.js +0 -15
- package/admin/src/components/Option/index.js +0 -47
- package/admin/src/components/Search/index.js +0 -86
- package/admin/src/components/Select/ClearIndicator.js +0 -15
- package/admin/src/components/Select/DropdownIndicator.js +0 -39
- package/admin/src/components/Select/ErrorMessage.js +0 -10
- package/admin/src/components/Select/IndicatorSeparator.js +0 -3
- package/admin/src/components/Select/MultiValueContainer.js +0 -43
- package/admin/src/components/Select/StyledOption.js +0 -11
- package/admin/src/components/Select/index.js +0 -68
- package/admin/src/components/Select/utils/styles.js +0 -92
- package/admin/src/containers/App/Wrapper.js +0 -14
- package/admin/src/containers/App/index.js +0 -34
- package/admin/src/containers/DetailsView/Wrapper.js +0 -21
- package/admin/src/containers/DetailsView/index.js +0 -111
- package/admin/src/containers/Initializer/index.js +0 -26
- package/admin/src/containers/ListView/Footer.js +0 -56
- package/admin/src/containers/ListView/components.js +0 -138
- package/admin/src/containers/ListView/index.js +0 -54
- package/admin/src/containers/View/FadedWrapper.js +0 -51
- package/admin/src/containers/View/HeaderForm.js +0 -9
- package/admin/src/containers/View/HeaderFormCell.js +0 -25
- package/admin/src/containers/View/Wrapper.js +0 -17
- package/admin/src/containers/View/components/NavigationItemForm/ModalFooter.js +0 -45
- package/admin/src/containers/View/components/NavigationItemForm/index.js +0 -427
- package/admin/src/containers/View/components/NavigationItemPopup/MediumPopup.js +0 -6
- package/admin/src/containers/View/index.js +0 -240
- package/admin/src/lifecycles.js +0 -3
- package/admin/src/permissions.js +0 -14
- package/config/functions/bootstrap.js +0 -138
- package/config/routes.json +0 -60
- package/config/schema.graphql.js +0 -205
- package/examples/audit-log-integrations.js.md +0 -38
- package/models/navigation.settings.json +0 -43
- package/public/assets/preview.png +0 -0
- package/services/navigation.js +0 -730
- 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
|
-
|
|
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
|
|
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
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
|
-
import {
|
|
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:
|
|
13
|
+
padding-bottom: "8rem" };
|
|
15
14
|
|
|
16
15
|
font-size: 2rem;
|
|
17
16
|
font-weight: 600;
|
|
18
|
-
color: ${colors.
|
|
17
|
+
color: ${({ theme }) => theme.colors.neutral600};
|
|
19
18
|
text-align: center;
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
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,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
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
55
|
-
|
|
56
|
-
const
|
|
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
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
</
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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.
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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;
|
package/admin/src/index.js
CHANGED
|
@@ -1,49 +1,53 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import lifecycles from "./lifecycles";
|
|
6
|
-
import trads from "./translations";
|
|
7
|
-
import pluginPermissions from "./permissions";
|
|
1
|
+
import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
|
2
|
+
import PluginIcon from './components/PluginIcon';
|
|
3
|
+
import pluginPkg from '../../package.json';
|
|
4
|
+
import pluginId from './pluginId';
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
const pluginDescription =
|
|
11
|
-
pluginPkg.strapi.description || pluginPkg.description;
|
|
12
|
-
const { icon, name } = pluginPkg.strapi;
|
|
6
|
+
const name = pluginPkg.strapi.name;
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
lifecycles,
|
|
26
|
-
leftMenuLinks: [],
|
|
27
|
-
leftMenuSections: [],
|
|
28
|
-
mainComponent: App,
|
|
29
|
-
name,
|
|
30
|
-
preventComponentRendering: false,
|
|
31
|
-
trads,
|
|
32
|
-
menu: {
|
|
33
|
-
pluginsSectionLinks: [
|
|
34
|
-
{
|
|
35
|
-
destination: `/plugins/${pluginId}`,
|
|
36
|
-
icon,
|
|
37
|
-
name,
|
|
38
|
-
label: {
|
|
39
|
-
id: `${pluginId}.plugin.name`,
|
|
40
|
-
defaultMessage: "NAVIGATION",
|
|
41
|
-
},
|
|
42
|
-
permissions: pluginPermissions.main,
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
},
|
|
46
|
-
};
|
|
8
|
+
export default {
|
|
9
|
+
register(app) {
|
|
10
|
+
app.addMenuLink({
|
|
11
|
+
to: `/plugins/${pluginId}`,
|
|
12
|
+
icon: PluginIcon,
|
|
13
|
+
intlLabel: {
|
|
14
|
+
id: `${pluginId}.plugin.name`,
|
|
15
|
+
defaultMessage: 'Navigation',
|
|
16
|
+
},
|
|
17
|
+
Component: async () => {
|
|
18
|
+
const component = await import(/* webpackChunkName: "my-plugin" */ './pages/App');
|
|
47
19
|
|
|
48
|
-
|
|
20
|
+
return component;
|
|
21
|
+
},
|
|
22
|
+
permissions: [],
|
|
23
|
+
});
|
|
24
|
+
app.registerPlugin({
|
|
25
|
+
id: pluginId,
|
|
26
|
+
name,
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
bootstrap() {},
|
|
30
|
+
async registerTrads({ locales }) {
|
|
31
|
+
const importedTrads = await Promise.all(
|
|
32
|
+
locales.map(locale => {
|
|
33
|
+
return import(
|
|
34
|
+
/* webpackChunkName: "[pluginId]-[request]" */ `./translations/${locale}.json`
|
|
35
|
+
)
|
|
36
|
+
.then(({ default: data }) => {
|
|
37
|
+
return {
|
|
38
|
+
data: prefixPluginTranslations(data, pluginId),
|
|
39
|
+
locale,
|
|
40
|
+
};
|
|
41
|
+
})
|
|
42
|
+
.catch(() => {
|
|
43
|
+
return {
|
|
44
|
+
data: {},
|
|
45
|
+
locale,
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return Promise.resolve(importedTrads);
|
|
52
|
+
},
|
|
49
53
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* This component is the skeleton around the actual pages, and should only
|
|
4
|
+
* contain code that should be seen on all pages. (e.g. navigation bar)
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { Suspense, lazy } from "react";
|
|
9
|
+
import { Switch, Route } from "react-router-dom";
|
|
10
|
+
import { NotFound, LoadingIndicatorPage } from "@strapi/helper-plugin";
|
|
11
|
+
// Utils
|
|
12
|
+
import DataManagerProvider from "../DataManagerProvider";
|
|
13
|
+
import pluginId from "../../pluginId";
|
|
14
|
+
// Containers
|
|
15
|
+
const View = lazy(() => import("../View"));
|
|
16
|
+
|
|
17
|
+
const App = () => {
|
|
18
|
+
return (
|
|
19
|
+
<DataManagerProvider>
|
|
20
|
+
<Suspense fallback={<LoadingIndicatorPage />}>
|
|
21
|
+
<Switch>
|
|
22
|
+
<Route path={`/plugins/${pluginId}`} component={View} exact />
|
|
23
|
+
<Route component={NotFound} />
|
|
24
|
+
</Switch>
|
|
25
|
+
</Suspense>
|
|
26
|
+
</DataManagerProvider>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default App;
|
|
31
|
+
|
|
File without changes
|