@strapi/admin 4.1.6-alpha.1 → 4.1.6

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 (31) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +17 -3
  2. package/admin/src/content-manager/components/DynamicTable/CellContent/utils/hasContent.js +33 -2
  3. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +42 -42
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.js +18 -0
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/handleAPIError.js +15 -0
  6. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +0 -1
  7. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/schema.js +21 -19
  8. package/admin/src/content-manager/components/InputUID/index.js +1 -5
  9. package/admin/src/content-manager/components/Inputs/index.js +8 -10
  10. package/admin/src/content-manager/components/RepeatableComponent/index.js +1 -4
  11. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +15 -3
  12. package/admin/src/content-manager/components/Wysiwyg/index.js +3 -4
  13. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +6 -1
  14. package/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +7 -1
  15. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +1 -4
  16. package/admin/src/content-manager/pages/EditView/DraftAndPublishBadge/index.js +1 -4
  17. package/admin/src/content-manager/pages/ListView/selectors.js +3 -6
  18. package/admin/src/content-manager/testUtils/data.js +5 -1
  19. package/admin/src/content-manager/utils/isFieldTypeNumber.js +3 -0
  20. package/admin/src/translations/en.json +2 -0
  21. package/build/{Admin-authenticatedApp.cf7104f9.chunk.js → Admin-authenticatedApp.c0239c26.chunk.js} +1 -1
  22. package/build/content-manager.abde723b.chunk.js +1 -0
  23. package/build/{en-json.c55e5344.chunk.js → en-json.94e6ed8a.chunk.js} +1 -1
  24. package/build/index.html +1 -1
  25. package/build/{main.06e1a4bf.js → main.82ea2ad5.js} +2 -2
  26. package/build/{main.06e1a4bf.js.LICENSE.txt → main.82ea2ad5.js.LICENSE.txt} +0 -0
  27. package/build/{runtime~main.b090a1bb.js → runtime~main.0634180a.js} +1 -1
  28. package/package.json +5 -5
  29. package/server/validation/permission.js +5 -1
  30. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getYupInnerErrors.js +0 -17
  31. package/build/content-manager.2f6a2082.chunk.js +0 -1
@@ -203,8 +203,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
203
203
  const displayErrors = useCallback(
204
204
  err => {
205
205
  const errorPayload = err.response.data;
206
- console.error(errorPayload);
207
-
208
206
  let errorMessage = get(errorPayload, ['error', 'message'], 'Bad Request');
209
207
 
210
208
  // TODO handle errors correctly when back-end ready
@@ -272,10 +270,14 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
272
270
  dispatch(setStatus('resolved'));
273
271
 
274
272
  replace(`/content-manager/collectionType/${slug}/${data.id}${rawQuery}`);
273
+
274
+ return Promise.resolve(data);
275
275
  } catch (err) {
276
- trackUsageRef.current('didNotCreateEntry', { error: err, trackerProperty });
277
276
  displayErrors(err);
277
+ trackUsageRef.current('didNotCreateEntry', { error: err, trackerProperty });
278
278
  dispatch(setStatus('resolved'));
279
+
280
+ return Promise.reject(err);
279
281
  }
280
282
  },
281
283
  [
@@ -308,9 +310,13 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
308
310
  type: 'success',
309
311
  message: { id: getTrad('success.record.publish') },
310
312
  });
313
+
314
+ return Promise.resolve(data);
311
315
  } catch (err) {
312
316
  displayErrors(err);
313
317
  dispatch(setStatus('resolved'));
318
+
319
+ return Promise.reject(err);
314
320
  }
315
321
  }, [cleanReceivedData, displayErrors, id, slug, dispatch, toggleNotification]);
316
322
 
@@ -334,11 +340,15 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
334
340
  dispatch(submitSucceeded(cleanReceivedData(data)));
335
341
 
336
342
  dispatch(setStatus('resolved'));
343
+
344
+ return Promise.resolve(data);
337
345
  } catch (err) {
338
346
  trackUsageRef.current('didNotEditEntry', { error: err, trackerProperty });
339
347
  displayErrors(err);
340
348
 
341
349
  dispatch(setStatus('resolved'));
350
+
351
+ return Promise.reject(err);
342
352
  }
343
353
  },
