@strapi/admin 4.6.2 → 4.7.0-exp.3d6a31eb083e9d44afcf98f68c107fb7567e5720

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 (97) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +0 -2
  2. package/admin/src/hooks/useRegenerate/index.js +2 -2
  3. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +7 -0
  4. package/admin/src/pages/HomePage/CloudBox.js +83 -0
  5. package/admin/src/pages/HomePage/ContentBlocks.js +2 -0
  6. package/admin/src/pages/HomePage/assets/strapi-cloud-background.png +0 -0
  7. package/admin/src/pages/HomePage/assets/strapi-cloud-flags.svg +1 -0
  8. package/admin/src/pages/HomePage/assets/strapi-cloud-icon.svg +1 -0
  9. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components → components/Tokens}/FormHead/index.js +36 -19
  10. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +95 -0
  11. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +97 -0
  12. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +73 -0
  13. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DeleteButton/index.js +19 -6
  14. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +145 -0
  15. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components/ContentBox → components/Tokens/TokenBox}/index.js +19 -16
  16. package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +51 -0
  17. package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +46 -0
  18. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +69 -0
  19. package/admin/src/pages/SettingsPage/components/Tokens/constants.js +2 -0
  20. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +3 -1
  21. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +53 -150
  22. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -1
  23. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +46 -17
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +16 -16
  25. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +101 -0
  26. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +48 -0
  27. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +219 -0
  28. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +16 -0
  29. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +4 -0
  30. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +10 -0
  31. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +194 -0
  32. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +48 -0
  33. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +14 -0
  34. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +14 -0
  35. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +12 -0
  36. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +33 -0
  37. package/admin/src/permissions/defaultPermissions.js +8 -0
  38. package/admin/src/translations/en.json +15 -0
  39. package/build/27d16aefee06412db90a.png +0 -0
  40. package/build/4049.16583eee.chunk.js +1 -0
  41. package/build/4649.b7e84a29.chunk.js +30 -0
  42. package/build/7259.3f04094f.chunk.js +1 -0
  43. package/build/{Admin-authenticatedApp.dd16edad.chunk.js → Admin-authenticatedApp.368164a1.chunk.js} +6 -6
  44. package/build/Admin_homePage.1f10437f.chunk.js +78 -0
  45. package/build/{Admin_settingsPage.3cd54156.chunk.js → Admin_settingsPage.5a329b58.chunk.js} +25 -25
  46. package/build/{admin-app.3a084127.chunk.js → admin-app.df9adf93.chunk.js} +26 -26
  47. package/build/{api-tokens-create-page.a31c7fba.chunk.js → api-tokens-create-page.4328b852.chunk.js} +1 -1
  48. package/build/{api-tokens-edit-page.64fef287.chunk.js → api-tokens-edit-page.bce5050f.chunk.js} +1 -1
  49. package/build/api-tokens-list-page.149903c8.chunk.js +16 -0
  50. package/build/bb3108f7fd1e6179bde1.svg +1 -0
  51. package/build/bb4d0d527bdfb161bc5a.svg +1 -0
  52. package/build/{content-manager.d04b738f.chunk.js → content-manager.6ed87531.chunk.js} +1 -1
  53. package/build/en-json.8e5451b1.chunk.js +1 -0
  54. package/build/index.html +1 -1
  55. package/build/{main.9c01de7f.js → main.8009bfe8.js} +1 -0
  56. package/build/runtime~main.725b20df.js +2 -0
  57. package/build/transfer-tokens-create-page.a1f14bb1.chunk.js +1 -0
  58. package/build/transfer-tokens-edit-page.00ee1c74.chunk.js +1 -0
  59. package/build/transfer-tokens-list-page.1e15926d.chunk.js +16 -0
  60. package/package.json +9 -9
  61. package/server/bootstrap.js +2 -0
  62. package/server/config/admin-actions.js +48 -0
  63. package/server/content-types/index.js +2 -0
  64. package/server/content-types/transfer-token-permission.js +36 -0
  65. package/server/content-types/transfer-token.js +66 -0
  66. package/server/controllers/api-token.js +4 -5
  67. package/server/controllers/index.js +1 -0
  68. package/server/controllers/transfer/index.js +13 -0
  69. package/server/controllers/transfer/runner.js +24 -0
  70. package/server/controllers/transfer/token.js +131 -0
  71. package/server/register.js +2 -9
  72. package/server/routes/index.js +2 -0
  73. package/server/routes/transfer.js +95 -0
  74. package/server/services/api-token.js +2 -3
  75. package/server/services/constants.js +6 -0
  76. package/server/services/index.js +1 -0
  77. package/server/services/transfer/index.js +6 -0
  78. package/server/services/transfer/permission.js +22 -0
  79. package/server/services/transfer/token.js +409 -0
  80. package/server/strategies/api-token.js +4 -2
  81. package/server/strategies/data-transfer.js +107 -0
  82. package/server/strategies/index.js +1 -0
  83. package/server/utils/index.d.ts +2 -0
  84. package/server/validation/api-tokens.js +1 -6
  85. package/server/validation/transfer/index.js +5 -0
  86. package/server/validation/transfer/token.js +34 -0
  87. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -77
  88. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +0 -110
  89. package/build/1341.5d48c79b.chunk.js +0 -1
  90. package/build/4318.9b1ac9bc.chunk.js +0 -30
  91. package/build/Admin_homePage.4b878f04.chunk.js +0 -72
  92. package/build/api-tokens-list-page.370459ba.chunk.js +0 -16
  93. package/build/en-json.9cada7f3.chunk.js +0 -1
  94. package/build/runtime~main.bb1389c9.js +0 -2
  95. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DefaultButton/index.js +1 -1
  96. /package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/ReadButton/index.js +0 -0
  97. /package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/UpdateButton/index.js +0 -0
