@strapi/admin 4.6.1 → 4.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/assets/images/onboarding-preview.png +0 -0
- package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +0 -2
- package/admin/src/hooks/useRegenerate/index.js +2 -2
- package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +7 -0
- package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
- package/admin/src/pages/Admin/Onboarding/index.js +161 -89
- package/admin/src/pages/Admin/index.js +5 -2
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components → components/Tokens}/FormHead/index.js +36 -19
- package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +96 -0
- package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +98 -0
- package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +73 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DefaultButton/index.js +1 -1
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DeleteButton/index.js +1 -1
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/ReadButton/index.js +0 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/UpdateButton/index.js +0 -0
- package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +135 -0
- package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components/ContentBox → components/Tokens/TokenBox}/index.js +17 -17
- package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +51 -0
- package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +46 -0
- package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +69 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +5 -3
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +52 -142
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +37 -14
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +5 -13
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +105 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +50 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +201 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +16 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +4 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +10 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +182 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +48 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +14 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +14 -0
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +12 -0
- package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +33 -0
- package/admin/src/permissions/defaultPermissions.js +8 -0
- package/admin/src/translations/en.json +18 -1
- package/build/19eb2dfcf2603eb55733.png +0 -0
- package/build/4649.15cc0afe.chunk.js +30 -0
- package/build/7259.aa68d808.chunk.js +1 -0
- package/build/7407.883fb1f5.chunk.js +1 -0
- package/build/Admin-authenticatedApp.f29f6021.chunk.js +79 -0
- package/build/{Admin_settingsPage.d1493824.chunk.js → Admin_settingsPage.178dc6e3.chunk.js} +25 -25
- package/build/{admin-app.25934eaa.chunk.js → admin-app.77a50e1f.chunk.js} +19 -19
- package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.0db3aec1.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.671e0e26.chunk.js} +1 -1
- package/build/api-tokens-list-page.7387102c.chunk.js +16 -0
- package/build/{content-manager.35ff9726.chunk.js → content-manager.42b24d46.chunk.js} +77 -77
- package/build/en-json.b0748970.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/main.1022ed01.js +4393 -0
- package/build/runtime~main.84941a97.js +2 -0
- package/build/transfer-tokens-create-page.16e23791.chunk.js +1 -0
- package/build/transfer-tokens-edit-page.3886c973.chunk.js +1 -0
- package/build/transfer-tokens-list-page.e8010a89.chunk.js +16 -0
- package/package.json +12 -12
- package/server/bootstrap.js +2 -0
- package/server/config/admin-actions.js +48 -0
- package/server/content-types/index.js +2 -0
- package/server/content-types/transfer-token-permission.js +36 -0
- package/server/content-types/transfer-token.js +66 -0
- package/server/controllers/api-token.js +4 -5
- package/server/controllers/index.js +1 -0
- package/server/controllers/transfer/index.js +13 -0
- package/server/controllers/transfer/runner.js +24 -0
- package/server/controllers/transfer/token.js +131 -0
- package/server/register.js +2 -9
- package/server/routes/index.js +2 -0
- package/server/routes/transfer.js +95 -0
- package/server/services/api-token.js +2 -3
- package/server/services/constants.js +6 -0
- package/server/services/index.js +1 -0
- package/server/services/transfer/index.js +6 -0
- package/server/services/transfer/permission.js +22 -0
- package/server/services/transfer/token.js +409 -0
- package/server/strategies/api-token.js +4 -2
- package/server/strategies/data-transfer.js +107 -0
- package/server/strategies/index.js +1 -0
- package/server/utils/index.d.ts +2 -0
- package/server/validation/api-tokens.js +1 -6
- package/server/validation/transfer/index.js +5 -0
- package/server/validation/transfer/token.js +34 -0
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -78
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +0 -112
- package/build/4318.f96a9d4d.chunk.js +0 -30
- package/build/8633.00ccd382.chunk.js +0 -1
- package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
- package/build/api-tokens-list-page.44a79fda.chunk.js +0 -16
- package/build/en-json.1f137a90.chunk.js +0 -1
- package/build/main.7b151630.js +0 -4377
- package/build/runtime~main.a20d633b.js +0 -2
|
Binary file
|
|
@@ -220,8 +220,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
|
|
|
220
220
|
|
|
221
221
|
const onDelete = useCallback(
|
|
222
222
|
async (trackerProperty) => {
|
|
223
|
-
console.log('onDelete');
|
|
224
|
-
|
|
225
223
|
try {
|
|
226
224
|
trackUsageRef.current('willDeleteEntry', trackerProperty);
|
|
227
225
|
|
|
@@ -2,7 +2,7 @@ import { useState } from 'react';
|
|
|
2
2
|
import { get } from 'lodash';
|
|
3
3
|
import { useFetchClient, useNotification } from '@strapi/helper-plugin';
|
|
4
4
|
|
|
5
|
-
const useRegenerate = (id, onRegenerate) => {
|
|
5
|
+
const useRegenerate = (url, id, onRegenerate) => {
|
|
6
6
|
const [isLoadingConfirmation, setIsLoadingConfirmation] = useState(false);
|
|
7
7
|
const toggleNotification = useNotification();
|
|
8
8
|
const { post } = useFetchClient();
|
|
@@ -13,7 +13,7 @@ const useRegenerate = (id, onRegenerate) => {
|
|
|
13
13
|
data: {
|
|
14
14
|
data: { accessKey },
|
|
15
15
|
},
|
|
16
|
-
} = await post(
|
|
16
|
+
} = await post(`${url}${id}/regenerate`);
|
|
17
17
|
setIsLoadingConfirmation(false);
|
|
18
18
|
onRegenerate(accessKey);
|
|
19
19
|
} catch (error) {
|
|
@@ -22,6 +22,13 @@ const defaultGlobalLinks = [
|
|
|
22
22
|
isDisplayed: false,
|
|
23
23
|
permissions: adminPermissions.settings['api-tokens'].main,
|
|
24
24
|
},
|
|
25
|
+
{
|
|
26
|
+
intlLabel: { id: 'Settings.transferTokens.title', defaultMessage: 'Transfer Tokens' },
|
|
27
|
+
to: '/settings/transfer-tokens?sort=name:ASC',
|
|
28
|
+
id: 'transfer-tokens',
|
|
29
|
+
isDisplayed: false,
|
|
30
|
+
permissions: adminPermissions.settings['transfer-tokens'].main,
|
|
31
|
+
},
|
|
25
32
|
];
|
|
26
33
|
|
|
27
34
|
export default defaultGlobalLinks;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Book, PaperPlane } from '@strapi/icons';
|
|
2
|
+
|
|
3
|
+
export const VIDEO_LINKS = [
|
|
4
|
+
{
|
|
5
|
+
label: {
|
|
6
|
+
id: 'app.components.Onboarding.link.build-content',
|
|
7
|
+
defaultMessage: 'Build a content architecture',
|
|
8
|
+
},
|
|
9
|
+
href: 'https://www.youtube.com/watch?v=G9GjN0RxhkE',
|
|
10
|
+
duration: '5:48',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: {
|
|
14
|
+
id: 'app.components.Onboarding.link.manage-content',
|
|
15
|
+
defaultMessage: 'Add & manage content',
|
|
16
|
+
},
|
|
17
|
+
href: 'https://www.youtube.com/watch?v=DEZw4KbybAI',
|
|
18
|
+
duration: '3:18',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: { id: 'app.components.Onboarding.link.manage-media', defaultMessage: 'Manage media' },
|
|
22
|
+
href: 'https://www.youtube.com/watch?v=-61MuiMQb38',
|
|
23
|
+
duration: '3:41',
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const WATCH_MORE = {
|
|
28
|
+
href: 'https://www.youtube.com/playlist?list=PL7Q0DQYATmvidz6lEmwE5nIcOAYagxWqq',
|
|
29
|
+
label: {
|
|
30
|
+
id: 'app.components.Onboarding.link.more-videos',
|
|
31
|
+
defaultMessage: 'Watch more videos',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const DOCUMENTATION_LINKS = [
|
|
36
|
+
{
|
|
37
|
+
label: { id: 'global.documentation', defaultMessage: 'documentation' },
|
|
38
|
+
href: 'https://docs.strapi.io',
|
|
39
|
+
icon: Book,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: { id: 'app.static.links.cheatsheet', defaultMessage: 'cheatsheet' },
|
|
43
|
+
href: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
|
|
44
|
+
icon: PaperPlane,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
@@ -1,92 +1,91 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
4
|
+
import {
|
|
5
|
+
Box,
|
|
6
|
+
Button,
|
|
7
|
+
Divider,
|
|
8
|
+
Flex,
|
|
9
|
+
FocusTrap,
|
|
10
|
+
Icon,
|
|
11
|
+
Portal,
|
|
12
|
+
PopoverPrimitives,
|
|
13
|
+
Stack,
|
|
14
|
+
Typography,
|
|
15
|
+
VisuallyHidden,
|
|
16
|
+
} from '@strapi/design-system';
|
|
17
|
+
import { Cross, Play, Question } from '@strapi/icons';
|
|
18
|
+
|
|
19
|
+
import onboardingPreview from '../../../assets/images/onboarding-preview.png';
|
|
20
|
+
import { VIDEO_LINKS, DOCUMENTATION_LINKS, WATCH_MORE } from './constants';
|
|
21
|
+
|
|
22
|
+
// TODO: use new Button props derived from Box props with next DS release
|
|
23
|
+
const HelperButton = styled(Button)`
|
|
21
24
|
border-radius: 50%;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
25
|
+
padding: ${({ theme }) => theme.spaces[3]};
|
|
26
|
+
/* Resetting 2rem height defined by Button component */
|
|
27
|
+
height: 100%;
|
|
26
28
|
`;
|
|
27
29
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
min-width: ${200 / 16}rem;
|
|
31
|
-
position: absolute;
|
|
32
|
-
right: 0;
|
|
30
|
+
const IconWrapper = styled(Flex)`
|
|
31
|
+
transform: translate(-50%, -50%);
|
|
33
32
|
`;
|
|
34
33
|
|
|
35
|
-
const
|
|
34
|
+
const VideoLinkWrapper = styled(Flex)`
|
|
36
35
|
text-decoration: none;
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
:focus-visible {
|
|
38
|
+
outline-offset: ${({ theme }) => `-${theme.spaces[1]}`};
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
background: ${({ theme }) => theme.colors.neutral100};
|
|
41
|
+
:hover {
|
|
42
|
+
background: ${({ theme }) => theme.colors.primary100};
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
/* Hover style for the number displayed */
|
|
45
|
+
${Typography}:first-child {
|
|
46
|
+
color: ${({ theme }) => theme.colors.primary500};
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
/* Hover style for the label */
|
|
50
|
+
${Typography}:nth-child(1) {
|
|
51
|
+
color: ${({ theme }) => theme.colors.primary600};
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
`;
|
|
55
55
|
|
|
56
|
+
const Preview = styled.img`
|
|
57
|
+
width: ${({ theme }) => theme.spaces[10]};
|
|
58
|
+
height: ${({ theme }) => theme.spaces[8]};
|
|
59
|
+
/* Same overlay used in ModalLayout */
|
|
60
|
+
background: ${({ theme }) => `${theme.colors.neutral800}1F`};
|
|
61
|
+
border-radius: ${({ theme }) => theme.borderRadius};
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
const TypographyLineHeight = styled(Typography)`
|
|
65
|
+
/* line height of label and watch more to 1 so they can be better aligned visually */
|
|
66
|
+
line-height: 1;
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const TextLink = styled(TypographyLineHeight)`
|
|
70
|
+
text-decoration: none;
|
|
71
|
+
|
|
72
|
+
:hover {
|
|
73
|
+
text-decoration: underline;
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
|
|
56
77
|
const Onboarding = () => {
|
|
78
|
+
const triggerRef = useRef();
|
|
57
79
|
const [isOpen, setIsOpen] = useState(false);
|
|
58
80
|
const { formatMessage } = useIntl();
|
|
59
|
-
const { showTutorials } = useConfigurations();
|
|
60
|
-
|
|
61
|
-
if (!showTutorials) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
81
|
|
|
65
|
-
const
|
|
66
|
-
{
|
|
67
|
-
Icon: <Book />,
|
|
68
|
-
label: formatMessage({
|
|
69
|
-
id: 'global.documentation',
|
|
70
|
-
defaultMessage: 'Documentation',
|
|
71
|
-
}),
|
|
72
|
-
destination: 'https://docs.strapi.io',
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
Icon: <Information />,
|
|
76
|
-
label: formatMessage({ id: 'app.static.links.cheatsheet', defaultMessage: 'CheatSheet' }),
|
|
77
|
-
destination: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
|
|
78
|
-
},
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
const handleClick = () => {
|
|
82
|
+
const handlePopoverVisibility = () => {
|
|
82
83
|
setIsOpen((prev) => !prev);
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
return (
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
as="button"
|
|
89
|
-
id="onboarding"
|
|
87
|
+
<Box as="aside" position="fixed" bottom={2} right={2}>
|
|
88
|
+
<HelperButton
|
|
90
89
|
aria-label={formatMessage(
|
|
91
90
|
isOpen
|
|
92
91
|
? {
|
|
@@ -98,37 +97,110 @@ const Onboarding = () => {
|
|
|
98
97
|
defaultMessage: 'Open help menu',
|
|
99
98
|
}
|
|
100
99
|
)}
|
|
101
|
-
onClick={
|
|
100
|
+
onClick={handlePopoverVisibility}
|
|
101
|
+
ref={triggerRef}
|
|
102
102
|
>
|
|
103
|
-
<Icon as={isOpen ? Cross : Question}
|
|
104
|
-
</
|
|
103
|
+
<Icon as={isOpen ? Cross : Question} color="buttonNeutral0" />
|
|
104
|
+
</HelperButton>
|
|
105
105
|
|
|
106
|
-
{/* FIX ME - replace with popover when overflow popover is fixed
|
|
107
|
-
+ when v4 mockups for onboarding component are ready */}
|
|
108
106
|
{isOpen && (
|
|
109
|
-
<
|
|
110
|
-
<
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
107
|
+
<Portal>
|
|
108
|
+
<PopoverPrimitives.Content
|
|
109
|
+
padding={0}
|
|
110
|
+
source={triggerRef}
|
|
111
|
+
placement="top-end"
|
|
112
|
+
spacing={12}
|
|
113
|
+
>
|
|
114
|
+
<FocusTrap onEscape={handlePopoverVisibility}>
|
|
115
|
+
<Flex
|
|
116
|
+
justifyContent="space-between"
|
|
117
|
+
paddingBottom={5}
|
|
118
|
+
paddingRight={6}
|
|
119
|
+
paddingLeft={6}
|
|
120
|
+
paddingTop={6}
|
|
121
121
|
>
|
|
122
|
-
<
|
|
123
|
-
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
122
|
+
<TypographyLineHeight fontWeight="bold">
|
|
123
|
+
{formatMessage({
|
|
124
|
+
id: 'app.components.Onboarding.title',
|
|
125
|
+
defaultMessage: 'Get started videos',
|
|
126
|
+
})}
|
|
127
|
+
</TypographyLineHeight>
|
|
128
|
+
<TextLink
|
|
129
|
+
as="a"
|
|
130
|
+
href={WATCH_MORE.href}
|
|
131
|
+
target="_blank"
|
|
132
|
+
rel="noreferrer noopener"
|
|
133
|
+
variant="pi"
|
|
134
|
+
textColor="primary600"
|
|
135
|
+
>
|
|
136
|
+
{formatMessage(WATCH_MORE.label)}
|
|
137
|
+
</TextLink>
|
|
138
|
+
</Flex>
|
|
139
|
+
<Divider />
|
|
140
|
+
{VIDEO_LINKS.map(({ href, duration, label }, index) => (
|
|
141
|
+
<VideoLinkWrapper
|
|
142
|
+
as="a"
|
|
143
|
+
href={href}
|
|
144
|
+
target="_blank"
|
|
145
|
+
rel="noreferrer noopener"
|
|
146
|
+
key={href}
|
|
147
|
+
hasRadius
|
|
148
|
+
paddingTop={4}
|
|
149
|
+
paddingBottom={4}
|
|
150
|
+
paddingLeft={6}
|
|
151
|
+
paddingRight={11}
|
|
152
|
+
>
|
|
153
|
+
<Box paddingRight={5}>
|
|
154
|
+
<Typography textColor="neutral200" variant="alpha">
|
|
155
|
+
{index + 1}
|
|
156
|
+
</Typography>
|
|
157
|
+
</Box>
|
|
158
|
+
<Box position="relative">
|
|
159
|
+
<Preview src={onboardingPreview} alt="" />
|
|
160
|
+
<IconWrapper
|
|
161
|
+
position="absolute"
|
|
162
|
+
top="50%"
|
|
163
|
+
left="50%"
|
|
164
|
+
background="primary600"
|
|
165
|
+
borderRadius="50%"
|
|
166
|
+
justifyContent="center"
|
|
167
|
+
width={6}
|
|
168
|
+
height={6}
|
|
169
|
+
>
|
|
170
|
+
<Icon as={Play} color="buttonNeutral0" width={3} height={3} />
|
|
171
|
+
</IconWrapper>
|
|
172
|
+
</Box>
|
|
173
|
+
<Flex direction="column" alignItems="start" paddingLeft={4}>
|
|
174
|
+
<Typography fontWeight="bold">{formatMessage(label)}</Typography>
|
|
175
|
+
<VisuallyHidden>:</VisuallyHidden>
|
|
176
|
+
<Typography textColor="neutral600" variant="pi">
|
|
177
|
+
{duration}
|
|
178
|
+
</Typography>
|
|
179
|
+
</Flex>
|
|
180
|
+
</VideoLinkWrapper>
|
|
181
|
+
))}
|
|
182
|
+
<Stack spacing={2} paddingLeft={5} paddingTop={2} paddingBottom={5}>
|
|
183
|
+
{DOCUMENTATION_LINKS.map(({ label, href, icon }) => (
|
|
184
|
+
<Stack horizontal spacing={3} key={href}>
|
|
185
|
+
<Icon as={icon} color="primary600" />
|
|
186
|
+
<TextLink
|
|
187
|
+
as="a"
|
|
188
|
+
href={href}
|
|
189
|
+
target="_blank"
|
|
190
|
+
rel="noreferrer noopener"
|
|
191
|
+
variant="sigma"
|
|
192
|
+
textColor="primary700"
|
|
193
|
+
>
|
|
194
|
+
{formatMessage(label)}
|
|
195
|
+
</TextLink>
|
|
196
|
+
</Stack>
|
|
197
|
+
))}
|
|
198
|
+
</Stack>
|
|
199
|
+
</FocusTrap>
|
|
200
|
+
</PopoverPrimitives.Content>
|
|
201
|
+
</Portal>
|
|
130
202
|
)}
|
|
131
|
-
</
|
|
203
|
+
</Box>
|
|
132
204
|
);
|
|
133
205
|
};
|
|
134
206
|
|
|
@@ -10,10 +10,11 @@ import { useTracking, LoadingIndicatorPage, useStrapiApp } from '@strapi/helper-
|
|
|
10
10
|
import { useDispatch, useSelector } from 'react-redux';
|
|
11
11
|
import { DndProvider } from 'react-dnd';
|
|
12
12
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
13
|
+
|
|
13
14
|
import GuidedTourModal from '../../components/GuidedTour/Modal';
|
|
14
15
|
import LeftMenu from '../../components/LeftMenu';
|
|
15
16
|
import AppLayout from '../../layouts/AppLayout';
|
|
16
|
-
import { useMenu } from '../../hooks';
|
|
17
|
+
import { useMenu, useConfigurations } from '../../hooks';
|
|
17
18
|
import { createRoute } from '../../utils';
|
|
18
19
|
import { SET_APP_RUNTIME_STATUS } from '../App/constants';
|
|
19
20
|
import Onboarding from './Onboarding';
|
|
@@ -65,6 +66,7 @@ const Admin = () => {
|
|
|
65
66
|
useTrackUsage();
|
|
66
67
|
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenu();
|
|
67
68
|
const { menu } = useStrapiApp();
|
|
69
|
+
const { showTutorials } = useConfigurations();
|
|
68
70
|
|
|
69
71
|
const routes = useMemo(() => {
|
|
70
72
|
return menu
|
|
@@ -106,7 +108,8 @@ const Admin = () => {
|
|
|
106
108
|
</Switch>
|
|
107
109
|
</Suspense>
|
|
108
110
|
<GuidedTourModal />
|
|
109
|
-
|
|
111
|
+
|
|
112
|
+
{showTutorials && <Onboarding />}
|
|
110
113
|
</AppLayout>
|
|
111
114
|
</DndProvider>
|
|
112
115
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl';
|
|
3
|
-
import { Link } from '@strapi/helper-plugin';
|
|
4
3
|
import PropTypes from 'prop-types';
|
|
4
|
+
import { Link } from '@strapi/helper-plugin';
|
|
5
5
|
import ArrowLeft from '@strapi/icons/ArrowLeft';
|
|
6
6
|
import Check from '@strapi/icons/Check';
|
|
7
7
|
import { Button } from '@strapi/design-system/Button';
|
|
@@ -9,29 +9,36 @@ import { HeaderLayout } from '@strapi/design-system/Layout';
|
|
|
9
9
|
import { Stack } from '@strapi/design-system/Stack';
|
|
10
10
|
import Regenerate from '../Regenerate';
|
|
11
11
|
|
|
12
|
-
const FormHead = ({
|
|
12
|
+
const FormHead = ({
|
|
13
|
+
title,
|
|
14
|
+
token,
|
|
15
|
+
setToken,
|
|
16
|
+
canEditInputs,
|
|
17
|
+
canRegenerate,
|
|
18
|
+
isSubmitting,
|
|
19
|
+
backUrl,
|
|
20
|
+
regenerateUrl,
|
|
21
|
+
}) => {
|
|
13
22
|
const { formatMessage } = useIntl();
|
|
14
23
|
const handleRegenerate = (newKey) => {
|
|
15
|
-
|
|
16
|
-
...
|
|
24
|
+
setToken({
|
|
25
|
+
...token,
|
|
17
26
|
accessKey: newKey,
|
|
18
27
|
});
|
|
19
28
|
};
|
|
20
29
|
|
|
21
30
|
return (
|
|
22
31
|
<HeaderLayout
|
|
23
|
-
title={
|
|
24
|
-
apiToken?.name ||
|
|
25
|
-
formatMessage({
|
|
26
|
-
id: 'Settings.apiTokens.createPage.title',
|
|
27
|
-
defaultMessage: 'Create API Token',
|
|
28
|
-
})
|
|
29
|
-
}
|
|
32
|
+
title={token?.name || formatMessage(title)}
|
|
30
33
|
primaryAction={
|
|
31
34
|
canEditInputs ? (
|
|
32
35
|
<Stack horizontal spacing={2}>
|
|
33
|
-
{canRegenerate &&
|
|
34
|
-
<Regenerate
|
|
36
|
+
{canRegenerate && token?.id && (
|
|
37
|
+
<Regenerate
|
|
38
|
+
backUrl={regenerateUrl}
|
|
39
|
+
onRegenerate={handleRegenerate}
|
|
40
|
+
idToRegenerate={token?.id}
|
|
41
|
+
/>
|
|
35
42
|
)}
|
|
36
43
|
<Button
|
|
37
44
|
disabled={isSubmitting}
|
|
@@ -48,13 +55,17 @@ const FormHead = ({ apiToken, setApiToken, canEditInputs, canRegenerate, isSubmi
|
|
|
48
55
|
</Stack>
|
|
49
56
|
) : (
|
|
50
57
|
canRegenerate &&
|
|
51
|
-
|
|
52
|
-
<Regenerate
|
|
58
|
+
token?.id && (
|
|
59
|
+
<Regenerate
|
|
60
|
+
onRegenerate={handleRegenerate}
|
|
61
|
+
idToRegenerate={token?.id}
|
|
62
|
+
backUrl={regenerateUrl}
|
|
63
|
+
/>
|
|
53
64
|
)
|
|
54
65
|
)
|
|
55
66
|
}
|
|
56
67
|
navigationAction={
|
|
57
|
-
<Link startIcon={<ArrowLeft />} to=
|
|
68
|
+
<Link startIcon={<ArrowLeft />} to={backUrl}>
|
|
58
69
|
{formatMessage({
|
|
59
70
|
id: 'global.back',
|
|
60
71
|
defaultMessage: 'Back',
|
|
@@ -66,7 +77,7 @@ const FormHead = ({ apiToken, setApiToken, canEditInputs, canRegenerate, isSubmi
|
|
|
66
77
|
};
|
|
67
78
|
|
|
68
79
|
FormHead.propTypes = {
|
|
69
|
-
|
|
80
|
+
token: PropTypes.shape({
|
|
70
81
|
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
71
82
|
type: PropTypes.string,
|
|
72
83
|
lifespan: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
@@ -78,12 +89,18 @@ FormHead.propTypes = {
|
|
|
78
89
|
}),
|
|
79
90
|
canEditInputs: PropTypes.bool.isRequired,
|
|
80
91
|
canRegenerate: PropTypes.bool.isRequired,
|
|
81
|
-
|
|
92
|
+
setToken: PropTypes.func.isRequired,
|
|
82
93
|
isSubmitting: PropTypes.bool.isRequired,
|
|
94
|
+
backUrl: PropTypes.string.isRequired,
|
|
95
|
+
title: PropTypes.shape({
|
|
96
|
+
id: PropTypes.string,
|
|
97
|
+
label: PropTypes.string,
|
|
98
|
+
}).isRequired,
|
|
99
|
+
regenerateUrl: PropTypes.string.isRequired,
|
|
83
100
|
};
|
|
84
101
|
|
|
85
102
|
FormHead.defaultProps = {
|
|
86
|
-
|
|
103
|
+
token: undefined,
|
|
87
104
|
};
|
|
88
105
|
|
|
89
106
|
export default FormHead;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { useIntl } from 'react-intl';
|
|
4
|
+
import { usePersistentState } from '@strapi/helper-plugin';
|
|
5
|
+
import { Select, Option } from '@strapi/design-system/Select';
|
|
6
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
7
|
+
import { getDateOfExpiration } from '../../../pages/ApiTokens/EditView/utils';
|
|
8
|
+
|
|
9
|
+
const LifeSpanInput = ({ token, errors, values, onChange, disabled }) => {
|
|
10
|
+
const { formatMessage } = useIntl();
|
|
11
|
+
const [lang] = usePersistentState('strapi-admin-language', 'en');
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
<Select
|
|
16
|
+
name="lifespan"
|
|
17
|
+
label={formatMessage({
|
|
18
|
+
id: 'Settings.apiTokens.form.duration',
|
|
19
|
+
defaultMessage: 'Token duration',
|
|
20
|
+
})}
|
|
21
|
+
value={values.lifespan !== null ? values.lifespan : '0'}
|
|
22
|
+
error={
|
|
23
|
+
errors.lifespan
|
|
24
|
+
? formatMessage(
|
|
25
|
+
errors.lifespan?.id
|
|
26
|
+
? errors.lifespan
|
|
27
|
+
: { id: errors.lifespan, defaultMessage: errors.lifespan }
|
|
28
|
+
)
|
|
29
|
+
: null
|
|
30
|
+
}
|
|
31
|
+
onChange={(value) => {
|
|
32
|
+
onChange({ target: { name: 'lifespan', value } });
|
|
33
|
+
}}
|
|
34
|
+
required
|
|
35
|
+
disabled={disabled}
|
|
36
|
+
placeholder="Select"
|
|
37
|
+
>
|
|
38
|
+
<Option value="604800000">
|
|
39
|
+
{formatMessage({
|
|
40
|
+
id: 'Settings.apiTokens.duration.7-days',
|
|
41
|
+
defaultMessage: '7 days',
|
|
42
|
+
})}
|
|
43
|
+
</Option>
|
|
44
|
+
<Option value="2592000000">
|
|
45
|
+
{formatMessage({
|
|
46
|
+
id: 'Settings.apiTokens.duration.30-days',
|
|
47
|
+
defaultMessage: '30 days',
|
|
48
|
+
})}
|
|
49
|
+
</Option>
|
|
50
|
+
<Option value="7776000000">
|
|
51
|
+
{formatMessage({
|
|
52
|
+
id: 'Settings.apiTokens.duration.90-days',
|
|
53
|
+
defaultMessage: '90 days',
|
|
54
|
+
})}
|
|
55
|
+
</Option>
|
|
56
|
+
<Option value="0">
|
|
57
|
+
{formatMessage({
|
|
58
|
+
id: 'Settings.apiTokens.duration.unlimited',
|
|
59
|
+
defaultMessage: 'Unlimited',
|
|
60
|
+
})}
|
|
61
|
+
</Option>
|
|
62
|
+
</Select>
|
|
63
|
+
<Typography variant="pi" textColor="neutral600">
|
|
64
|
+
{disabled &&
|
|
65
|
+
`${formatMessage({
|
|
66
|
+
id: 'Settings.apiTokens.duration.expiration-date',
|
|
67
|
+
defaultMessage: 'Expiration date',
|
|
68
|
+
})}: ${getDateOfExpiration(token?.createdAt, parseInt(values.lifespan, 10, lang))}`}
|
|
69
|
+
</Typography>
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
LifeSpanInput.propTypes = {
|
|
75
|
+
errors: PropTypes.string,
|
|
76
|
+
onChange: PropTypes.func.isRequired,
|
|
77
|
+
values: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
78
|
+
disabled: PropTypes.bool.isRequired,
|
|
79
|
+
token: PropTypes.shape({
|
|
80
|
+
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
81
|
+
type: PropTypes.string,
|
|
82
|
+
lifespan: PropTypes.string,
|
|
83
|
+
name: PropTypes.string,
|
|
84
|
+
accessKey: PropTypes.string,
|
|
85
|
+
permissions: PropTypes.array,
|
|
86
|
+
description: PropTypes.string,
|
|
87
|
+
createdAt: PropTypes.string,
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
LifeSpanInput.defaultProps = {
|
|
92
|
+
errors: {},
|
|
93
|
+
token: {},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export default LifeSpanInput;
|