@strapi/admin 4.9.0 → 4.9.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.
Files changed (71) hide show
  1. package/admin/src/components/LanguageProvider/index.js +1 -1
  2. package/admin/src/components/LocalesProvider/index.js +2 -3
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +3 -6
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +9 -5
  5. package/admin/src/content-manager/components/InputUID/index.js +1 -1
  6. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -8
  7. package/admin/src/content-manager/pages/App/LeftMenu/index.js +56 -35
  8. package/admin/src/content-manager/pages/App/actions.js +19 -7
  9. package/admin/src/content-manager/pages/App/constants.js +3 -3
  10. package/admin/src/content-manager/pages/App/index.js +5 -4
  11. package/admin/src/content-manager/pages/App/reducer.js +7 -6
  12. package/admin/src/content-manager/pages/App/selectors.js +3 -0
  13. package/admin/src/content-manager/pages/App/{useModels.js → useContentManagerInitData.js} +29 -28
  14. package/admin/src/content-manager/pages/App/utils/generateModelsLinks.js +2 -2
  15. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +17 -15
  16. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +4 -5
  17. package/admin/src/content-manager/pages/EditSettingsView/index.js +4 -0
  18. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +6 -7
  19. package/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +1 -30
  20. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +5 -11
  21. package/admin/src/content-manager/pages/EditView/index.js +2 -7
  22. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -0
  23. package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +7 -8
  24. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -0
  25. package/admin/src/pages/HomePage/SocialLinks.js +1 -1
  26. package/admin/src/pages/MarketplacePage/components/EmptyNpmPackageSearch/index.js +3 -3
  27. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -9
  28. package/admin/src/pages/MarketplacePage/components/NpmPackagesPagination/index.js +26 -0
  29. package/admin/src/pages/MarketplacePage/components/OfflineLayout/index.js +45 -0
  30. package/admin/src/pages/MarketplacePage/index.js +80 -175
  31. package/admin/src/pages/MarketplacePage/utils/useMarketplaceData.js +85 -0
  32. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +12 -4
  33. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +21 -2
  34. package/admin/src/translations/en.json +51 -50
  35. package/admin/src/translations/ru.json +51 -19
  36. package/build/{Admin-authenticatedApp.31bf88ef.chunk.js → Admin-authenticatedApp.217db666.chunk.js} +5 -5
  37. package/build/{Admin_homePage.da2181fe.chunk.js → Admin_homePage.f9309c6d.chunk.js} +1 -1
  38. package/build/Admin_marketplace.56bc1008.chunk.js +31 -0
  39. package/build/{Admin_settingsPage.cb63220f.chunk.js → Admin_settingsPage.1dbfc9ce.chunk.js} +1 -1
  40. package/build/{admin-app.8cde5b22.chunk.js → admin-app.558af642.chunk.js} +6 -6
  41. package/build/admin-roles-list.329c1f63.chunk.js +31 -0
  42. package/build/audit-logs-settings-page.19d90bda.chunk.js +76 -0
  43. package/build/content-manager.d1565bfc.chunk.js +1132 -0
  44. package/build/content-type-builder-translation-en-json.6c8e69ab.chunk.js +1 -0
  45. package/build/content-type-builder.9d780e7f.chunk.js +126 -0
  46. package/build/en-json.cf600231.chunk.js +1 -0
  47. package/build/index.html +1 -1
  48. package/build/main.ef8db4a2.js +2280 -0
  49. package/build/ru-json.e0662702.chunk.js +1 -0
  50. package/build/{runtime~main.7cdc9956.js → runtime~main.3a92d953.js} +1 -1
  51. package/build/users-roles-settings-page.2f85dcec.chunk.js +30 -0
  52. package/ee/admin/hooks/useLicenseLimitNotification/index.js +1 -1
  53. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useAuditLogsData.js +6 -3
  54. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/index.js +15 -5
  55. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getDisplayedFilters.js +52 -45
  56. package/package.json +20 -20
  57. package/webpack.config.js +5 -1
  58. package/admin/src/content-manager/pages/App/LeftMenu/utils/index.js +0 -1
  59. package/admin/src/content-manager/pages/App/LeftMenu/utils/matchByTitle.js +0 -24
  60. package/build/9347.058ddb22.chunk.js +0 -1
  61. package/build/Admin_marketplace.d99044eb.chunk.js +0 -31
  62. package/build/admin-roles-list.97e198f9.chunk.js +0 -31
  63. package/build/audit-logs-settings-page.ca9a3c46.chunk.js +0 -76
  64. package/build/content-manager.de0ee3e5.chunk.js +0 -1132
  65. package/build/content-type-builder-translation-en-json.e577d595.chunk.js +0 -1
  66. package/build/content-type-builder.ec5ac7ab.chunk.js +0 -126
  67. package/build/en-json.b052667a.chunk.js +0 -1
  68. package/build/main.d40f9ca1.js +0 -2280
  69. package/build/ru-json.6a01cea6.chunk.js +0 -1
  70. package/build/users-roles-settings-page.a5c5b0df.chunk.js +0 -30
  71. /package/admin/src/{content-manager/components/InputUID/useDebounce.js → hooks/useDebounce/index.js} +0 -0
