@strapi/admin 4.10.0-beta.1 → 4.10.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 (77) hide show
  1. package/admin/src/content-manager/components/RepeatableComponent/components/Component.js +8 -2
  2. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +3 -1
  3. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +8 -2
  4. package/admin/src/content-manager/pages/EditViewLayoutManager/reducer.js +4 -4
  5. package/admin/src/content-manager/sharedReducers/crudReducer/actions.js +0 -6
  6. package/admin/src/content-manager/sharedReducers/crudReducer/constants.js +0 -1
  7. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +0 -5
  8. package/admin/src/hooks/useFetchPermissionsLayout/index.js +24 -15
  9. package/admin/src/hooks/useFetchRole/index.js +37 -30
  10. package/admin/src/hooks/useModels/index.js +22 -12
  11. package/admin/src/hooks/useSettingsForm/index.js +14 -6
  12. package/admin/src/pages/App/index.js +19 -24
  13. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +1 -3
  14. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +6 -12
  15. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +6 -10
  16. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js +18 -33
  17. package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +41 -41
  18. package/admin/src/translations/en.json +1 -1
  19. package/admin/src/translations/fr.json +89 -1
  20. package/build/{Admin-authenticatedApp.52c88751.chunk.js → Admin-authenticatedApp.b036fe95.chunk.js} +2 -2
  21. package/build/{Admin_settingsPage.257b3477.chunk.js → Admin_settingsPage.4604a16c.chunk.js} +1 -1
  22. package/build/admin-app.014adc27.chunk.js +110 -0
  23. package/build/admin-edit-roles-page.8a4063f7.chunk.js +280 -0
  24. package/build/content-manager.84f81966.chunk.js +1130 -0
  25. package/build/{content-type-builder-translation-de-json.0979cccb.chunk.js → content-type-builder-translation-de-json.393a76c0.chunk.js} +1 -1
  26. package/build/{content-type-builder-translation-dk-json.e05583e9.chunk.js → content-type-builder-translation-dk-json.fbd39bb7.chunk.js} +1 -1
  27. package/build/{content-type-builder-translation-en-json.510e88ca.chunk.js → content-type-builder-translation-en-json.446b611d.chunk.js} +1 -1
  28. package/build/{content-type-builder-translation-es-json.fe4daad8.chunk.js → content-type-builder-translation-es-json.9288474b.chunk.js} +1 -1
  29. package/build/{content-type-builder-translation-fr-json.b1eb52f6.chunk.js → content-type-builder-translation-fr-json.d35e269c.chunk.js} +1 -1
  30. package/build/{content-type-builder-translation-id-json.ee3b36bb.chunk.js → content-type-builder-translation-id-json.f0513929.chunk.js} +1 -1
  31. package/build/{content-type-builder-translation-it-json.13b3c26a.chunk.js → content-type-builder-translation-it-json.aaf16753.chunk.js} +1 -1
  32. package/build/{content-type-builder-translation-ko-json.8a274be5.chunk.js → content-type-builder-translation-ko-json.8fe21a7f.chunk.js} +1 -1
  33. package/build/{content-type-builder-translation-ms-json.2d29c1e0.chunk.js → content-type-builder-translation-ms-json.3b5d2d3e.chunk.js} +1 -1
  34. package/build/{content-type-builder-translation-nl-json.40bbc562.chunk.js → content-type-builder-translation-nl-json.225ef5d3.chunk.js} +1 -1
  35. package/build/{content-type-builder-translation-pl-json.24a34349.chunk.js → content-type-builder-translation-pl-json.92f36be2.chunk.js} +1 -1
  36. package/build/{content-type-builder-translation-pt-BR-json.97f71a9d.chunk.js → content-type-builder-translation-pt-BR-json.3bd10f89.chunk.js} +1 -1
  37. package/build/{content-type-builder-translation-ru-json.54d11230.chunk.js → content-type-builder-translation-ru-json.9bfe47ce.chunk.js} +1 -1
  38. package/build/{content-type-builder-translation-sk-json.626c9493.chunk.js → content-type-builder-translation-sk-json.d03cc18a.chunk.js} +1 -1
  39. package/build/{content-type-builder-translation-sv-json.59f5e1e5.chunk.js → content-type-builder-translation-sv-json.d23dcd32.chunk.js} +1 -1
  40. package/build/{content-type-builder-translation-th-json.6fe3ed55.chunk.js → content-type-builder-translation-th-json.7ad256e2.chunk.js} +1 -1
  41. package/build/{content-type-builder-translation-tr-json.cea4d226.chunk.js → content-type-builder-translation-tr-json.926f6191.chunk.js} +1 -1
  42. package/build/{content-type-builder-translation-uk-json.c4524247.chunk.js → content-type-builder-translation-uk-json.7bf19546.chunk.js} +1 -1
  43. package/build/{content-type-builder-translation-zh-json.faedd610.chunk.js → content-type-builder-translation-zh-json.ad24dbeb.chunk.js} +1 -1
  44. package/build/content-type-builder.68af11d2.chunk.js +126 -0
  45. package/build/en-json.c7fc79af.chunk.js +1 -0
  46. package/build/fr-json.5947cf63.chunk.js +1 -0
  47. package/build/i18n-settings-page.d95b32df.chunk.js +60 -0
  48. package/build/index.html +1 -1
  49. package/build/{main.120be100.js → main.841e0dcb.js} +194 -194
  50. package/build/{review-workflows-settings.9092ed72.chunk.js → review-workflows-settings.f7890c40.chunk.js} +1 -1
  51. package/build/{runtime~main.112b3101.js → runtime~main.965f8af8.js} +2 -2
  52. package/build/users-roles-settings-page.20656f92.chunk.js +30 -0
  53. package/build/webhook-edit-page.a3b62049.chunk.js +75 -0
  54. package/build/webhook-list-page.ca38eeef.chunk.js +71 -0
  55. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +3 -1
  56. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +7 -4
  57. package/ee/admin/hooks/useAuthProviders/index.js +28 -29
  58. package/ee/admin/pages/AuthResponse/index.js +7 -3
  59. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +1 -1
  60. package/ee/server/controllers/authentication/middlewares.js +2 -1
  61. package/ee/server/services/index.js +1 -0
  62. package/ee/server/services/review-workflows/metrics.js +24 -0
  63. package/ee/server/services/review-workflows/review-workflows.js +25 -11
  64. package/ee/server/services/review-workflows/stages.js +28 -10
  65. package/ee/server/utils/persisted-tables.js +7 -5
  66. package/package.json +10 -10
  67. package/server/strategies/api-token.js +8 -1
  68. package/build/admin-app.dfaeea5d.chunk.js +0 -110
  69. package/build/admin-edit-roles-page.4f1858e9.chunk.js +0 -280
  70. package/build/content-manager.def692c2.chunk.js +0 -1130
  71. package/build/content-type-builder.5e1f4afc.chunk.js +0 -126
  72. package/build/en-json.08303b37.chunk.js +0 -1
  73. package/build/fr-json.f66c3211.chunk.js +0 -1
  74. package/build/i18n-settings-page.7d80aae0.chunk.js +0 -60
  75. package/build/users-roles-settings-page.2f85dcec.chunk.js +0 -30
  76. package/build/webhook-edit-page.213f0075.chunk.js +0 -75
  77. package/build/webhook-list-page.5beb2a5c.chunk.js +0 -71