344
354
  [cleanReceivedData, displayErrors, slug, id, dispatch, toggleNotification]
@@ -362,9 +372,13 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
362
372
 
363
373
  dispatch(submitSucceeded(cleanReceivedData(data)));
364
374
  dispatch(setStatus('resolved'));
375
+
376
+ return Promise.resolve(data);
365
377
  } catch (err) {
366
378
  dispatch(setStatus('resolved'));
367
379
  displayErrors(err);
380
+
381
+ return Promise.reject(err);
368
382
  }
369
383
  }, [cleanReceivedData, displayErrors, id, slug, dispatch, toggleNotification]);
370
384
 
@@ -1,11 +1,13 @@
1
1
  import isEmpty from 'lodash/isEmpty';
2
+ import isNumber from 'lodash/isNumber';
2
3
 
3
4
  import isSingleRelation from './isSingleRelation';
5
+ import isFieldTypeNumber from '../../../../utils/isFieldTypeNumber';
4
6
 
5
7
  export default function hasContent(type, content, metadatas, fieldSchema) {
6
8
  if (type === 'component') {
7
9
  const {
8
- mainField: { name: mainFieldName },
10
+ mainField: { name: mainFieldName, type: mainFieldType },
9
11
  } = metadatas;
10
12
 
11
13
  // Repeatable fields show the ID as fallback, in case the mainField
@@ -14,7 +16,28 @@ export default function hasContent(type, content, metadatas, fieldSchema) {
14
16
  return content.length > 0;
15
17
  }
16
18
 
17
- return !isEmpty(content[mainFieldName]);
19
+ const value = content?.[mainFieldName];
20
+
21
+ // relations, media ... show the id as fallback
22
+ if (mainFieldName === 'id' && ![undefined, null].includes(value)) {
23
+ return true;
24
+ }
25
+
26
+ /* The ID field reports itself as type `integer`, which makes it
27
+ impossible to distinguish it from other number fields.
28
+
29
+ Biginteger fields need to be treated as strings, as `isNumber`
30
+ doesn't deal with them.
31
+ */
32
+ if (
33
+ isFieldTypeNumber(mainFieldType) &&
34
+ mainFieldType !== 'biginteger' &&
35
+ mainFieldName !== 'id'
36
+ ) {
37
+ return isNumber(value);
38
+ }
39
+
40
+ return !isEmpty(value);
18
41
  }
19
42
 
20
43
  if (type === 'relation') {
@@ -25,5 +48,13 @@ export default function hasContent(type, content, metadatas, fieldSchema) {
25
48
  return content.count > 0;
26
49
  }
27
50
 
51
+ /*
52
+ Biginteger fields need to be treated as strings, as `isNumber`
53
+ doesn't deal with them.
54
+ */
55
+ if (isFieldTypeNumber(type) && type !== 'biginteger') {
56
+ return isNumber(content);
57
+ }
58
+
28
59
  return !isEmpty(content);
29
60
  }
@@ -1,5 +1,9 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef, useReducer } from 'react';
2
- import { cloneDeep, get, isEmpty, isEqual, set } from 'lodash';
2
+ import isEmpty from 'lodash/isEmpty';
3
+ import cloneDeep from 'lodash/cloneDeep';
4
+ import get from 'lodash/get';
5
+ import isEqual from 'lodash/isEqual';
6
+ import set from 'lodash/set';
3
7
  import PropTypes from 'prop-types';
4
8
  import { useIntl } from 'react-intl';
5
9
  import { Prompt, Redirect } from 'react-router-dom';
@@ -10,10 +14,13 @@ import {
10
14
  useNotification,
11
15
  useOverlayBlocker,
12
16
  useTracking,
17
+ getYupInnerErrors,
13
18
  } from '@strapi/helper-plugin';
19
+
14
20
  import { getTrad, removeKeyInObject } from '../../utils';
15
21
  import reducer, { initialState } from './reducer';
16
- import { cleanData, createYupSchema, getYupInnerErrors } from './utils';
22
+ import { cleanData, createYupSchema } from './utils';
23
+ import { getAPIInnerError } from './utils/getAPIInnerError';
17
24
 