@@ -1,4 +1,3 @@
1
- /* eslint-disable indent */
2
1
  const getRowSize = (arr) => arr.reduce((sum, value) => sum + value.size, 0);
3
2
 
4
3
  const createLayout = (arr) => {
@@ -75,26 +74,6 @@ const unformatLayout = (arr) => {
75
74
  }, []);
76
75
  };
77
76
 
78
- const getDefaultInputSize = (type) => {
79
- switch (type) {
80
- case 'boolean':
81
- case 'date':
82
- case 'integer':
83
- case 'float':
84
- case 'biginteger':
85
- case 'decimal':
86
- case 'time':
87
- return 4;
88
- case 'json':
89
- case 'component':
90
- case 'richtext':
91
- case 'dynamiczone':
92
- return 12;
93
- default:
94
- return 6;
95
- }
96
- };
97
-
98
77
  const getFieldSize = (name, layouts = []) => {
99
78
  return layouts.reduce((acc, { rowContent }) => {
100
79
  const size = rowContent.find((row) => row.name === name)?.size ?? null;
@@ -124,12 +103,4 @@ const setFieldSize = (name, size, layouts = []) => {
124
103
  });
125
104
  };
126
105
 
127
- export {
128
- createLayout,
129
- formatLayout,
130
- getDefaultInputSize,
131
- getFieldSize,
132
- setFieldSize,
133
- getRowSize,
134
- unformatLayout,
135
- };
106
+ export { createLayout, formatLayout, getFieldSize, setFieldSize, getRowSize, unformatLayout };
@@ -8,14 +8,14 @@ import PropTypes from 'prop-types';
8
8
  import { getTrad } from '../../../utils';
9
9
  import { connect, select } from './utils';
10
10
 
11
- const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerProperty }) => {
12
- const [showWarningDelete, setWarningDelete] = useState(false);
11
+ const DeleteLink = ({ onDelete, trackerProperty }) => {
12
+ const [displayDeleteConfirmation, setDisplayDeleteConfirmation] = useState(false);
13
13
  const [isModalConfirmButtonLoading, setIsModalConfirmButtonLoading] = useState(false);
14
14
  const { formatMessage } = useIntl();
15
15
  const { formatAPIError } = useAPIErrorHandler(getTrad);
16
16
  const toggleNotification = useNotification();
17
17
 
18
- const toggleWarningDelete = () => setWarningDelete((prevState) => !prevState);
18
+ const toggleWarningDelete = () => setDisplayDeleteConfirmation((prevState) => !prevState);
19
19
 
20
20
  const handleConfirmDelete = async () => {
21
21
  try {
@@ -27,7 +27,6 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
27
27
  setIsModalConfirmButtonLoading(false);
28
28
 
29
29
  toggleWarningDelete();
30
- onDeleteSucceeded();
31
30
  } catch (err) {
32
31
  setIsModalConfirmButtonLoading(false);
33
32
  toggleWarningDelete();
@@ -38,10 +37,6 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
38
37
  }
39
38
  };
40
39
 
41
- if (isCreatingEntry) {
42
- return null;
43
- }
44
-
45
40
  return (
46
41
  <>
47
42
  <Button onClick={toggleWarningDelete} size="S" startIcon={<Trash />} variant="danger-light">
@@ -50,9 +45,10 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
50
45
  defaultMessage: 'Delete this entry',
51
46
  })}