@@ -97,11 +97,17 @@ const DraggedItem = ({
97
97
  const accordionRef = useRef(null);
98
98
  const { formatMessage } = useIntl();
99
99
 
100
- const [parentFieldName] = componentFieldName.split('.');
100
+ /**
101
+ * The last item in the fieldName array will be the index of this component.
102
+ * Drag and drop should be isolated to the parent component so nested repeatable
103
+ * components are not affected by the drag and drop of the parent component in
104
+ * their own re-ordering context.
105
+ */
106
+ const componentKey = componentFieldName.split('.').slice(0, -1).join('.');
101
107
 
102
108
  const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] =
103
109
  useDragAndDrop(!isReadOnly, {
104
- type: `${ItemTypes.COMPONENT}_${parentFieldName}`,
110
+ type: `${ItemTypes.COMPONENT}_${componentKey}`,
105
111
  index,
106
112
  item: {
107
113
  displayedValue,
@@ -102,7 +102,9 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => {
102
102
  );
103
103
  });
104
104
 
105
- const { isResizable } = fieldSizes[attributes[selectedField].type];
105
+ // Check for a custom input provided by a custom field, or use the default one for that type
106
+ const { type, customField } = attributes[selectedField];
107
+ const { isResizable } = fieldSizes[customField] ?? fieldSizes[type];
106
108
 
107
109
  const sizeField = (
108
110
  <GridItem col={6} key="size">
@@ -30,8 +30,14 @@ const reducer = (state = initialState, action) =>
30
30
  }
31
31
  case 'ON_ADD_FIELD': {
32
32
  const newState = cloneDeep(state);
33
- const type = get(newState, ['modifiedData', 'attributes', action.name, 'type'], '');
34
- const size = action.fieldSizes[type]?.default ?? DEFAULT_FIELD_SIZE;
33
+ const attribute = get(newState, ['modifiedData', 'attributes', action.name], {});
34
+
35
+ // Get the default size, checking custom fields first, then the type and generic defaults
36
+ const size =
37
+ action.fieldSizes[attribute?.customField]?.default ??
38
+ action.fieldSizes[attribute?.type]?.default ??
39
+ DEFAULT_FIELD_SIZE;
40
+
35
41
  const listSize = get(newState, layoutPathEdit, []).length;
36
42
  const actualRowContentPath = [...layoutPathEdit, listSize - 1, 'rowContent'];
37
43
  const rowContentToSet = get(newState, actualRowContentPath, []);
@@ -12,18 +12,18 @@ export const initialState = {
12
12
 
13
13
  const editViewManagerReducer = (state = initialState, action) =>
14
14
  // eslint-disable-next-line consistent-return
15
- produce(state, (drafState) => {
15
+ produce(state, (draftState) => {
16
16
  switch (action.type) {
17
17
  case RESET_PROPS: {
18
- drafState.currentLayout = null;
18
+ draftState.currentLayout = null;
19
19
  break;
20
20
  }
21
21
  case SET_LAYOUT: {
22
- drafState.currentLayout = action.layout;
22
+ draftState.currentLayout = action.layout;
23
23
  break;
24
24
  }
25
25
  default:
26
- return drafState;
26
+ return draftState;
27
27
  }
28
28
  });
29
29
 
@@ -2,7 +2,6 @@ import {
2
2
  GET_DATA,
3
3
  GET_DATA_SUCCEEDED,
4
4
  INIT_FORM,
5
- UPDATE_PARTIAL_DATA,
6
5
  RESET_PROPS,
7
6
  SET_DATA_STRUCTURES,
8
7
  SET_STATUS,
@@ -48,8 +47,3 @@ export const submitSucceeded = (data) => ({
48
47
  export const clearSetModifiedDataOnly = () => ({
49
48
  type: CLEAR_SET_MODIFIED_DATA_ONLY,
50
49
  });
51
-
52
- export const updatePartialData = (data) => ({
53
- type: UPDATE_PARTIAL_DATA,
54
- data,
55
- });
@@ -7,4 +7,3 @@ export const SET_STATUS = 'ContentManager/CrudReducer/SET_STATUS';
7
7
  export const SUBMIT_SUCCEEDED = 'ContentManager/CrudReducer/SUBMIT_SUCCEEDED';
8
8
  export const CLEAR_SET_MODIFIED_DATA_ONLY =
9
9
  'ContentManager/CrudReducer/CLEAR_SET_MODIFIED_DATA_ONLY';
10
- export const UPDATE_PARTIAL_DATA = 'ContentManager/CrudReducer/PARTIAL_DATA_UPDATE';
@@ -12,7 +12,6 @@ import {
12
12
  GET_DATA,
13
13
  GET_DATA_SUCCEEDED,
14
14
  INIT_FORM,
15
- UPDATE_PARTIAL_DATA,
16
15
  RESET_PROPS,
17
16
  SET_DATA_STRUCTURES,
18
17
  SET_STATUS,
@@ -54,10 +53,6 @@ const crudReducer = (state = crudInitialState, action) =>
54
53
  draftState.data = state.contentTypeDataStructure;
55
54
  break;
56
55
  }
57
- case UPDATE_PARTIAL_DATA: {
58
- draftState.data = { ...state.data, ...action.data };
59
- break;
60
- }
61
56
  case RESET_PROPS: {
62
57
  return crudInitialState;
63
58
  }
@@ -1,30 +1,39 @@
1
1
  import { useEffect, useReducer } from 'react';
2
- import { request } from '@strapi/helper-plugin';
2
+ import { useFetchClient } from '@strapi/helper-plugin';
3
3
 
4
4
  import reducer, { initialState } from './reducer';
5
5
 
6
+ /**
7
+ * TODO: refactor this to use react-query and move it to the `Roles` SettingsPage
8
+ */
6
9
  const useFetchPermissionsLayout = (id) => {
7
10
  const [{ data, error, isLoading }, dispatch] = useReducer(reducer, initialState);
11
+ const { get } = useFetchClient();
8
12
 
9
13
  useEffect(() => {
10
14
  const getData = async () => {
11
- dispatch({
12
- type: 'GET_DATA',
13
- });
14
-
15
- const { data } = await request('/admin/permissions', {
16
- method: 'GET',
17
- params: { role: id },
18
- });
19
-
20
- dispatch({
21
- type: 'GET_DATA_SUCCEEDED',
22
- data,
23
- });
15
+ try {
16
+ dispatch({
17
+ type: 'GET_DATA',
18
+ });
19
+
20
+ const {
21
+ data: { data },
22
+ } = await get('/admin/permissions', {
23
+ params: { role: id },
24
+ });
25
+
26
+ dispatch({
27
+ type: 'GET_DATA_SUCCEEDED',
28
+ data,
29
+ });
30
+ } catch (err) {
31
+ // silence is golden
32
+ }
24
33
  };
25
34
 
26
35
  getData();
27
- }, [id]);
36
+ }, [id, get]);
28
37
 
29
38
  return { data, error, isLoading };
30
39
  };
@@ -1,13 +1,48 @@
1
1
  import { useCallback, useReducer, useEffect } from 'react';
2
- import { request, useNotification } from '@strapi/helper-plugin';
2
+ import { useFetchClient, useNotification } from '@strapi/helper-plugin';
3
3
  import reducer, { initialState } from './reducer';
4
4
 
5
5
  const useFetchRole = (id) => {
6
6
  const toggleNotification = useNotification();
7
7
  const [state, dispatch] = useReducer(reducer, initialState);
8
8
 
9
+ const { get } = useFetchClient();
10
+
9
11
  useEffect(() => {
10
12
  if (id) {
13
+ const fetchRole = async (roleId) => {
14
+ try {
15
+ const [
16
+ {
17
+ data: { data: role },
18
+ },
19
+ {
20
+ data: { data: permissions },
21
+ },
22
+ ] = await Promise.all(
23
+ [`roles/${roleId}`, `roles/${roleId}/permissions`].map((endPoint) =>
24
+ get(`/admin/${endPoint}`)
25
+ )
26
+ );
27
+
28
+ dispatch({
29
+ type: 'GET_DATA_SUCCEEDED',
30
+ role,
31
+ permissions,
32
+ });
33
+ } catch (err) {
34
+ console.error(err);
35
+
36
+ dispatch({
37
+ type: 'GET_DATA_ERROR',
38
+ });
39
+ toggleNotification({
40
+ type: 'warning',
41
+ message: { id: 'notification.error' },
42
+ });
43
+ }
44
+ };
45
+
11
46
  fetchRole(id);
12
47
  } else {
13
48
  dispatch({
@@ -16,35 +51,7 @@ const useFetchRole = (id) => {
16
51
  permissions: [],
17
52
  });
18
53
  }
19
-
20
- // eslint-disable-next-line react-hooks/exhaustive-deps
21
- }, [id]);
22
-
23
- const fetchRole = async (roleId) => {
24
- try {
25
- const [{ data: role }, { data: permissions }] = await Promise.all(
26
- [`roles/${roleId}`, `roles/${roleId}/permissions`].map((endPoint) =>
27
- request(`/admin/${endPoint}`, { method: 'GET' })
28
- )
29
- );
30
-
31
- dispatch({
32
- type: 'GET_DATA_SUCCEEDED',
33
- role,
34
- permissions,
35
- });
36
- } catch (err) {
37
- console.error(err);
38
-
39
- dispatch({
40
- type: 'GET_DATA_ERROR',
41
- });
42
- toggleNotification({
43
- type: 'warning',
44
- message: { id: 'notification.error' },
45
- });
46
- }
47
- };
54
+ }, [get, id, toggleNotification]);
48
55
 
49
56
  const handleSubmitSucceeded = useCallback((data) => {
50
57
  dispatch({
@@ -1,26 +1,32 @@
1
- import { useReducer, useEffect } from 'react';
2
- import { request, useNotification } from '@strapi/helper-plugin';
1
+ import { useReducer, useEffect, useCallback } from 'react';
2
+ import { useFetchClient, useNotification } from '@strapi/helper-plugin';
3
3
  import reducer, { initialState } from './reducer';
4
4
 
5
+ /**
6
+ * TODO: refactor this to not use the `useReducer` hook,
7
+ * it's not really necessary. Also use `useQuery`?
8
+ */
5
9
  const useModels = () => {
6
10
  const toggleNotification = useNotification();
7
11
  const [state, dispatch] = useReducer(reducer, initialState);
8
12
 
9
- useEffect(() => {
10
- fetchModels();
11
- // eslint-disable-next-line react-hooks/exhaustive-deps
12
- }, []);
13
+ const { get } = useFetchClient();
13
14
 
14
- const fetchModels = async () => {
15
+ const fetchModels = useCallback(async () => {
15
16
  dispatch({
16
17
  type: 'GET_MODELS',
17
18
  });
18
19
 
19
20
  try {
20
- const [{ data: components }, { data: contentTypes }] = await Promise.all(
21
- ['components', 'content-types'].map((endPoint) =>
22
- request(`/content-manager/${endPoint}`, { method: 'GET' })
23
- )
21
+ const [
22
+ {
23
+ data: { data: components },
24
+ },
25
+ {
26
+ data: { data: contentTypes },
27
+ },
28
+ ] = await Promise.all(
29
+ ['components', 'content-types'].map((endPoint) => get(`/content-manager/${endPoint}`))
24
30
  );
25
31
 
26
32
  dispatch({
@@ -37,7 +43,11 @@ const useModels = () => {
37
43
  message: { id: 'notification.error' },
38
44
  });
39
45
  }
40
- };
46
+ }, [toggleNotification, get]);
47
+
48
+ useEffect(() => {
49
+ fetchModels();
50
+ }, [fetchModels]);
41
51
 
42
52
  return {
43
53
  ...state,
@@ -1,10 +1,15 @@
1
1
  import { useEffect, useReducer } from 'react';
2
- import { request, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
2
+ import { useFetchClient, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
3
3
  import omit from 'lodash/omit';
4
4
  import { checkFormValidity, formatAPIErrors } from '../../utils';
5
5
  import { initialState, reducer } from './reducer';
6
6
  import init from './init';
7
7
 
8
+ /**
9
+ * TODO: refactor this, it's confusing and hard to read.
10
+ * It's also only used in `Settings/pages/SingleSignOn` so it can
11
+ * probably be deleted and everything written there...
12
+ */
8
13
  const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
9
14
  const [
10
15
  { formErrors, initialData, isLoading, modifiedData, showHeaderButtonLoader, showHeaderLoader },
@@ -13,10 +18,14 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
13
18
  const toggleNotification = useNotification();
14
19
  const { lockApp, unlockApp } = useOverlayBlocker();
15
20
 
21
+ const { get, put } = useFetchClient();
22
+
16
23
  useEffect(() => {
17
24
  const getData = async () => {
18
25
  try {
19
- const { data } = await request(endPoint, { method: 'GET' });
26
+ const {
27
+ data: { data },
28
+ } = await get(endPoint);
20
29
 
21
30
  dispatch({
22
31
  type: 'GET_DATA_SUCCEEDED',
@@ -85,10 +94,9 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
85
94
  cleanedData.roles = cleanedData.roles.map((role) => role.id);
86
95
  }
87
96
 
88
- const { data } = await request(endPoint, {
89
- method: 'PUT',
90
- body: cleanedData,
91
- });
97
+ const {
98
+ data: { data },
99
+ } = await put(endPoint, cleanedData);
92
100
 
93
101
  cbSuccess(data);
94
102
 
@@ -6,17 +6,16 @@
6
6
 
7
7
  import React, { useEffect, useState, useMemo, lazy, Suspense } from 'react';
8
8
  import { Switch, Route } from 'react-router-dom';
9
+ import axios from 'axios';
9
10
  import {
10
11
  LoadingIndicatorPage,
11
12
  auth,
12
- request,
13
13
  useNotification,
14
14
  TrackingProvider,
15
15
  prefixFileUrlWithBackendUrl,
16
16
  useAppInfos,
17
17
  useFetchClient,
18
18
  } from '@strapi/helper-plugin';
19
- import axios from 'axios';
20
19
  import { SkipToContent } from '@strapi/design-system';
21
20
  import { useIntl } from 'react-intl';
22
21
  import PrivateRoute from '../../components/PrivateRoute';
@@ -41,7 +40,7 @@ function App() {
41
40
  hasAdmin: false,
42
41
  });
43
42
  const appInfo = useAppInfos();
44
- const { get } = useFetchClient();
43
+ const { get, post } = useFetchClient();
45
44
 
46
45
  const authRoutes = useMemo(() => {
47
46
  return makeUniqueRoutes(
@@ -57,11 +56,10 @@ function App() {
57
56
  const renewToken = async () => {
58
57
  try {
59
58
  const {
60
- data: { token },
61
- } = await request('/admin/renew-token', {
62
- method: 'POST',
63
- body: { token: currentToken },
64
- });
59
+ data: {
60
+ data: { token },
61
+ },
62
+ } = await post('/admin/renew-token', { token: currentToken });
65
63
  auth.updateToken(token);
66
64
  } catch (err) {
67
65
  // Refresh app
@@ -73,7 +71,7 @@ function App() {
73
71
  if (currentToken) {
74
72
  renewToken();
75
73
  }
76
- }, []);
74
+ }, [post]);
77
75
 
78
76
  useEffect(() => {
79
77
  const getData = async () => {
@@ -82,7 +80,7 @@ function App() {
82
80
  data: {
83
81
  data: { hasAdmin, uuid, menuLogo, authLogo },
84
82
  },
85
- } = await axios.get(`${strapi.backendURL}/admin/init`);
83
+ } = await get(`/admin/init`);
86
84
 
87
85
  updateProjectSettings({
88
86
  menuLogo: prefixFileUrlWithBackendUrl(menuLogo),
@@ -102,20 +100,17 @@ function App() {
102
100
  setTelemetryProperties(properties);
103
101
 
104
102
  try {
105
- await fetch('https://analytics.strapi.io/api/v2/track', {
106
- method: 'POST',
107
- body: JSON.stringify({
108
- // This event is anonymous
109
- event: 'didInitializeAdministration',
110
- userId: '',
111
- deviceId,
112
- eventPropeties: {},
113
- userProperties: { environment: appInfo.currentEnvironment },
114
- groupProperties: { ...properties, projectId: uuid },
115
- }),
116
- headers: {
117
- 'Content-Type': 'application/json',
118
- },
103
+ /**
104
+ * TODO: remove this call to `axios`
105
+ */
106
+ await axios.post('https://analytics.strapi.io/api/v2/track', {
107
+ // This event is anonymous
108
+ event: 'didInitializeAdministration',
109
+ userId: '',
110
+ deviceId,
111
+ eventPropeties: {},
112
+ userProperties: { environment: appInfo.currentEnvironment },
113
+ groupProperties: { ...properties, projectId: uuid },
119
114
  });
120
115
  } catch (e) {
121
116
  // Silent.
@@ -43,9 +43,7 @@ const PendingLogoDialog = ({ onClose, asset, prev, next, goTo, setLocalImage, on
43
43
  })}
44
44
  </Button>
45
45
  </Flex>
46
- <Box maxWidth={pxToRem(180)}>
47
- <ImageCardAsset asset={asset} />
48
- </Box>
46
+ <Box maxWidth={pxToRem(180)}>{asset.url ? <ImageCardAsset asset={asset} /> : null}</Box>
49
47
  </Box>
50
48
  <ModalFooter
51
49
  startActions={
@@ -5,7 +5,7 @@ import {
5
5
  Form,
6
6
  LoadingIndicatorPage,
7
7
  SettingsPageTitle,
8
- request,
8
+ useFetchClient,
9
9
  useNotification,
10
10
  useOverlayBlocker,
11
11
  useTracking,
@@ -59,6 +59,8 @@ const CreatePage = () => {
59
59
  const { isLoading: isLayoutLoading, data: permissionsLayout } = useFetchPermissionsLayout();
60
60
  const { permissions: rolePermissions, isLoading: isRoleLoading } = useFetchRole(id);
61
61
 
62
+ const { post, put } = useFetchClient();
63
+
62
64
  const handleCreateRoleSubmit = (data) => {
63
65
  lockApp();
64
66
  setIsSubmiting(true);
@@ -69,13 +71,8 @@ const CreatePage = () => {
69
71
  trackUsage('willCreateNewRole');
70
72
  }
71
73
 
72
- Promise.resolve(
73
- request('/admin/roles', {
74
- method: 'POST',
75
- body: data,
76
- })
77
- )
78
- .then(async (res) => {
74
+ Promise.resolve(post('/admin/roles', data))
75
+ .then(async ({ data: res }) => {
79
76
  const { permissionsToSend } = permissionsRef.current.getPermissions();
80
77
 
81
78
  if (id) {
@@ -85,10 +82,7 @@ const CreatePage = () => {
85
82
  }
86
83
 
87
84
  if (res.data.id && !isEmpty(permissionsToSend)) {
88
- await request(`/admin/roles/${res.data.id}/permissions`, {
89
- method: 'PUT',
90
- body: { permissions: permissionsToSend },
91
- });
85
+ await put(`/admin/roles/${res.data.id}/permissions`, { permissions: permissionsToSend });
92
86
  }
93
87
 
94
88
  return res;
@@ -1,6 +1,6 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import {
3
- request,
3
+ useFetchClient,
4
4
  useNotification,
5
5
  useOverlayBlocker,
6
6
  useTracking,
@@ -37,6 +37,8 @@ const EditPage = () => {
37
37
  onSubmitSucceeded,
38
38
  } = useFetchRole(id);
39
39
 
40
+ const { put } = useFetchClient();
41
+
40
42
  const handleEditRoleSubmit = async (data) => {
41
43
  try {
42
44
  lockApp();
@@ -44,17 +46,11 @@ const EditPage = () => {
44
46
 
45
47
  const { permissionsToSend, didUpdateConditions } = permissionsRef.current.getPermissions();
46
48
 
47
- await request(`/admin/roles/${id}`, {
48
- method: 'PUT',
49
- body: data,
50
- });
49
+ await put(`/admin/roles/${id}`, data);
51
50
 
52
51
  if (role.code !== 'strapi-super-admin') {
53
- await request(`/admin/roles/${id}/permissions`, {
54
- method: 'PUT',
55
- body: {
56
- permissions: permissionsToSend,
57
- },
52
+ await put(`/admin/roles/${id}/permissions`, {
53
+ permissions: permissionsToSend,
58
54
  });
59
55
 
60
56
  if (didUpdateConditions) {
@@ -3,12 +3,10 @@
3
3
  * EditView
4
4
  *
5
5
  */
6
- import React, { useCallback, useMemo } from 'react';
6
+ import * as React from 'react';
7
7
  import {
8
8
  LoadingIndicatorPage,
9
- request,
10
9
  SettingsPageTitle,
11
- to,
12
10
  useNotification,
13
11
  useOverlayBlocker,
14
12
  useFetchClient,
@@ -30,19 +28,20 @@ const EditView = () => {
30
28
  const toggleNotification = useNotification();
31
29
  const queryClient = useQueryClient();
32
30
  const { isLoading: isLoadingForModels, collectionTypes } = useModels();
33
- const { post } = useFetchClient();
31
+ const { put, get, post } = useFetchClient();
34
32
 
35
33
  const isCreating = id === 'create';
36
34
 
37
- const fetchWebhook = useCallback(
38
- async (id) => {
39
- const [err, { data }] = await to(
40
- request(`/admin/webhooks/${id}`, {
41
- method: 'GET',
42
- })
43
- );
35
+ const { isLoading, data } = useQuery(
36
+ ['get-webhook', id],
37
+ async () => {
38
+ try {
39
+ const {
40
+ data: { data },
41
+ } = await get(`/admin/webhooks/${id}`);
44
42
 
45
- if (err) {
43
+ return data;
44
+ } catch (err) {
46
45
  toggleNotification({
47
46
  type: 'warning',
48
47
  message: { id: 'notification.error' },
@@ -50,16 +49,12 @@ const EditView = () => {
50
49
 
51
50
  return null;
52
51
  }
53
-
54
- return data;
55
52
  },
56
- [toggleNotification]
53
+ {
54
+ enabled: !isCreating,
55
+ }
57
56
  );
58
57
 
59
- const { isLoading, data } = useQuery(['get-webhook', id], () => fetchWebhook(id), {
60
- enabled: !isCreating,
61
- });
62
-
63
58
  const {
64
59
  isLoading: isTriggering,
65
60
  data: triggerResponse,
@@ -77,25 +72,15 @@ const EditView = () => {
77
72
  },
78
73
  });
79
74
 
80
- const createWebhookMutation = useMutation((body) =>
81
- request('/admin/webhooks', {
82
- method: 'POST',
83
- body,
84
- })
85
- );
75
+ const createWebhookMutation = useMutation((body) => post('/admin/webhooks', body));
86
76
 
87
- const updateWebhookMutation = useMutation(({ id, body }) =>
88
- request(`/admin/webhooks/${id}`, {
89
- method: 'PUT',
90
- body,
91
- })
92
- );
77
+ const updateWebhookMutation = useMutation(({ id, body }) => put(`/admin/webhooks/${id}`, body));
93
78
 
94
79
  const handleSubmit = async (data) => {
95
80
  if (isCreating) {
96
81
  lockApp();
97
82
  createWebhookMutation.mutate(cleanData(data), {
98
- onSuccess(result) {
83
+ onSuccess({ data: result }) {
99
84
  toggleNotification({
100
85
  type: 'success',
101
86
  message: { id: 'Settings.webhooks.created' },
@@ -138,7 +123,7 @@ const EditView = () => {
138
123
  }
139
124
  };
140
125
 
141
- const isDraftAndPublishEvents = useMemo(
126
+ const isDraftAndPublishEvents = React.useMemo(
142
127
  () => collectionTypes.some((ct) => ct.options.draftAndPublish === true),
143
128
  [collectionTypes]
144
129
  );