@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.
Files changed (93) hide show
  1. package/admin/src/assets/images/onboarding-preview.png +0 -0
  2. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +0 -2
  3. package/admin/src/hooks/useRegenerate/index.js +2 -2
  4. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +7 -0
  5. package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
  6. package/admin/src/pages/Admin/Onboarding/index.js +161 -89
  7. package/admin/src/pages/Admin/index.js +5 -2
  8. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components → components/Tokens}/FormHead/index.js +36 -19
  9. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +96 -0
  10. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +98 -0
  11. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +73 -0
  12. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DefaultButton/index.js +1 -1
  13. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DeleteButton/index.js +1 -1
  14. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/ReadButton/index.js +0 -0
  15. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/UpdateButton/index.js +0 -0
  16. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +135 -0
  17. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components/ContentBox → components/Tokens/TokenBox}/index.js +17 -17
  18. package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +51 -0
  19. package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +46 -0
  20. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +69 -0
  21. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +5 -3
  22. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +52 -142
  23. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -1
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +37 -14
  25. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +5 -13
  26. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +105 -0
  27. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +50 -0
  28. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +201 -0
  29. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +16 -0
  30. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +4 -0
  31. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +10 -0
  32. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +182 -0
  33. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +48 -0
  34. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +14 -0
  35. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +14 -0
  36. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +12 -0
  37. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +33 -0
  38. package/admin/src/permissions/defaultPermissions.js +8 -0
  39. package/admin/src/translations/en.json +18 -1
  40. package/build/19eb2dfcf2603eb55733.png +0 -0
  41. package/build/4649.15cc0afe.chunk.js +30 -0
  42. package/build/7259.aa68d808.chunk.js +1 -0
  43. package/build/7407.883fb1f5.chunk.js +1 -0
  44. package/build/Admin-authenticatedApp.f29f6021.chunk.js +79 -0
  45. package/build/{Admin_settingsPage.d1493824.chunk.js → Admin_settingsPage.178dc6e3.chunk.js} +25 -25
  46. package/build/{admin-app.25934eaa.chunk.js → admin-app.77a50e1f.chunk.js} +19 -19
  47. package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.0db3aec1.chunk.js} +1 -1
  48. package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.671e0e26.chunk.js} +1 -1
  49. package/build/api-tokens-list-page.7387102c.chunk.js +16 -0
  50. package/build/{content-manager.35ff9726.chunk.js → content-manager.42b24d46.chunk.js} +77 -77
  51. package/build/en-json.b0748970.chunk.js +1 -0
  52. package/build/index.html +1 -1
  53. package/build/main.1022ed01.js +4393 -0
  54. package/build/runtime~main.84941a97.js +2 -0
  55. package/build/transfer-tokens-create-page.16e23791.chunk.js +1 -0
  56. package/build/transfer-tokens-edit-page.3886c973.chunk.js +1 -0
  57. package/build/transfer-tokens-list-page.e8010a89.chunk.js +16 -0
  58. package/package.json +12 -12
  59. package/server/bootstrap.js +2 -0
  60. package/server/config/admin-actions.js +48 -0
  61. package/server/content-types/index.js +2 -0
  62. package/server/content-types/transfer-token-permission.js +36 -0
  63. package/server/content-types/transfer-token.js +66 -0
  64. package/server/controllers/api-token.js +4 -5
  65. package/server/controllers/index.js +1 -0
  66. package/server/controllers/transfer/index.js +13 -0
  67. package/server/controllers/transfer/runner.js +24 -0
  68. package/server/controllers/transfer/token.js +131 -0
  69. package/server/register.js +2 -9
  70. package/server/routes/index.js +2 -0
  71. package/server/routes/transfer.js +95 -0
  72. package/server/services/api-token.js +2 -3
  73. package/server/services/constants.js +6 -0
  74. package/server/services/index.js +1 -0
  75. package/server/services/transfer/index.js +6 -0
  76. package/server/services/transfer/permission.js +22 -0
  77. package/server/services/transfer/token.js +409 -0
  78. package/server/strategies/api-token.js +4 -2
  79. package/server/strategies/data-transfer.js +107 -0
  80. package/server/strategies/index.js +1 -0
  81. package/server/utils/index.d.ts +2 -0
  82. package/server/validation/api-tokens.js +1 -6
  83. package/server/validation/transfer/index.js +5 -0
  84. package/server/validation/transfer/token.js +34 -0
  85. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -78
  86. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +0 -112
  87. package/build/4318.f96a9d4d.chunk.js +0 -30
  88. package/build/8633.00ccd382.chunk.js +0 -1
  89. package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
  90. package/build/api-tokens-list-page.44a79fda.chunk.js +0 -16
  91. package/build/en-json.1f137a90.chunk.js +0 -1
  92. package/build/main.7b151630.js +0 -4377
  93. package/build/runtime~main.a20d633b.js +0 -2
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Select, Option } from '@strapi/design-system/Select';
5
+ import { Typography } from '@strapi/design-system/Typography';
6
+ import { getDateOfExpiration } from '../../../pages/ApiTokens/EditView/utils';
7
+
8
+ const LifeSpanInput = ({ token, errors, values, onChange, isCreating }) => {
9
+ const { formatMessage } = useIntl();
10
+
11
+ return (
12
+ <>
13
+ <Select
14
+ name="lifespan"
15
+ label={formatMessage({
16
+ id: 'Settings.apiTokens.form.duration',
17
+ defaultMessage: 'Token duration',
18
+ })}
19
+ value={values.lifespan !== null ? values.lifespan : '0'}
20
+ error={
21
+ errors.lifespan
22
+ ? formatMessage(
23
+ errors.lifespan?.id
24
+ ? errors.lifespan
25
+ : { id: errors.lifespan, defaultMessage: errors.lifespan }
26
+ )
27
+ : null
28
+ }
29
+ onChange={(value) => {
30
+ onChange({ target: { name: 'lifespan', value } });
31
+ }}
32
+ required
33
+ disabled={!isCreating}
34
+ placeholder="Select"
35
+ >
36
+ <Option value="604800000">
37
+ {formatMessage({
38
+ id: 'Settings.tokens.duration.7-days',
39
+ defaultMessage: '7 days',
40
+ })}
41
+ </Option>
42
+ <Option value="2592000000">
43
+ {formatMessage({
44
+ id: 'Settings.tokens.duration.30-days',
45
+ defaultMessage: '30 days',
46
+ })}
47
+ </Option>
48
+ <Option value="7776000000">
49
+ {formatMessage({
50
+ id: 'Settings.tokens.duration.90-days',
51
+ defaultMessage: '90 days',
52
+ })}
53
+ </Option>
54
+ <Option value="0">
55
+ {formatMessage({
56
+ id: 'Settings.tokens.duration.unlimited',
57
+ defaultMessage: 'Unlimited',
58
+ })}
59
+ </Option>
60
+ </Select>
61
+ <Typography variant="pi" textColor="neutral600">
62
+ {!isCreating &&
63
+ `${formatMessage({
64
+ id: 'Settings.tokens.duration.expiration-date',
65
+ defaultMessage: 'Expiration date',
66
+ })}: ${getDateOfExpiration(token?.createdAt, parseInt(values.lifespan, 10))}`}
67
+ </Typography>
68
+ </>
69
+ );
70
+ };
71
+
72
+ LifeSpanInput.propTypes = {
73
+ errors: PropTypes.shape({
74
+ lifespan: PropTypes.string,
75
+ }),
76
+ onChange: PropTypes.func.isRequired,
77
+ values: PropTypes.shape({
78
+ lifespan: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
79
+ }).isRequired,
80
+ isCreating: PropTypes.bool.isRequired,
81
+ token: PropTypes.shape({
82
+ id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
83
+ type: PropTypes.string,
84
+ lifespan: PropTypes.string,
85
+ name: PropTypes.string,
86
+ accessKey: PropTypes.string,
87
+ permissions: PropTypes.array,
88
+ description: PropTypes.string,
89
+ createdAt: PropTypes.string,
90
+ }),
91
+ };
92
+
93
+ LifeSpanInput.defaultProps = {
94
+ errors: {},
95
+ token: {},
96
+ };
97
+
98
+ export default LifeSpanInput;
@@ -0,0 +1,73 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Button } from '@strapi/design-system/Button';
5
+ import Refresh from '@strapi/icons/Refresh';
6
+ import { ConfirmDialog } from '@strapi/helper-plugin';
7
+ import { useRegenerate } from '../../../../../hooks';
8
+
9
+ export const Regenerate = ({ onRegenerate, idToRegenerate, backUrl }) => {
10
+ const { formatMessage } = useIntl();
11
+ const [showConfirmDialog, setShowConfirmDialog] = useState(false);
12
+ const { regenerateData, isLoadingConfirmation } = useRegenerate(
13
+ backUrl,
14
+ idToRegenerate,
15
+ onRegenerate
16
+ );
17
+ const handleConfirmRegeneration = async () => {
18
+ regenerateData();
19
+ setShowConfirmDialog(false);
20
+ };
21
+
22
+ return (
23
+ <>
24
+ <Button
25
+ startIcon={<Refresh />}
26
+ type="button"
27
+ size="S"
28
+ variant="tertiary"
29
+ onClick={() => setShowConfirmDialog(true)}
30
+ name="regenerate"
31
+ >
32
+ {formatMessage({
33
+ id: 'Settings.apiTokens.regenerate',
34
+ defaultMessage: 'Regenerate',
35
+ })}
36
+ </Button>
37
+
38
+ <ConfirmDialog
39
+ bodyText={{
40
+ id: 'Settings.apiTokens.popUpWarning.message',
41
+ defaultMessage: 'Are you sure you want to regenerate this token?',
42
+ }}
43
+ iconRightButton={<Refresh />}
44
+ isConfirmButtonLoading={isLoadingConfirmation}
45
+ isOpen={showConfirmDialog}
46
+ onToggleDialog={() => setShowConfirmDialog(false)}
47
+ onConfirm={handleConfirmRegeneration}
48
+ leftButtonText={{
49
+ id: 'Settings.apiTokens.Button.cancel',
50
+ defaultMessage: 'Cancel',
51
+ }}
52
+ rightButtonText={{
53
+ id: 'Settings.apiTokens.Button.regenerate',
54
+ defaultMessage: 'Regenerate',
55
+ }}
56
+ title={{
57
+ id: 'Settings.apiTokens.RegenerateDialog.title',
58
+ defaultMessage: 'Regenerate token',
59
+ }}
60
+ />
61
+ </>
62
+ );
63
+ };
64
+
65
+ Regenerate.defaultProps = { onRegenerate() {} };
66
+
67
+ Regenerate.propTypes = {
68
+ onRegenerate: PropTypes.func,
69
+ idToRegenerate: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
70
+ backUrl: PropTypes.string.isRequired,
71
+ };
72
+
73
+ export default Regenerate;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import PropTypes from 'prop-types';
4
- import { Link } from '@strapi/helper-plugin';
5
4
  import { useHistory } from 'react-router-dom';