52
47
  </Button>
48
+
53
49
  <ConfirmDialog
54
50
  isConfirmButtonLoading={isModalConfirmButtonLoading}
55
- isOpen={showWarningDelete}
51
+ isOpen={displayDeleteConfirmation}
56
52
  onConfirm={handleConfirmDelete}
57
53
  onToggleDialog={toggleWarningDelete}
58
54
  />
@@ -61,9 +57,7 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
61
57
  };
62
58
 
63
59
  DeleteLink.propTypes = {
64
- isCreatingEntry: PropTypes.bool.isRequired,
65
60
  onDelete: PropTypes.func.isRequired,
66
- onDeleteSucceeded: PropTypes.func.isRequired,
67
61
  trackerProperty: PropTypes.object.isRequired,
68
62
  };
69
63
 
@@ -77,7 +77,6 @@ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, user
77
77
  isCreatingEntry,
78
78
  isLoadingForData,
79
79
  onDelete,
80
- onDeleteSucceeded,
81
80
  onPost,
82
81
  onPublish,
83
82
  onDraftRelationCheck,
@@ -221,12 +220,8 @@ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, user
221
220
  </LinkButton>
222
221
  </CheckPermissions>
223
222
 
224
- {allowedActions.canDelete && (
225
- <DeleteLink
226
- isCreatingEntry={isCreatingEntry}
227
- onDelete={onDelete}
228
- onDeleteSucceeded={onDeleteSucceeded}
229
- />
223
+ {allowedActions.canDelete && !isCreatingEntry && (
224
+ <DeleteLink onDelete={onDelete} />
230
225
  )}
231
226
  </Flex>
232
227
  </Box>
@@ -127,6 +127,7 @@ const ListSettingsView = ({ layout, slug }) => {
127
127
  dispatch({
128
128
  type: 'SUBMIT_FIELD_FORM',
129
129
  });
130
+ handleCloseModal();
130
131
  };
131
132
 
132
133
  const submitMutation = useMutation((body) => putCMSettingsLV(body, slug), {
@@ -1,19 +1,18 @@
1
1
  import axios from 'axios';
2
+ import qs from 'qs';
2
3
 
3
4
  const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
4
5
 
5
6
  const fetchMarketplacePlugins = async (params = {}) => {
6
- const { data: response } = await axios.get(`${MARKETPLACE_API_URL}/plugins`, {
7
+ const { data } = await axios.get(`${MARKETPLACE_API_URL}/plugins`, {
7
8
  params,
9
+ paramsSerializer: {
10
+ encode: qs.parse,
11
+ serialize: qs.stringify,
12
+ },
8
13
  });
9
14
 
10
- // Only keep v4 plugins
11
- const filteredResponse = {
12
- ...response,
13
- data: response.data.filter((plugin) => plugin.attributes.strapiCompatibility === 'v4'),
14
- };
15
-
16
- return filteredResponse;
15
+ return data;
17
16
  };
18
17
 
19
18
  export { fetchMarketplacePlugins };
@@ -1,10 +1,15 @@
1
1
  import axios from 'axios';
2
+ import qs from 'qs';
2
3
 
3
4
  const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
4
5
 
5
6
  const fetchMarketplaceProviders = async (params = {}) => {
6
7
  const { data } = await axios.get(`${MARKETPLACE_API_URL}/providers`, {
7
8
  params,
9
+ paramsSerializer: {
10
+ encode: qs.parse,
11
+ serialize: qs.stringify,
12
+ },
8
13
  });
9
14
 
10
15
  return data;
@@ -187,7 +187,7 @@ const SocialLinks = () => {
187
187
  <GridGap>
188
188
  {socialLinksExtended.map(({ icon, link, name }) => {
189
189
  return (
190
- <GridItem col={6} s={12} key={name}>
190
+ <GridItem col={6} s={12} key={name.id}>
191
191
  <LinkCustom size="L" startIcon={icon} variant="tertiary" href={link} isExternal>
192
192
  {formatMessage(name)}
193
193
  </LinkCustom>
@@ -1,16 +1,16 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Typography, Box, Flex, Icon } from '@strapi/design-system';
4
- import { EmptyStateDocument } from '@strapi/icons';
4
+ import { EmptyDocuments } from '@strapi/icons';
5
5
  import { EmptyNpmPackageGrid } from './EmptyNpmPackageGrid';
6
6
 
7
7
  const EmptyNpmPackageSearch = ({ content }) => {
8
8
  return (
9
- <Box position="relative">
9
+ <Box position="relative" data-testid="marketplace-results">
10
10
  <EmptyNpmPackageGrid />
11
11
  <Box position="absolute" top={11} width="100%">
12
12
  <Flex alignItems="center" justifyContent="center" direction="column">
13
- <Icon as={EmptyStateDocument} color="" width="160px" height="88px" />
13
+ <Icon as={EmptyDocuments} color="" width="160px" height="88px" />
14
14
  <Box paddingTop={6}>
15
15
  <Typography variant="delta" as="p" textColor="neutral600">
16
16
  {content}
@@ -1,29 +1,58 @@
1
- import React, { useCallback } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Grid, GridItem } from '@strapi/design-system';
3
+ import { Grid, GridItem, Flex, Loader } from '@strapi/design-system';
4
+ import { useIntl } from 'react-intl';
5
+ import { AnErrorOccurred } from '@strapi/helper-plugin';
4
6
  import NpmPackageCard from '../NpmPackageCard';
7
+ import EmptyNpmPackageSearch from '../EmptyNpmPackageSearch';
5
8
 
6
9
  const NpmPackagesGrid = ({
10
+ status,
7
11
  npmPackages,
8
12
  installedPackageNames,
9
13
  useYarn,
10
14
  isInDevelopmentMode,
11
15
  npmPackageType,
12
16
  strapiAppVersion,
17
+ debouncedSearch,
13
18
  }) => {
14
- // Check if an individual package is in the dependencies
15
- const isAlreadyInstalled = useCallback(
16
- (npmPackageName) => installedPackageNames.includes(npmPackageName),
17
- [installedPackageNames]
19
+ const { formatMessage } = useIntl();
20
+
21
+ if (status === 'error') {
22
+ return (
23
+ <Flex paddingTop={8}>
24
+ <AnErrorOccurred />
25
+ </Flex>
26
+ );
27
+ }
28
+
29
+ if (status === 'loading') {
30
+ return (
31
+ <Flex justifyContent="center" paddingTop={8}>
32
+ <Loader>Loading content...</Loader>
33
+ </Flex>
34
+ );
35
+ }
36
+
37
+ const emptySearchMessage = formatMessage(
38
+ {
39
+ id: 'admin.pages.MarketPlacePage.search.empty',
40
+ defaultMessage: 'No result for "{target}"',
41
+ },
42
+ { target: debouncedSearch }
18
43
  );
19
44
 
45
+ if (npmPackages.length === 0) {
46
+ return <EmptyNpmPackageSearch content={emptySearchMessage} />;
47
+ }
48
+
20
49
  return (
21
- <Grid gap={4}>
50
+ <Grid gap={4} data-testid="marketplace-results">
22
51
  {npmPackages.map((npmPackage) => (
23
52
  <GridItem col={4} s={6} xs={12} style={{ height: '100%' }} key={npmPackage.id}>
24
53
  <NpmPackageCard
25
54
  npmPackage={npmPackage}
26
- isInstalled={isAlreadyInstalled(npmPackage.attributes.npmPackageName)}
55
+ isInstalled={installedPackageNames.includes(npmPackage.attributes.npmPackageName)}
27
56
  useYarn={useYarn}
28
57
  isInDevelopmentMode={isInDevelopmentMode}
29
58
  npmPackageType={npmPackageType}
@@ -36,17 +65,21 @@ const NpmPackagesGrid = ({
36
65
  };
37
66
 
38
67
  NpmPackagesGrid.defaultProps = {
68
+ npmPackages: [],
39
69
  installedPackageNames: [],
40
70
  strapiAppVersion: null,
71
+ debouncedSearch: '',
41
72
  };
42
73
 
43
74
  NpmPackagesGrid.propTypes = {
44
- npmPackages: PropTypes.array.isRequired,
75
+ status: PropTypes.string.isRequired,
76
+ npmPackages: PropTypes.array,
45
77
  installedPackageNames: PropTypes.arrayOf(PropTypes.string),
46
78
  useYarn: PropTypes.bool.isRequired,
47
79
  isInDevelopmentMode: PropTypes.bool.isRequired,
48
80
  npmPackageType: PropTypes.string.isRequired,
49
81
  strapiAppVersion: PropTypes.string,
82
+ debouncedSearch: PropTypes.string,
50
83
  };
51
84
 
52
85
  export default NpmPackagesGrid;
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Box, Flex } from '@strapi/design-system';
4
+ import { PaginationURLQuery, PageSizeURLQuery } from '@strapi/helper-plugin';
5
+
6
+ const NpmPackagesPagination = ({ pagination }) => {
7
+ return (
8
+ <Box paddingTop={4}>
9
+ <Flex alignItems="flex-end" justifyContent="space-between">
10
+ <PageSizeURLQuery options={['12', '24', '50', '100']} defaultValue="24" />
11
+ <PaginationURLQuery pagination={pagination} />
12
+ </Flex>
13
+ </Box>
14
+ );
15
+ };
16
+
17
+ NpmPackagesPagination.propTypes = {
18
+ pagination: PropTypes.shape({
19
+ page: PropTypes.number.isRequired,
20
+ pageCount: PropTypes.number.isRequired,
21
+ pageSize: PropTypes.number.isRequired,
22
+ total: PropTypes.number.isRequired,
23
+ }).isRequired,
24
+ };
25
+
26
+ export default NpmPackagesPagination;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { pxToRem } from '@strapi/helper-plugin';
4
+ import { Box, Flex, Typography, Layout, Main } from '@strapi/design-system';
5
+ import PageHeader from '../PageHeader';
6
+ import offlineCloud from '../../../../assets/images/icon_offline-cloud.svg';
7
+
8
+ const OfflineLayout = () => {
9
+ const { formatMessage } = useIntl();
10
+
11
+ return (
12
+ <Layout>
13
+ <Main>
14
+ <PageHeader isOnline={false} />
15
+ <Flex
16
+ width="100%"
17
+ direction="column"
18
+ alignItems="center"
19
+ justifyContent="center"
20
+ paddingTop={pxToRem(120)}
21
+ >
22
+ <Box paddingBottom={2}>
23
+ <Typography textColor="neutral700" variant="alpha">
24
+ {formatMessage({
25
+ id: 'admin.pages.MarketPlacePage.offline.title',
26
+ defaultMessage: 'You are offline',
27
+ })}
28
+ </Typography>
29
+ </Box>
30
+ <Box paddingBottom={6}>
31
+ <Typography textColor="neutral700" variant="epsilon">
32
+ {formatMessage({
33
+ id: 'admin.pages.MarketPlacePage.offline.subtitle',
34
+ defaultMessage: 'You need to be connected to the Internet to access Strapi Market.',
35
+ })}
36
+ </Typography>
37
+ </Box>
38
+ <img src={offlineCloud} alt="offline" style={{ width: '88px', height: '88px' }} />
39
+ </Flex>
40
+ </Main>
41
+ </Layout>
42
+ );
43
+ };
44
+
45
+ export default OfflineLayout;