@@ -0,0 +1,145 @@
1
+ import React from 'react';
2
+ import { useHistory } from 'react-router-dom';
3
+ import PropTypes from 'prop-types';
4
+ import { Typography, Flex, Tbody, Tr, Td } from '@strapi/design-system';
5
+ import {
6
+ RelativeTime,
7
+ onRowClick,
8
+ pxToRem,
9
+ DynamicTable,
10
+ useQueryParams,
11
+ useTracking,
12
+ } from '@strapi/helper-plugin';
13
+ import DeleteButton from './DeleteButton';
14
+ import UpdateButton from './UpdateButton';
15
+ import ReadButton from './ReadButton';
16
+
17
+ const Table = ({
18
+ permissions,
19
+ headers,
20
+ contentType,
21
+ isLoading,
22
+ tokens,
23
+ onConfirmDelete,
24
+ tokenType,
25
+ }) => {
26
+ const { canDelete, canUpdate, canRead } = permissions;
27
+ const withBulkActions = canDelete || canUpdate || canRead;
28
+ const [{ query }] = useQueryParams();
29
+ const [, sortOrder] = query ? query.sort.split(':') : 'ASC';
30
+ const {
31
+ push,
32
+ location: { pathname },
33
+ } = useHistory();
34
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
35
+
36
+ const sortedTokens = tokens.sort((a, b) => {
37
+ const comparison = a.name.localeCompare(b.name);
38
+
39
+ return sortOrder === 'DESC' ? -comparison : comparison;
40
+ });
41
+
42
+ return (
43
+ <DynamicTable
44
+ headers={headers}
45
+ contentType={contentType}
46
+ rows={tokens}
47
+ withBulkActions={withBulkActions}
48
+ isLoading={isLoading}
49
+ onConfirmDelete={onConfirmDelete}
50
+ >
51
+ <Tbody>
52
+ {sortedTokens.map((token) => {
53
+ return (
54
+ <Tr
55
+ key={token.id}
56
+ {...onRowClick({
57
+ fn() {
58
+ trackUsage('willEditTokenFromList', {
59
+ tokenType,
60
+ });
61
+ push(`${pathname}/${token.id}`);
62
+ },
63
+ condition: canUpdate,
64
+ })}
65
+ >
66
+ <Td>
67
+ <Typography textColor="neutral800" fontWeight="bold">
68
+ {token.name}
69
+ </Typography>
70
+ </Td>
71
+ <Td maxWidth={pxToRem(250)}>
72
+ <Typography textColor="neutral800" ellipsis>
73
+ {token.description}
74
+ </Typography>
75
+ </Td>
76
+ <Td>
77
+ <Typography textColor="neutral800">
78
+ <RelativeTime timestamp={new Date(token.createdAt)} />
79
+ </Typography>
80
+ </Td>
81
+ <Td>
82
+ {token.lastUsedAt && (
83
+ <Typography textColor="neutral800">
84
+ <RelativeTime timestamp={new Date(token.lastUsedAt)} />
85
+ </Typography>
86
+ )}
87
+ </Td>
88
+
89
+ {withBulkActions && (
90
+ <Td>
91
+ <Flex justifyContent="end">
92
+ {canUpdate && <UpdateButton tokenName={token.name} tokenId={token.id} />}
93
+ {!canUpdate && canRead && (
94
+ <ReadButton tokenName={token.name} tokenId={token.id} />
95
+ )}
96
+ {canDelete && (
97
+ <DeleteButton
98
+ tokenName={token.name}
99
+ onClickDelete={() => onConfirmDelete(token.id)}
100
+ tokenType={tokenType}
101
+ />
102
+ )}
103
+ </Flex>
104
+ </Td>
105
+ )}
106
+ </Tr>
107
+ );
108
+ })}
109
+ </Tbody>
110
+ </DynamicTable>
111
+ );
112
+ };
113
+
114
+ Table.propTypes = {
115
+ tokens: PropTypes.array,
116
+ permissions: PropTypes.shape({
117
+ canRead: PropTypes.bool,
118
+ canDelete: PropTypes.bool,
119
+ canUpdate: PropTypes.bool,
120
+ }).isRequired,
121
+ headers: PropTypes.arrayOf(
122
+ PropTypes.shape({
123
+ cellFormatter: PropTypes.func,
124
+ key: PropTypes.string.isRequired,
125
+ metadatas: PropTypes.shape({
126
+ label: PropTypes.string.isRequired,
127
+ sortable: PropTypes.bool,
128
+ }).isRequired,
129
+ name: PropTypes.string.isRequired,
130
+ })
131
+ ),
132
+ contentType: PropTypes.string.isRequired,
133
+ isLoading: PropTypes.bool,
134
+ onConfirmDelete: PropTypes.func,
135
+ tokenType: PropTypes.string.isRequired,
136
+ };
137
+
138
+ Table.defaultProps = {
139
+ tokens: [],
140
+ headers: [],
141
+ isLoading: false,
142
+ onConfirmDelete() {},
143
+ };
144
+
145
+ export default Table;
@@ -6,26 +6,28 @@ import { Duplicate, Key } from '@strapi/icons';
6
6
  import PropTypes from 'prop-types';