6
5
  import styled from 'styled-components';
6
+ import { Link } from '@strapi/helper-plugin';
7
7
 
8
8
  const MESSAGES_MAP = {
9
9
  edit: {
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
8
8
 
9
9
  const DeleteButton = ({ tokenName, onClickDelete }) => {
10
10
  const { formatMessage } = useIntl();
11
- const { trackUsage } = useTracking();
11
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
12
12
 
13
13
  return (
14
14
  <Box paddingLeft={1} {...stopPropagation}>
@@ -0,0 +1,135 @@
1
+ import React from 'react';
2
+ import { useHistory } from 'react-router-dom';
3
+ import PropTypes from 'prop-types';
4
+ import { Typography } from '@strapi/design-system/Typography';
5
+ import { Tbody, Tr, Td } from '@strapi/design-system/Table';
6
+ import { Flex } from '@strapi/design-system/Flex';
7
+ import {
8
+ RelativeTime,
9
+ onRowClick,
10
+ pxToRem,
11
+ DynamicTable,
12
+ useQueryParams,
13
+ useTracking,
14
+ } from '@strapi/helper-plugin';
15
+ import DeleteButton from './DeleteButton';
16
+ import UpdateButton from './UpdateButton';
17
+ import ReadButton from './ReadButton';
18
+
19
+ const Table = ({ permissions, headers, contentType, isLoading, tokens, onConfirmDelete }) => {
20
+ const { canDelete, canUpdate, canRead } = permissions;
21
+ const withBulkActions = canDelete || canUpdate || canRead;
22
+ const [{ query }] = useQueryParams();
23
+ const [, sortOrder] = query ? query.sort.split(':') : 'ASC';
24
+ const {
25
+ push,
26
+ location: { pathname },
27
+ } = useHistory();
28
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
29
+
30
+ const sortedTokens = tokens.sort((a, b) => {
31
+ const comparison = a.name.localeCompare(b.name);
32
+
33
+ return sortOrder === 'DESC' ? -comparison : comparison;
34
+ });
35
+
36
+ return (
37
+ <DynamicTable
38
+ headers={headers}
39
+ contentType={contentType}
40
+ rows={tokens}
41
+ withBulkActions={withBulkActions}
42
+ isLoading={isLoading}
43
+ onConfirmDelete={onConfirmDelete}
44
+ >
45
+ <Tbody>
46
+ {sortedTokens.map((token) => {
47
+ return (
48
+ <Tr
49
+ key={token.id}
50
+ {...onRowClick({
51
+ fn() {
52
+ trackUsage('willEditTokenFromList');
53
+ push(`${pathname}/${token.id}`);
54
+ },
55
+ condition: canUpdate,
56
+ })}
57
+ >
58
+ <Td>
59
+ <Typography textColor="neutral800" fontWeight="bold">
60
+ {token.name}
61
+ </Typography>
62
+ </Td>
63
+ <Td maxWidth={pxToRem(250)}>
64
+ <Typography textColor="neutral800" ellipsis>
65
+ {token.description}
66
+ </Typography>
67
+ </Td>
68
+ <Td>
69
+ <Typography textColor="neutral800">
70
+ <RelativeTime timestamp={new Date(token.createdAt)} />
71
+ </Typography>
72
+ </Td>
73
+ <Td>
74
+ {token.lastUsedAt && (
75
+ <Typography textColor="neutral800">
76
+ <RelativeTime timestamp={new Date(token.lastUsedAt)} />
77
+ </Typography>
78
+ )}
79
+ </Td>
80
+
81
+ {withBulkActions && (
82
+ <Td>
83
+ <Flex justifyContent="end">
84
+ {canUpdate && <UpdateButton tokenName={token.name} tokenId={token.id} />}
85
+ {!canUpdate && canRead && (
86
+ <ReadButton tokenName={token.name} tokenId={token.id} />
87
+ )}
88
+ {canDelete && (
89
+ <DeleteButton
90
+ tokenName={token.name}
91
+ onClickDelete={() => onConfirmDelete(token.id)}
92
+ />
93
+ )}
94
+ </Flex>
95
+ </Td>
96
+ )}
97
+ </Tr>
98
+ );
99
+ })}
100
+ </Tbody>
101
+ </DynamicTable>
102
+ );
103
+ };
104
+
105
+ Table.propTypes = {
106
+ tokens: PropTypes.array,
107
+ permissions: PropTypes.shape({
108
+ canRead: PropTypes.bool,
109
+ canDelete: PropTypes.bool,
110
+ canUpdate: PropTypes.bool,
111
+ }).isRequired,
112
+ headers: PropTypes.arrayOf(
113
+ PropTypes.shape({
114
+ cellFormatter: PropTypes.func,
115
+ key: PropTypes.string.isRequired,
116
+ metadatas: PropTypes.shape({
117
+ label: PropTypes.string.isRequired,
118
+ sortable: PropTypes.bool,
119
+ }).isRequired,
120
+ name: PropTypes.string.isRequired,
121
+ })
122
+ ),
123
+ contentType: PropTypes.string.isRequired,
124
+ isLoading: PropTypes.bool,
125
+ onConfirmDelete: PropTypes.func,
126
+ };
127
+
128
+ Table.defaultProps = {
129
+ tokens: [],
130
+ headers: [],
131
+ isLoading: false,
132
+ onConfirmDelete() {},
133
+ };
134
+
135
+ export default Table;
@@ -1,32 +1,32 @@
1
1
  import React, { useRef } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import { CopyToClipboard } from 'react-copy-to-clipboard';
3
5
  import { ContentBox, useNotification, useTracking } from '@strapi/helper-plugin';
4
6
  import { IconButton } from '@strapi/design-system/IconButton';
5
7
  import Duplicate from '@strapi/icons/Duplicate';
6
- import PropTypes from 'prop-types';
7
- import { CopyToClipboard } from 'react-copy-to-clipboard';
8
8
  import Key from '@strapi/icons/Key';
9
9
 
10
- const HeaderContentBox = ({ apiToken }) => {
10
+ const TokenBox = ({ token }) => {
11
11
  const { formatMessage } = useIntl();
12
12
  const toggleNotification = useNotification();
13
- const { trackUsage } = useTracking();
13
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
14
14
  const trackUsageRef = useRef(trackUsage);
15
15
 
16
16
  return (
17
17
  <ContentBox
18
18
  endAction={
19
- apiToken && (
19
+ token && (
20
20
  <span style={{ alignSelf: 'start' }}>
21
21
  <CopyToClipboard
22
22
  onCopy={() => {
23
23
  trackUsageRef.current('didCopyTokenKey');
24
24
  toggleNotification({
25
25
  type: 'success',
26
- message: { id: 'Settings.apiTokens.notification.copied' },
26
+ message: { id: 'Settings.tokens.notification.copied' },
27
27
  });
28
28
  }}
29
- text={apiToken}
29
+ text={token}
30
30
  >
31
31
  <IconButton
32
32
  label={formatMessage({
@@ -42,20 +42,20 @@ const HeaderContentBox = ({ apiToken }) => {
42
42
  )
43
43
  }
44
44
  title={
45
- apiToken ||
45
+ token ||
46
46
  formatMessage({
47
- id: 'Settings.apiTokens.copy.editTitle',
47
+ id: 'Settings.tokens.copy.editTitle',
48
48
  defaultMessage: 'This token isn’t accessible anymore.',
49
49
  })
50
50
  }
51
51
  subtitle={
52
- apiToken
52
+ token
53
53
  ? formatMessage({
54
- id: 'Settings.apiTokens.copy.lastWarning',
54
+ id: 'Settings.tokens.copy.lastWarning',
55
55
  defaultMessage: 'Make sure to copy this token, you won’t be able to see it again!',
56
56
  })
57
57
  : formatMessage({
58
- id: 'Settings.apiTokens.copy.editMessage',
58
+ id: 'Settings.tokens.copy.editMessage',
59
59
  defaultMessage: 'For security reasons, you can only see your token once.',
60
60
  })
61
61
  }
@@ -65,12 +65,12 @@ const HeaderContentBox = ({ apiToken }) => {
65
65
  );
66
66
  };
67
67
 
68
- HeaderContentBox.defaultProps = {
69
- apiToken: null,
68
+ TokenBox.defaultProps = {
69
+ token: null,
70
70
  };
71
71
 
72
- HeaderContentBox.propTypes = {
73
- apiToken: PropTypes.string,
72
+ TokenBox.propTypes = {
73
+ token: PropTypes.string,
74
74
  };
75
75
 
76
- export default HeaderContentBox;
76
+ 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/Textarea';
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/TextInput';
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/Select';
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;
@@ -1,5 +1,8 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { capitalize } from 'lodash';
3
+ import { useIntl } from 'react-intl';
4
+ import styled from 'styled-components';
5
+ import PropTypes from 'prop-types';
3
6
  import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion';
4
7
  import { Checkbox } from '@strapi/design-system/Checkbox';
5
8
  import { Grid, GridItem } from '@strapi/design-system/Grid';
@@ -7,8 +10,6 @@ import { Typography } from '@strapi/design-system/Typography';
7
10
  import { Box } from '@strapi/design-system/Box';
8
11
  import { Flex } from '@strapi/design-system/Flex';
9
12
  import CogIcon from '@strapi/icons/Cog';
10
- import styled from 'styled-components';
11
- import PropTypes from 'prop-types';
12
13
  import { useApiTokenPermissionsContext } from '../../../../../../../contexts/ApiTokenPermissions';
13
14
  import CheckboxWrapper from './CheckBoxWrapper';
14
15
 
@@ -30,6 +31,7 @@ const CollapsableContentType = ({
30
31
  value: { onChangeSelectAll, onChange, selectedActions, setSelectedAction, selectedAction },
31
32
  } = useApiTokenPermissionsContext();
32
33
  const [expanded, setExpanded] = useState(false);
34
+ const { formatMessage } = useIntl();
33
35
 
34
36
  const handleExpandedAccordion = () => {
35
37
  setExpanded((s) => !s);
@@ -83,7 +85,7 @@ const CollapsableContentType = ({
83
85
  }}
84
86
  disabled={disabled}
85
87
  >
86
- Select all
88
+ {formatMessage({ id: 'app.utils.select-all', defaultMessage: 'Select all' })}
87
89
  </Checkbox>
88
90
  </Box>
89
91
  </Flex>