18
25
  const EditViewDataManagerProvider = ({
19
26
  allLayoutData,
@@ -262,7 +269,7 @@ const EditViewDataManagerProvider = ({
262
269
  );
263
270
 
264
271
  const createFormData = useCallback(
265
- data => {
272
+ (data) => {
266
273
  // First we need to remove the added keys needed for the dnd
267
274
  const preparedData = removeKeyInObject(cloneDeep(data), '__temp_key__');
268
275
  // Then we need to apply our helper
@@ -286,34 +293,31 @@ const EditViewDataManagerProvider = ({
286
293
  }, [hasDraftAndPublish, shouldNotRunValidations]);
287
294
 
288
295
  const handleSubmit = useCallback(
289
- async e => {
296
+ async (e) => {
290
297
  e.preventDefault();
291
298
  let errors = {};
292
299
 
293
- // First validate the form
294
300
  try {
295
301
  await yupSchema.validate(modifiedData, { abortEarly: false });
296
-
297
- const formData = createFormData(modifiedData);
298
-
299
- if (isCreatingEntry) {
300
- onPost(formData, trackerProperty);
301
- } else {
302
- onPut(formData, trackerProperty);
303
- }
304
302
  } catch (err) {
305
- console.log('ValidationError');
306
- console.log(err);
307
-
308
303
  errors = getYupInnerErrors(err);
304
+ }
309
305
 
310
- toggleNotification({
311
- type: 'warning',
312
- message: {
313
- id: getTrad('containers.EditView.notification.errors'),
314
- defaultMessage: 'The form contains some errors',
315
- },
316
- });
306
+ try {
307
+ if (isEmpty(errors)) {
308
+ const formData = createFormData(modifiedData);
309
+
310
+ if (isCreatingEntry) {
311
+ await onPost(formData, trackerProperty);
312
+ } else {
313
+ await onPut(formData, trackerProperty);
314
+ }
315
+ }
316
+ } catch (err) {
317
+ errors = {
318
+ ...errors,
319
+ ...getAPIInnerError(err),
320
+ };
317
321
  }
318
322
 
319
323
  dispatch({
@@ -321,16 +325,7 @@ const EditViewDataManagerProvider = ({
321
325
  errors,
322
326
  });
323
327
  },
324
- [
325
- createFormData,
326
- isCreatingEntry,
327
- modifiedData,
328
- onPost,
329
- onPut,
330
- toggleNotification,
331
- trackerProperty,
332
- yupSchema,
333
- ]
328
+ [createFormData, isCreatingEntry, modifiedData, onPost, onPut, trackerProperty, yupSchema]
334
329
  );
335
330
 
336
331
  const handlePublish = useCallback(async () => {
@@ -345,17 +340,22 @@ const EditViewDataManagerProvider = ({
345
340
  let errors = {};
346
341
 
347
342
  try {
348
- // Validate the form using yup
349
343
  await schema.validate(modifiedData, { abortEarly: false });
350
-
351
- onPublish();
352
344
  } catch (err) {
353
- console.error('ValidationError');
354
- console.error(err);
355
-
356
345
  errors = getYupInnerErrors(err);
357
346
  }
358
347
 
348
+ try {
349
+ if (isEmpty(errors)) {
350
+ await onPublish();
351
+ }
352
+ } catch (err) {
353
+ errors = {
354
+ ...errors,
355
+ ...getAPIInnerError(err),
356
+ };
357
+ }
358
+
359
359
  dispatch({
360
360
  type: 'SET_FORM_ERRORS',
361
361
  errors,
@@ -363,8 +363,8 @@ const EditViewDataManagerProvider = ({
363
363
  }, [allLayoutData, currentContentTypeLayout, isCreatingEntry, modifiedData, onPublish]);
364
364
 
365
365
  const shouldCheckDZErrors = useCallback(
366
- dzName => {
367
- const doesDZHaveError = Object.keys(formErrors).some(key => key.split('.')[0] === dzName);
366
+ (dzName) => {
367
+ const doesDZHaveError = Object.keys(formErrors).some((key) => key.split('.')[0] === dzName);
368
368
  const shouldCheckErrors = !isEmpty(formErrors) && doesDZHaveError;
369
369
 
370
370
  return shouldCheckErrors;
@@ -418,7 +418,7 @@ const EditViewDataManagerProvider = ({
418
418
  });
419
419
  }, []);
420
420
 
421
- const onRemoveRelation = useCallback(keys => {
421
+ const onRemoveRelation = useCallback((keys) => {
422
422
  dispatch({
423
423
  type: 'REMOVE_RELATION',
424
424
  keys,
@@ -0,0 +1,18 @@
1
+ import { getTrad } from '../../../utils';
2
+
3
+ export function getAPIInnerError(error) {
4
+ const errorPayload = error.response.data.error.details.errors;
5
+ const validationErrors = errorPayload.reduce((acc, err) => {
6
+ acc[err.path.join('.')] = {
7
+ id: getTrad(`apiError.${err.message}`),
8
+ defaultMessage: err.message,
9
+ values: {
10
+ field: err.path[err.path.length - 1],
11
+ },
12
+ };
13
+
14
+ return acc;
15
+ }, {});
16
+
17
+ return validationErrors;
18
+ }
@@ -0,0 +1,15 @@
1
+ import { getTrad } from '../../../utils';
2
+
3
+ export function handleAPIError(error) {
4
+ const errorPayload = error.response.data.error.details.errors;
5
+ const validationErrors = errorPayload.reduce((acc, err) => {
6
+ acc[err.path.join('.')] = {
7
+ id: getTrad(`apiError.${err.message}`),
8
+ defaultMessage: err.message,
9
+ };
10
+
11
+ return acc;
12
+ }, {});
13
+
14
+ return validationErrors;
15
+ }
@@ -1,4 +1,3 @@
1
1
  export { default as moveFields } from './moveFields';
2
2
  export { default as cleanData } from './cleanData';
3
- export { default as getYupInnerErrors } from './getYupInnerErrors';
4
3
  export { default as createYupSchema } from './schema';
@@ -7,12 +7,14 @@ import toNumber from 'lodash/toNumber';
7
7
  import * as yup from 'yup';
8
8
  import { translatedErrors as errorsTrads } from '@strapi/helper-plugin';
9
9
 
10
+ import isFieldTypeNumber from '../../../utils/isFieldTypeNumber';
11
+
10
12
  yup.addMethod(yup.mixed, 'defined', function() {
11
- return this.test('defined', errorsTrads.required, value => value !== undefined);
13
+ return this.test('defined', errorsTrads.required, (value) => value !== undefined);
12
14
  });
13
15
 
14
16
  yup.addMethod(yup.array, 'notEmptyMin', function(min) {
15
- return this.test('notEmptyMin', errorsTrads.min, value => {
17
+ return this.test('notEmptyMin', errorsTrads.min, (value) => {
16
18
  if (isEmpty(value)) {
17
19
  return true;
18
20
  }
@@ -49,7 +51,7 @@ yup.addMethod(yup.string, 'isSuperior', function(message, min) {
49
51
  });
50
52
  });
51
53
 
52
- const getAttributes = data => get(data, ['attributes'], {});
54
+ const getAttributes = (data) => get(data, ['attributes'], {});
53
55
 
54
56
  const createYupSchema = (
55
57
  model,
@@ -95,7 +97,7 @@ const createYupSchema = (
95
97
  if (attribute.repeatable === true) {
96
98
  const { min, max, required } = attribute;
97
99
 
98
- let componentSchema = yup.lazy(value => {
100
+ let componentSchema = yup.lazy((value) => {
99
101
  let baseSchema = yup.array().of(componentFieldSchema);
100
102
 
101
103
  if (min) {
@@ -121,7 +123,7 @@ const createYupSchema = (
121
123
 
122
124
  return acc;
123
125
  }
124
- const componentSchema = yup.lazy(obj => {
126
+ const componentSchema = yup.lazy((obj) => {
125
127
  if (obj !== undefined) {
126
128
  return attribute.required === true && !options.isDraft
127
129
  ? componentFieldSchema.defined()
@@ -152,7 +154,7 @@ const createYupSchema = (
152
154
  if (min) {
153
155
  if (attribute.required) {
154
156
  dynamicZoneSchema = dynamicZoneSchema
155
- .test('min', errorsTrads.min, value => {
157
+ .test('min', errorsTrads.min, (value) => {
156
158
  if (options.isCreatingEntry) {
157
159
  return value && value.length >= min;
158
160
  }
@@ -163,7 +165,7 @@ const createYupSchema = (
163
165
 
164
166
  return value !== null && value.length >= min;
165
167
  })
166
- .test('required', errorsTrads.required, value => {
168
+ .test('required', errorsTrads.required, (value) => {
167
169
  if (options.isCreatingEntry) {
168
170
  return value !== null || value !== undefined;
169
171
  }
@@ -178,7 +180,7 @@ const createYupSchema = (
178
180
  dynamicZoneSchema = dynamicZoneSchema.notEmptyMin(min);
179
181
  }
180
182
  } else if (attribute.required && !options.isDraft) {
181
- dynamicZoneSchema = dynamicZoneSchema.test('required', errorsTrads.required, value => {
183
+ dynamicZoneSchema = dynamicZoneSchema.test('required', errorsTrads.required, (value) => {
182
184
  if (options.isCreatingEntry) {
183
185
  return value !== null || value !== undefined;
184
186
  }
@@ -213,7 +215,7 @@ const createYupSchemaAttribute = (type, validations, options) => {
213
215
  if (type === 'json') {
214
216
  schema = yup
215
217
  .mixed(errorsTrads.json)
216
- .test('isJSON', errorsTrads.json, value => {
218
+ .test('isJSON', errorsTrads.json, (value) => {
217
219
  if (value === undefined) {
218
220
  return true;
219
221
  }
@@ -236,19 +238,19 @@ const createYupSchemaAttribute = (type, validations, options) => {
236
238
  if (['number', 'integer', 'float', 'decimal'].includes(type)) {
237
239
  schema = yup
238
240
  .number()
239
- .transform(cv => (isNaN(cv) ? undefined : cv))
241
+ .transform((cv) => (isNaN(cv) ? undefined : cv))
240
242
  .typeError();
241
243
  }
242
244
 
243
- if (['date', 'datetime'].includes(type)) {
244
- schema = yup.date();
245
- }
246
-
247
245
  if (type === 'biginteger') {
248
246
  schema = yup.string().matches(/^-?\d*$/);
249
247
  }
250
248
 
251
- Object.keys(validations).forEach(validation => {
249
+ if (['date', 'datetime'].includes(type)) {
250
+ schema = yup.date();
251
+ }
252
+
253
+ Object.keys(validations).forEach((validation) => {
252
254
  const validationValue = validations[validation];
253
255
 
254
256
  if (
@@ -267,13 +269,13 @@ const createYupSchemaAttribute = (type, validations, options) => {
267
269
  if (options.isCreatingEntry) {
268
270
  schema = schema.required(errorsTrads.required);
269
271
  } else {
270
- schema = schema.test('required', errorsTrads.required, value => {
272
+ schema = schema.test('required', errorsTrads.required, (value) => {
271
273
  // Field is not touched and the user is editing the entry
272
274
  if (value === undefined && !options.isFromComponent) {
273
275
  return true;
274
276
  }
275
277
 
276
- if (['number', 'integer', 'biginteger', 'float', 'decimal'].includes(type)) {
278
+ if (isFieldTypeNumber(type)) {
277
279
  if (value === 0) {
278
280
  return true;
279
281
  }
@@ -344,12 +346,12 @@ const createYupSchemaAttribute = (type, validations, options) => {
344
346
  }
345
347
  break;
346
348
  case 'positive':
347
- if (['number', 'integer', 'bigint', 'float', 'decimal'].includes(type)) {
349
+ if (isFieldTypeNumber(type)) {
348
350
  schema = schema.positive();
349
351
  }
350
352
  break;
351
353
  case 'negative':
352
- if (['number', 'integer', 'bigint', 'float', 'decimal'].includes(type)) {
354
+ if (isFieldTypeNumber(type)) {
353
355
  schema = schema.negative();
354
356
  }
355
357
  break;
@@ -82,7 +82,6 @@ const InputUID = ({
82
82
  onChange({ target: { name, value: data, type: 'text' } }, shouldSetInitialValue);
83
83
  setIsLoading(false);
84
84
  } catch (err) {
85
- console.error({ err });
86
85
  setIsLoading(false);
87
86
  }
88
87
  };
@@ -107,7 +106,6 @@ const InputUID = ({
107
106
 
108
107
  setIsLoading(false);
109
108
  } catch (err) {
110
- console.error({ err });
111
109
  setIsLoading(false);
112
110
  }
113
111
  };
@@ -184,12 +182,10 @@ const InputUID = ({
184
182
  onChange(e);
185
183
  };
186
184
 
187
- const formattedError = error ? formatMessage({ id: error, defaultMessage: error }) : undefined;
188
-
189
185
  return (
190
186
  <TextInput
191
187
  disabled={disabled}
192
- error={formattedError}
188
+ error={error}
193
189
  endAction={
194
190
  <EndActionWrapper>
195
191
  {availability && availability.isAvailable && !regenerateLabel && (
@@ -42,10 +42,7 @@ function Inputs({
42
42
 
43
43
  const disabled = useMemo(() => !get(metadatas, 'editable', true), [metadatas]);
44
44
  const type = fieldSchema.type;
45
-
46
- const errorId = useMemo(() => {
47
- return get(formErrors, [keys, 'id'], null);
48
- }, [formErrors, keys]);
45
+ const error = get(formErrors, [keys], null);
49
46
 
50
47
  const fieldName = useMemo(() => {
51
48
  return getFieldName(keys);
@@ -160,10 +157,10 @@ function Inputs({
160
157
  return disabled;
161
158
  }, [disabled, isCreatingEntry, isUserAllowedToEditField, isUserAllowedToReadField]);
162
159
 
163
- const options = useMemo(() => generateOptions(fieldSchema.enum || [], isRequired), [
164
- fieldSchema,
165
- isRequired,
166
- ]);
160
+ const options = useMemo(
161
+ () => generateOptions(fieldSchema.enum || [], isRequired),
162
+ [fieldSchema, isRequired]
163
+ );
167
164
 
168
165
  const { label, description, placeholder, visible } = metadatas;
169
166
 
@@ -177,7 +174,7 @@ function Inputs({
177
174
  description={description ? { id: description, defaultMessage: description } : null}
178
175
  intlLabel={{ id: label, defaultMessage: label }}
179
176
  labelAction={labelAction}
180
- error={errorId}
177
+ error={error && formatMessage(error)}
181
178
  name={keys}
182
179
  required={isRequired}
183
180
  />
@@ -215,6 +212,7 @@ function Inputs({
215
212
  }
216
213
  queryInfos={queryInfos}
217
214
  value={value}
215
+ error={error && formatMessage(error)}
218
216
  />
219
217
  );
220
218
  }
@@ -228,7 +226,7 @@ function Inputs({
228
226
  isNullable={inputType === 'bool' && [null, undefined].includes(fieldSchema.default)}
229
227
  description={description ? { id: description, defaultMessage: description } : null}
230
228
  disabled={shouldDisableField}
231
- error={errorId}
229
+ error={error}
232
230
  labelAction={labelAction}
233
231
  contentTypeUID={currentContentTypeLayout.uid}
234
232
  customInputs={{
@@ -207,9 +207,6 @@ RepeatableComponent.propTypes = {
207
207
 
208
208
  const Memoized = memo(RepeatableComponent);
209
209
 
210
- export default connect(
211
- Memoized,
212
- select
213
- );
210
+ export default connect(Memoized, select);
214
211
 
215
212
  export { RepeatableComponent };
@@ -144,8 +144,6 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
144
144
  const displayErrors = useCallback(
145
145
  err => {
146
146
  const errorPayload = err.response.payload;
147
- console.error(errorPayload);
148
-
149
147
  let errorMessage = get(errorPayload, ['message'], 'Bad Request');
150
148
 
151
149
  // TODO handle errors correctly when back-end ready
@@ -178,10 +176,12 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
178
176
  } catch (err) {
179
177
  trackUsageRef.current('didNotDeleteEntry', { error: err, ...trackerProperty });
180
178
 
179
+ displayErrors(err);
180
+
181
181
  return Promise.reject(err);
182
182
  }
183
183
  },
184
- [slug, toggleNotification, searchToSend]
184
+ [slug, displayErrors, toggleNotification, searchToSend]
185
185
  );
186
186
 
187
187
  const onDeleteSucceeded = useCallback(() => {
@@ -211,12 +211,16 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
211
211
  setIsCreatingEntry(false);
212
212
 
213
213
  dispatch(setStatus('resolved'));
214
+
215
+ return Promise.resolve(data);
214
216
  } catch (err) {
215
217
  trackUsageRef.current('didNotCreateEntry', { error: err, trackerProperty });
216
218
 
217
219
  displayErrors(err);
218
220
 
219
221
  dispatch(setStatus('resolved'));
222
+
223
+ return Promise.reject(err);
220
224
  }
221
225
  },
222
226
  [cleanReceivedData, displayErrors, slug, dispatch, rawQuery, toggleNotification, setCurrentStep]
@@ -239,10 +243,14 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
239
243
  dispatch(submitSucceeded(cleanReceivedData(data)));
240
244
 
241
245
  dispatch(setStatus('resolved'));
246
+
247
+ return Promise.resolve(data);
242
248
  } catch (err) {
243
249
  displayErrors(err);
244
250
 
245
251
  dispatch(setStatus('resolved'));
252
+
253
+ return Promise.reject(err);
246
254
  }
247
255
  }, [cleanReceivedData, displayErrors, slug, searchToSend, dispatch, toggleNotification]);
248
256
 
@@ -267,12 +275,16 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
267
275
  dispatch(submitSucceeded(cleanReceivedData(data)));
268
276
 
269
277
  dispatch(setStatus('resolved'));
278
+
279
+ return Promise.resolve(data);
270
280
  } catch (err) {
271
281
  displayErrors(err);
272
282
 
273
283
  trackUsageRef.current('didNotEditEntry', { error: err, trackerProperty });
274
284
 
275
285
  dispatch(setStatus('resolved'));
286
+
287
+ return Promise.reject(err);
276
288
  }
277
289
  },
278
290
  [cleanReceivedData, displayErrors, slug, dispatch, rawQuery, toggleNotification]
@@ -118,7 +118,6 @@ const Wysiwyg = ({
118
118
  )
119
119
  : '';
120
120
 
121
- const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : '';
122
121
  const label = intlLabel.id
123
122
  ? formatMessage(
124
123
  { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
@@ -157,7 +156,7 @@ const Wysiwyg = ({
157
156
  disabled={disabled}
158
157
  isExpandMode={isExpandMode}
159
158
  editorRef={editorRef}
160
- error={errorMessage}
159
+ error={error}
161
160
  isPreviewMode={isPreviewMode}
162
161
  name={name}
163
162
  onChange={onChange}
@@ -171,10 +170,10 @@ const Wysiwyg = ({
171
170
  <Hint description={description} name={name} error={error} />
172
171
  </Stack>
173
172
 
174
- {errorMessage && (
173
+ {error && (
175
174
  <Box paddingTop={1}>
176
175
  <Typography variant="pi" textColor="danger600" data-strapi-field-error>
177
- {errorMessage}
176
+ {error}
178
177
  </Typography>
179
178
  </Box>
180
179
  )}
@@ -11,7 +11,12 @@ import { makeSelectModelAndComponentSchemas } from '../../App/selectors';
11
11
  import getTrad from '../../../utils/getTrad';
12
12
  import GenericInput from './GenericInput';
13
13
 
14
- const FIELD_SIZES = [[4, '33%'], [6, '50%'], [8, '66%'], [12, '100%']];
14
+ const FIELD_SIZES = [
15
+ [4, '33%'],
16
+ [6, '50%'],
17
+ [8, '66%'],
18
+ [12, '100%'],
19
+ ];
15
20
 
16
21
  const NON_RESIZABLE_FIELD_TYPES = ['dynamiczone', 'component', 'json', 'richtext'];
17
22
 
@@ -28,7 +28,13 @@ const formatLayout = arr => {
28
28
 
29
29
  return acc2;
30
30
  }, []);
31
- const rowId = acc.length === 0 ? 0 : Math.max.apply(Math, acc.map(o => o.rowId)) + 1;
31
+ const rowId =
32
+ acc.length === 0
33
+ ? 0
34
+ : Math.max.apply(
35
+ Math,
36
+ acc.map(o => o.rowId)
37
+ ) + 1;
32
38
 
33
39
  const currentRowSize = getRowSize(currentRow);
34
40