7
7
  import { CopyToClipboard } from 'react-copy-to-clipboard';
8
8
 
9
- const HeaderContentBox = ({ apiToken }) => {
9
+ const TokenBox = ({ token, tokenType }) => {
10
10
  const { formatMessage } = useIntl();
11
11
  const toggleNotification = useNotification();
12
- const { trackUsage } = useTracking();
12
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
13
13
  const trackUsageRef = useRef(trackUsage);
14
14
 
15
15
  return (
16
16
  <ContentBox
17
17
  endAction={
18
- apiToken && (
18
+ token && (
19
19
  <span style={{ alignSelf: 'start' }}>
20
20
  <CopyToClipboard
21
21
  onCopy={() => {
22
- trackUsageRef.current('didCopyTokenKey');
22
+ trackUsageRef.current('didCopyTokenKey', {
23
+ tokenType,
24
+ });
23
25
  toggleNotification({
24
26
  type: 'success',
25
- message: { id: 'Settings.apiTokens.notification.copied' },
27
+ message: { id: 'Settings.tokens.notification.copied' },
26
28
  });
27
29
  }}
28
- text={apiToken}
30
+ text={token}
29
31
  >
30
32
  <IconButton
31
33
  label={formatMessage({
@@ -41,20 +43,20 @@ const HeaderContentBox = ({ apiToken }) => {
41
43
  )
42
44
  }
43
45
  title={
44
- apiToken ||
46
+ token ||
45
47
  formatMessage({
46
- id: 'Settings.apiTokens.copy.editTitle',
48
+ id: 'Settings.tokens.copy.editTitle',
47
49
  defaultMessage: 'This token isn’t accessible anymore.',
48
50
  })
49
51
  }
50
52
  subtitle={
51
- apiToken
53
+ token
52
54
  ? formatMessage({
53
- id: 'Settings.apiTokens.copy.lastWarning',
55
+ id: 'Settings.tokens.copy.lastWarning',
54
56
  defaultMessage: 'Make sure to copy this token, you won’t be able to see it again!',
55
57
  })
56
58
  : formatMessage({
57
- id: 'Settings.apiTokens.copy.editMessage',
59
+ id: 'Settings.tokens.copy.editMessage',
58
60
  defaultMessage: 'For security reasons, you can only see your token once.',
59
61
  })
60
62
  }
@@ -64,12 +66,13 @@ const HeaderContentBox = ({ apiToken }) => {
64
66
  );
65
67
  };
66
68
 
67
- HeaderContentBox.defaultProps = {
68
- apiToken: null,
69
+ TokenBox.defaultProps = {
70
+ token: null,
69
71
  };
70
72
 
71
- HeaderContentBox.propTypes = {
72
- apiToken: PropTypes.string,
73
+ TokenBox.propTypes = {
74
+ token: PropTypes.string,
75
+ tokenType: PropTypes.string.isRequired,
73
76
  };
74
77
 
75
- export default HeaderContentBox;
78
+ export default TokenBox;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Textarea } from '@strapi/design-system';
5
+
6
+ const TokenDescription = ({ errors, values, onChange, canEditInputs }) => {
7
+ const { formatMessage } = useIntl();
8
+
9
+ return (
10
+ <Textarea
11
+ label={formatMessage({
12
+ id: 'Settings.tokens.form.description',
13
+ defaultMessage: 'Description',
14
+ })}
15
+ name="description"
16
+ error={
17
+ errors.description
18
+ ? formatMessage(
19
+ errors.description?.id
20
+ ? errors.description
21
+ : {
22
+ id: errors.description,
23
+ defaultMessage: errors.description,
24
+ }
25
+ )
26
+ : null
27
+ }
28
+ onChange={onChange}
29
+ disabled={!canEditInputs}
30
+ >
31
+ {values.description}
32
+ </Textarea>
33
+ );
34
+ };
35
+
36
+ TokenDescription.propTypes = {
37
+ errors: PropTypes.shape({
38
+ description: PropTypes.string,
39
+ }),
40
+ onChange: PropTypes.func.isRequired,
41
+ canEditInputs: PropTypes.bool.isRequired,
42
+ values: PropTypes.shape({
43
+ description: PropTypes.string,
44
+ }).isRequired,
45
+ };
46
+
47
+ TokenDescription.defaultProps = {
48
+ errors: {},
49
+ };
50
+
51
+ export default TokenDescription;
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { TextInput } from '@strapi/design-system';
5
+
6
+ const TokenName = ({ errors, values, onChange, canEditInputs }) => {
7
+ const { formatMessage } = useIntl();
8
+
9
+ return (
10
+ <TextInput
11
+ name="name"
12
+ error={
13
+ errors.name
14
+ ? formatMessage(
15
+ errors.name?.id ? errors.name : { id: errors.name, defaultMessage: errors.name }
16
+ )
17
+ : null
18
+ }
19
+ label={formatMessage({
20
+ id: 'Settings.tokens.form.name',
21
+ defaultMessage: 'Name',
22
+ })}
23
+ onChange={onChange}
24
+ value={values.name}
25
+ disabled={!canEditInputs}
26
+ required
27
+ />
28
+ );
29
+ };
30
+
31
+ TokenName.propTypes = {
32
+ errors: PropTypes.shape({
33
+ name: PropTypes.string,
34
+ }),
35
+ onChange: PropTypes.func.isRequired,
36
+ canEditInputs: PropTypes.bool.isRequired,
37
+ values: PropTypes.shape({
38
+ name: PropTypes.string,
39
+ }).isRequired,
40
+ };
41
+
42
+ TokenName.defaultProps = {
43
+ errors: {},
44
+ };
45
+
46
+ export default TokenName;
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+
5
+ import { Select, Option } from '@strapi/design-system';
6
+
7
+ const TokenTypeSelect = ({ errors, values, onChange, canEditInputs, options, label }) => {
8
+ const { formatMessage } = useIntl();
9
+
10
+ return (
11
+ <Select
12
+ name="type"
13
+ label={formatMessage({
14
+ id: label.id,
15
+ defaultMessage: label.defaultMessage,
16
+ })}
17
+ value={values?.type}
18
+ error={
19
+ errors.type
20
+ ? formatMessage(
21
+ errors.type?.id ? errors.type : { id: errors.type, defaultMessage: errors.type }
22
+ )
23
+ : null
24
+ }
25
+ onChange={onChange}
26
+ placeholder="Select"
27
+ required
28
+ disabled={!canEditInputs}
29
+ >
30
+ {options &&
31
+ options.map(({ value, label }) => (
32
+ <Option key={value} value={value}>
33
+ {formatMessage(label)}
34
+ </Option>
35
+ ))}
36
+ </Select>
37
+ );
38
+ };
39
+
40
+ TokenTypeSelect.propTypes = {
41
+ options: PropTypes.arrayOf(
42
+ PropTypes.shape({
43
+ label: PropTypes.shape({
44
+ id: PropTypes.string,
45
+ defaultMessage: PropTypes.string,
46
+ }),
47
+ value: PropTypes.string,
48
+ })
49
+ ),
50
+ errors: PropTypes.shape({
51
+ type: PropTypes.string,
52
+ }),
53
+ onChange: PropTypes.func.isRequired,
54
+ canEditInputs: PropTypes.bool.isRequired,
55
+ values: PropTypes.shape({
56
+ type: PropTypes.string,
57
+ }).isRequired,
58
+ label: PropTypes.shape({
59
+ id: PropTypes.string,
60
+ defaultMessage: PropTypes.string,
61
+ }).isRequired,
62
+ };
63
+
64
+ TokenTypeSelect.defaultProps = {
65
+ errors: {},
66
+ options: [],
67
+ };
68
+
69
+ export default TokenTypeSelect;
@@ -0,0 +1,2 @@
1
+ export const API_TOKEN_TYPE = 'api-token';
2
+ export const TRANSFER_TOKEN_TYPE = 'transfer-token';
@@ -1,5 +1,6 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { capitalize } from 'lodash';
3
+ import { useIntl } from 'react-intl';
3
4
  import {
4
5
  Accordion,
5
6
  AccordionToggle,
@@ -35,6 +36,7 @@ const CollapsableContentType = ({
35
36
  value: { onChangeSelectAll, onChange, selectedActions, setSelectedAction, selectedAction },
36
37
  } = useApiTokenPermissionsContext();
37
38
  const [expanded, setExpanded] = useState(false);
39
+ const { formatMessage } = useIntl();
38
40
 
39
41
  const handleExpandedAccordion = () => {
40
42
  setExpanded((s) => !s);
@@ -88,7 +90,7 @@ const CollapsableContentType = ({
88
90
  }}
89
91
  disabled={disabled}
90
92
  >
91
- Select all
93
+ {formatMessage({ id: 'app.utils.select-all', defaultMessage: 'Select all' })}
92
94
  </Checkbox>
93
95
  </Box>
94
96
  </Flex>
@@ -1,19 +1,11 @@
1
1
  import React from 'react';
2
2
  import { useIntl } from 'react-intl';
3
- import { usePersistentState } from '@strapi/helper-plugin';
4
3
  import PropTypes from 'prop-types';
5
- import {
6
- Box,
7
- Grid,
8
- GridItem,
9
- Select,
10
- Option,
11
- Stack,
12
- Textarea,
13
- TextInput,
14
- Typography,
15
- } from '@strapi/design-system';
16
- import { getDateOfExpiration } from '../../utils';
4
+ import { Box, Grid, GridItem, Stack, Typography } from '@strapi/design-system';
5
+ import LifeSpanInput from '../../../../../components/Tokens/LifeSpanInput';
6
+ import TokenName from '../../../../../components/Tokens/TokenName';
7
+ import TokenDescription from '../../../../../components/Tokens/TokenDescription';
8
+ import TokenTypeSelect from '../../../../../components/Tokens/TokenTypeSelect';
17
9
 
18
10
  const FormApiTokenContainer = ({
19
11
  errors,
@@ -26,7 +18,6 @@ const FormApiTokenContainer = ({
26
18
  setHasChangedPermissions,
27
19
  }) => {
28
20
  const { formatMessage } = useIntl();
29
- const [lang] = usePersistentState('strapi-admin-language', 'en');
30
21
 
31
22
  const handleChangeSelectApiTokenType = ({ target: { value } }) => {
32
23
  setHasChangedPermissions(false);
@@ -43,6 +34,30 @@ const FormApiTokenContainer = ({
43
34
  }
44
35
  };
45
36
 
37
+ const typeOptions = [
38
+ {
39
+ value: 'read-only',
40
+ label: {
41
+ id: 'Settings.apiTokens.types.read-only',
42
+ defaultMessage: 'Read-only',
43
+ },
44
+ },
45
+ {
46
+ value: 'full-access',
47
+ label: {
48
+ id: 'Settings.apiTokens.types.full-access',
49
+ defaultMessage: 'Full access',
50
+ },
51
+ },
52
+ {
53
+ value: 'custom',
54
+ label: {
55
+ id: 'Settings.apiTokens.types.custom',
56
+ defaultMessage: 'Custom',
57
+ },
58
+ },
59
+ ];
60
+
46
61
  return (
47
62
  <Box
48
63
  background="neutral0"
@@ -62,158 +77,46 @@ const FormApiTokenContainer = ({
62
77
  </Typography>
63
78
  <Grid gap={5}>
64
79
  <GridItem key="name" col={6} xs={12}>
65
- <TextInput
66
- name="name"
67
- error={
68
- errors.name
69
- ? formatMessage(
70
- errors.name?.id
71
- ? errors.name
72
- : { id: errors.name, defaultMessage: errors.name }
73
- )
74
- : null
75
- }
76
- label={formatMessage({
77
- id: 'Settings.apiTokens.form.name',
78
- defaultMessage: 'Name',
79
- })}
80
+ <TokenName
81
+ errors={errors}
82
+ values={values}
83
+ canEditInputs={canEditInputs}
80
84
  onChange={onChange}
81
- value={values.name}
82
- disabled={!canEditInputs}
83
- required
84
85
  />
85
86
  </GridItem>
86
87
  <GridItem key="description" col={6} xs={12}>
87
- <Textarea
88
- label={formatMessage({
89
- id: 'Settings.apiTokens.form.description',
90
- defaultMessage: 'Description',
91
- })}
92
- name="description"
93
- error={
94
- errors.description
95
- ? formatMessage(
96
- errors.description?.id
97
- ? errors.description
98
- : {
99
- id: errors.description,
100
- defaultMessage: errors.description,
101
- }
102
- )
103
- : null
104
- }
88
+ <TokenDescription
89
+ errors={errors}
90
+ values={values}
91
+ canEditInputs={canEditInputs}
105
92
  onChange={onChange}
106
- disabled={!canEditInputs}
107
- >
108
- {values.description}
109
- </Textarea>
93
+ />
110
94
  </GridItem>
111
95
  <GridItem key="lifespan" col={6} xs={12}>
112
- <Select
113
- name="lifespan"
114
- label={formatMessage({
115
- id: 'Settings.apiTokens.form.duration',
116
- defaultMessage: 'Token duration',
117
- })}
118
- value={values.lifespan !== null ? values.lifespan : '0'}
119
- error={
120
- errors.lifespan
121
- ? formatMessage(
122
- errors.lifespan?.id
123
- ? errors.lifespan
124
- : { id: errors.lifespan, defaultMessage: errors.lifespan }
125
- )
126
- : null
127
- }
128
- onChange={(value) => {
129
- onChange({ target: { name: 'lifespan', value } });
130
- }}
131
- required
132
- disabled={!isCreating}
133
- placeholder="Select"
134
- >
135
- <Option value="604800000">
136
- {formatMessage({
137
- id: 'Settings.apiTokens.duration.7-days',
138
- defaultMessage: '7 days',
139
- })}
140
- </Option>
141
- <Option value="2592000000">
142
- {formatMessage({
143
- id: 'Settings.apiTokens.duration.30-days',
144
- defaultMessage: '30 days',
145
- })}
146
- </Option>
147
- <Option value="7776000000">
148
- {formatMessage({
149
- id: 'Settings.apiTokens.duration.90-days',
150
- defaultMessage: '90 days',
151
- })}
152
- </Option>
153
- <Option value="0">
154
- {formatMessage({
155
- id: 'Settings.apiTokens.duration.unlimited',
156
- defaultMessage: 'Unlimited',
157
- })}
158
- </Option>
159
- </Select>
160
- <Typography variant="pi" textColor="neutral600">
161
- {!isCreating &&
162
- `${formatMessage({
163
- id: 'Settings.apiTokens.duration.expiration-date',
164
- defaultMessage: 'Expiration date',
165
- })}: ${getDateOfExpiration(
166
- apiToken?.createdAt,
167
- parseInt(values.lifespan, 10),
168
- lang
169
- )}`}
170
- </Typography>
96
+ <LifeSpanInput
97
+ isCreating={isCreating}
98
+ errors={errors}
99
+ values={values}
100
+ onChange={onChange}
101
+ token={apiToken}
102
+ />
171
103
  </GridItem>
172
104
 
173
105
  <GridItem key="type" col={6} xs={12}>
174
- <Select
175
- name="type"
176
- label={formatMessage({
106
+ <TokenTypeSelect
107
+ values={values}
108
+ errors={errors}
109
+ label={{
177
110
  id: 'Settings.apiTokens.form.type',
178
111
  defaultMessage: 'Token type',
179
- })}
180
- value={values?.type}
181
- error={
182
- errors.type
183
- ? formatMessage(
184
- errors.type?.id
185
- ? errors.type
186
- : { id: errors.type, defaultMessage: errors.type }
187
- )
188
- : null
189
- }
112
+ }}
190
113
  onChange={(value) => {
191
114
  handleChangeSelectApiTokenType({ target: { value } });
192
115
  onChange({ target: { name: 'type', value } });
193
116
  }}
194
- placeholder="Select"
195
- required
196
- disabled={!canEditInputs}
197
- >
198
- <Option value="read-only">
199
- {formatMessage({
200
- id: 'Settings.apiTokens.types.read-only',
201
- defaultMessage: 'Read-only',
202
- })}
203
- </Option>
204
- <Option value="full-access">
205
- {formatMessage({
206
- id: 'Settings.apiTokens.types.full-access',
207
- defaultMessage: 'Full access',
208
- })}
209
- </Option>
210
- <Option value="custom">
211
- {formatMessage({
212
- id: 'Settings.apiTokens.types.custom',
213
- defaultMessage: 'Custom',
214
- })}
215
- </Option>
216
- </Select>
117
+ options={typeOptions}
118
+ canEditInputs={canEditInputs}
119
+ />
217
120
  </GridItem>
218
121
  </Grid>
219
122
  </Stack>
@@ -9,7 +9,11 @@ import { useRegenerate } from '../../../../../../../hooks';
9
9
  export const Regenerate = ({ onRegenerate, idToRegenerate }) => {
10
10
  const { formatMessage } = useIntl();
11
11
  const [showConfirmDialog, setShowConfirmDialog] = useState(false);
12
- const { regenerateData, isLoadingConfirmation } = useRegenerate(idToRegenerate, onRegenerate);
12
+ const { regenerateData, isLoadingConfirmation } = useRegenerate(
13
+ '/admin/api-tokens/',
14
+ idToRegenerate,
15
+ onRegenerate
16
+ );
13
17
  const handleConfirmRegeneration = async () => {
14
18
  regenerateData();
15
19
  setShowConfirmDialog(false);