@contentful/field-editor-validation-errors 2.0.7-alpha.0 → 2.0.7-canary.59

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.
@@ -61,67 +61,75 @@ function _interop_require_wildcard(obj, nodeInterop) {
61
61
  }
62
62
  return newObj;
63
63
  }
64
- function UniquenessError(props) {
64
+ function UniquenessError({ error, cma, localeCode, defaultLocaleCode, getEntryURL }) {
65
65
  const [state, setState] = _react.useState({
66
66
  loading: true,
67
67
  entries: []
68
68
  });
69
- const contentTypesById = _react.useMemo(()=>props.space.getCachedContentTypes().reduce((prev, ct)=>({
69
+ const { contentTypes: allContentTypes } = (0, _fieldeditorshared.useContentTypes)(cma);
70
+ const contentTypesById = _react.useMemo(()=>allContentTypes.reduce((prev, ct)=>({
70
71
  ...prev,
71
72
  [ct.sys.id]: ct
72
73
  }), {}), [
73
- props.space
74
+ allContentTypes
74
75
  ]);
75
- const getTitle = _react.useCallback((entry)=>_fieldeditorshared.entityHelpers.getEntryTitle({
76
- entry,
77
- defaultTitle: _core.i18n._({
78
- id: "FieldEditors.ValidationErrors.UniquenessError.DefaultTitle",
79
- message: "Untitled"
80
- }),
81
- localeCode: props.localeCode,
82
- defaultLocaleCode: props.defaultLocaleCode,
83
- contentType: contentTypesById[entry.sys.contentType.sys.id]
84
- }), [
85
- props.localeCode,
86
- props.defaultLocaleCode,
87
- contentTypesById
76
+ const conflictKey = _react.useMemo(()=>{
77
+ const conflicting = 'conflicting' in error ? error.conflicting : [];
78
+ return conflicting.map((entry)=>entry.sys.id).sort().join(',');
79
+ }, [
80
+ error
88
81
  ]);
89
- let conflicting = [];
90
- if ('conflicting' in props.error) {
91
- conflicting = props.error.conflicting;
92
- }
93
82
  _react.useEffect(()=>{
94
- const entryIds = state.entries.map((entry)=>entry.id);
95
- const conflictIds = conflicting.map((entry)=>entry.sys.id);
96
- if (conflictIds.every((id)=>entryIds.includes(id))) {
83
+ if (!conflictKey) {
84
+ setState({
85
+ loading: false,
86
+ entries: []
87
+ });
97
88
  return;
98
89
  }
99
- setState((state)=>({
100
- ...state,
101
- loading: true
102
- }));
103
- props.cma.entry.getMany({
90
+ setState({
91
+ loading: true,
92
+ entries: []
93
+ });
94
+ const conflicting = 'conflicting' in error ? error.conflicting : [];
95
+ const conflictIds = conflicting.map((entry)=>entry.sys.id);
96
+ cma.entry.getMany({
104
97
  query: {
105
98
  'sys.id[in]': conflictIds.join(',')
106
99
  },
107
100
  releaseId: undefined
108
101
  }).then(({ items })=>{
109
- const entries = items.map((entry)=>({
110
- id: entry.sys.id,
111
- title: getTitle(entry),
112
- href: props.getEntryURL(entry)
113
- }));
114
102
  setState({
115
103
  loading: false,
116
- entries
104
+ entries: items
117
105
  });
118
106
  });
119
107
  }, [
120
- getTitle,
108
+ conflictKey,
109
+ error,
110
+ cma
111
+ ]);
112
+ const displayEntries = _react.useMemo(()=>{
113
+ return state.entries.map((entry)=>({
114
+ id: entry.sys.id,
115
+ title: _fieldeditorshared.entityHelpers.getEntryTitle({
116
+ entry,
117
+ defaultTitle: _core.i18n._({
118
+ id: "FieldEditors.ValidationErrors.UniquenessError.DefaultTitle",
119
+ message: "Untitled"
120
+ }),
121
+ localeCode,
122
+ defaultLocaleCode,
123
+ contentType: contentTypesById[entry.sys.contentType.sys.id]
124
+ }),
125
+ href: getEntryURL(entry)
126
+ }));
127
+ }, [
121
128
  state.entries,
122
- conflicting,
123
- props.cma,
124
- props.getEntryURL
129
+ contentTypesById,
130
+ localeCode,
131
+ defaultLocaleCode,
132
+ getEntryURL
125
133
  ]);
126
134
  return /*#__PURE__*/ _react.createElement(_f36components.List, {
127
135
  className: _styles.errorList,
@@ -131,7 +139,7 @@ function UniquenessError(props) {
131
139
  }, state.loading ? /*#__PURE__*/ _react.createElement("div", null, _core.i18n._({
132
140
  id: "FieldEditors.ValidationErrors.UniquenessError.LoadingMessage",
133
141
  message: "Loading title for conflicting entry…"
134
- })) : state.entries.map((entry)=>/*#__PURE__*/ _react.createElement(_f36components.TextLink, {
142
+ })) : displayEntries.map((entry)=>/*#__PURE__*/ _react.createElement(_f36components.TextLink, {
135
143
  key: entry.id,
136
144
  href: entry.href,
137
145
  icon: /*#__PURE__*/ _react.createElement(_f36icons.ArrowSquareOutIcon, null),
@@ -141,7 +149,7 @@ function UniquenessError(props) {
141
149
  rel: "noopener noreferrer"
142
150
  }, entry.title))));
143
151
  }
144
- function ValidationErrors({ field, space, cma, locales, errorMessageOverride, getEntryURL }) {
152
+ function ValidationErrorsInternal({ field, cma, locales, errorMessageOverride, getEntryURL }) {
145
153
  const [errors, setErrors] = _react.useState([]);
146
154
  _react.useEffect(()=>{
147
155
  const onErrors = (errors)=>{
@@ -171,10 +179,12 @@ function ValidationErrors({ field, space, cma, locales, errorMessageOverride, ge
171
179
  }, errorMessageOverride?.(error.message) ?? error.message, error.name === 'unique' && /*#__PURE__*/ _react.createElement(UniquenessError, {
172
180
  cma: cma,
173
181
  error: error,
174
- space: space,
175
182
  localeCode: field.locale,
176
183
  defaultLocaleCode: locales.default,
177
184
  getEntryURL: getEntryURL
178
185
  })));
179
186
  }));
180
187
  }
188
+ function ValidationErrors(props) {
189
+ return /*#__PURE__*/ _react.createElement(_fieldeditorshared.SharedQueryClientProvider, null, /*#__PURE__*/ _react.createElement(ValidationErrorsInternal, props));
190
+ }
@@ -53,19 +53,6 @@ function _interop_require_wildcard(obj, nodeInterop) {
53
53
  });
54
54
  const displayField = 'my-title';
55
55
  const contentTypeId = 'my-content-type';
56
- const getCachedContentTypes = ()=>[
57
- {
58
- displayField,
59
- fields: [
60
- {
61
- id: displayField
62
- }
63
- ],
64
- sys: {
65
- id: 'my-content-type'
66
- }
67
- }
68
- ];
69
56
  const createEntry = (id)=>({
70
57
  fields: {
71
58
  [displayField]: {
@@ -86,6 +73,26 @@ const cma = {
86
73
  getMany: jest.fn().mockReturnValue({
87
74
  items: []
88
75
  })
76
+ },
77
+ contentType: {
78
+ getMany: jest.fn().mockResolvedValue({
79
+ items: [
80
+ {
81
+ sys: {
82
+ id: contentTypeId
83
+ },
84
+ name: 'My Content Type',
85
+ displayField,
86
+ fields: [
87
+ {
88
+ id: displayField,
89
+ name: 'Title',
90
+ type: 'Symbol'
91
+ }
92
+ ]
93
+ }
94
+ ]
95
+ })
89
96
  }
90
97
  };
91
98
  describe('ValidationErrors', ()=>{
@@ -95,7 +102,6 @@ describe('ValidationErrors', ()=>{
95
102
  const { container } = (0, _react1.render)(/*#__PURE__*/ _react.createElement(_ValidationErrors.ValidationErrors, {
96
103
  field: field,
97
104
  cma: cma,
98
- space: _fieldeditortestutils.createFakeSpaceAPI(),
99
105
  locales: _fieldeditortestutils.createFakeLocalesAPI(),
100
106
  getEntryURL: (entry)=>`url.${entry.sys.id}`
101
107
  }));
@@ -113,7 +119,6 @@ describe('ValidationErrors', ()=>{
113
119
  const { findByText } = (0, _react1.render)(/*#__PURE__*/ _react.createElement(_ValidationErrors.ValidationErrors, {
114
120
  field: field,
115
121
  cma: cma,
116
- space: _fieldeditortestutils.createFakeSpaceAPI(),
117
122
  locales: _fieldeditortestutils.createFakeLocalesAPI(),
118
123
  getEntryURL: (entry)=>`url.${entry.sys.id}`
119
124
  }));
@@ -149,17 +154,12 @@ describe('ValidationErrors', ()=>{
149
154
  }
150
155
  ];
151
156
  const [field, emitter] = _fieldeditortestutils.createFakeFieldAPI();
152
- const space = _fieldeditortestutils.createFakeSpaceAPI((api)=>({
153
- ...api,
154
- getCachedContentTypes
155
- }));
156
157
  cma.entry.getMany.mockResolvedValue({
157
158
  items: ids.map(createEntry)
158
159
  });
159
160
  const { findByText, findAllByTestId } = (0, _react1.render)(/*#__PURE__*/ _react.createElement(_ValidationErrors.ValidationErrors, {
160
161
  field: field,
161
162
  cma: cma,
162
- space: space,
163
163
  locales: _fieldeditortestutils.createFakeLocalesAPI(),
164
164
  getEntryURL: (entry)=>`url.${entry.sys.id}`
165
165
  }));
@@ -2,70 +2,78 @@ import * as React from 'react';
2
2
  import { List, ListItem, TextLink } from '@contentful/f36-components';
3
3
  import { ArrowSquareOutIcon, InfoIcon } from '@contentful/f36-icons';
4
4
  import tokens from '@contentful/f36-tokens';
5
- import { entityHelpers } from '@contentful/field-editor-shared';
5
+ import { entityHelpers, useContentTypes, SharedQueryClientProvider } from '@contentful/field-editor-shared';
6
6
  import { i18n as $_i18n } from "@lingui/core";
7
7
  import * as styles from './styles';
8
- function UniquenessError(props) {
8
+ function UniquenessError({ error, cma, localeCode, defaultLocaleCode, getEntryURL }) {
9
9
  const [state, setState] = React.useState({
10
10
  loading: true,
11
11
  entries: []
12
12
  });
13
- const contentTypesById = React.useMemo(()=>props.space.getCachedContentTypes().reduce((prev, ct)=>({
13
+ const { contentTypes: allContentTypes } = useContentTypes(cma);
14
+ const contentTypesById = React.useMemo(()=>allContentTypes.reduce((prev, ct)=>({
14
15
  ...prev,
15
16
  [ct.sys.id]: ct
16
17
  }), {}), [
17
- props.space
18
+ allContentTypes
18
19
  ]);
19
- const getTitle = React.useCallback((entry)=>entityHelpers.getEntryTitle({
20
- entry,
21
- defaultTitle: $_i18n._({
22
- id: "FieldEditors.ValidationErrors.UniquenessError.DefaultTitle",
23
- message: "Untitled"
24
- }),
25
- localeCode: props.localeCode,
26
- defaultLocaleCode: props.defaultLocaleCode,
27
- contentType: contentTypesById[entry.sys.contentType.sys.id]
28
- }), [
29
- props.localeCode,
30
- props.defaultLocaleCode,
31
- contentTypesById
20
+ const conflictKey = React.useMemo(()=>{
21
+ const conflicting = 'conflicting' in error ? error.conflicting : [];
22
+ return conflicting.map((entry)=>entry.sys.id).sort().join(',');
23
+ }, [
24
+ error
32
25
  ]);
33
- let conflicting = [];
34
- if ('conflicting' in props.error) {
35
- conflicting = props.error.conflicting;
36
- }
37
26
  React.useEffect(()=>{
38
- const entryIds = state.entries.map((entry)=>entry.id);
39
- const conflictIds = conflicting.map((entry)=>entry.sys.id);
40
- if (conflictIds.every((id)=>entryIds.includes(id))) {
27
+ if (!conflictKey) {
28
+ setState({
29
+ loading: false,
30
+ entries: []
31
+ });
41
32
  return;
42
33
  }
43
- setState((state)=>({
44
- ...state,
45
- loading: true
46
- }));
47
- props.cma.entry.getMany({
34
+ setState({
35
+ loading: true,
36
+ entries: []
37
+ });
38
+ const conflicting = 'conflicting' in error ? error.conflicting : [];
39
+ const conflictIds = conflicting.map((entry)=>entry.sys.id);
40
+ cma.entry.getMany({
48
41
  query: {
49
42
  'sys.id[in]': conflictIds.join(',')
50
43
  },
51
44
  releaseId: undefined
52
45
  }).then(({ items })=>{
53
- const entries = items.map((entry)=>({
54
- id: entry.sys.id,
55
- title: getTitle(entry),
56
- href: props.getEntryURL(entry)
57
- }));
58
46
  setState({
59
47
  loading: false,
60
- entries
48
+ entries: items
61
49
  });
62
50
  });
63
51
  }, [
64
- getTitle,
52
+ conflictKey,
53
+ error,
54
+ cma
55
+ ]);
56
+ const displayEntries = React.useMemo(()=>{
57
+ return state.entries.map((entry)=>({
58
+ id: entry.sys.id,
59
+ title: entityHelpers.getEntryTitle({
60
+ entry,
61
+ defaultTitle: $_i18n._({
62
+ id: "FieldEditors.ValidationErrors.UniquenessError.DefaultTitle",
63
+ message: "Untitled"
64
+ }),
65
+ localeCode,
66
+ defaultLocaleCode,
67
+ contentType: contentTypesById[entry.sys.contentType.sys.id]
68
+ }),
69
+ href: getEntryURL(entry)
70
+ }));
71
+ }, [
65
72
  state.entries,
66
- conflicting,
67
- props.cma,
68
- props.getEntryURL
73
+ contentTypesById,
74
+ localeCode,
75
+ defaultLocaleCode,
76
+ getEntryURL
69
77
  ]);
70
78
  return /*#__PURE__*/ React.createElement(List, {
71
79
  className: styles.errorList,
@@ -75,7 +83,7 @@ function UniquenessError(props) {
75
83
  }, state.loading ? /*#__PURE__*/ React.createElement("div", null, $_i18n._({
76
84
  id: "FieldEditors.ValidationErrors.UniquenessError.LoadingMessage",
77
85
  message: "Loading title for conflicting entry…"
78
- })) : state.entries.map((entry)=>/*#__PURE__*/ React.createElement(TextLink, {
86
+ })) : displayEntries.map((entry)=>/*#__PURE__*/ React.createElement(TextLink, {
79
87
  key: entry.id,
80
88
  href: entry.href,
81
89
  icon: /*#__PURE__*/ React.createElement(ArrowSquareOutIcon, null),
@@ -85,7 +93,7 @@ function UniquenessError(props) {
85
93
  rel: "noopener noreferrer"
86
94
  }, entry.title))));
87
95
  }
88
- export function ValidationErrors({ field, space, cma, locales, errorMessageOverride, getEntryURL }) {
96
+ function ValidationErrorsInternal({ field, cma, locales, errorMessageOverride, getEntryURL }) {
89
97
  const [errors, setErrors] = React.useState([]);
90
98
  React.useEffect(()=>{
91
99
  const onErrors = (errors)=>{
@@ -115,10 +123,12 @@ export function ValidationErrors({ field, space, cma, locales, errorMessageOverr
115
123
  }, errorMessageOverride?.(error.message) ?? error.message, error.name === 'unique' && /*#__PURE__*/ React.createElement(UniquenessError, {
116
124
  cma: cma,
117
125
  error: error,
118
- space: space,
119
126
  localeCode: field.locale,
120
127
  defaultLocaleCode: locales.default,
121
128
  getEntryURL: getEntryURL
122
129
  })));
123
130
  }));
124
131
  }
132
+ export function ValidationErrors(props) {
133
+ return /*#__PURE__*/ React.createElement(SharedQueryClientProvider, null, /*#__PURE__*/ React.createElement(ValidationErrorsInternal, props));
134
+ }
@@ -8,19 +8,6 @@ configure({
8
8
  });
9
9
  const displayField = 'my-title';
10
10
  const contentTypeId = 'my-content-type';
11
- const getCachedContentTypes = ()=>[
12
- {
13
- displayField,
14
- fields: [
15
- {
16
- id: displayField
17
- }
18
- ],
19
- sys: {
20
- id: 'my-content-type'
21
- }
22
- }
23
- ];
24
11
  const createEntry = (id)=>({
25
12
  fields: {
26
13
  [displayField]: {
@@ -41,6 +28,26 @@ const cma = {
41
28
  getMany: jest.fn().mockReturnValue({
42
29
  items: []
43
30
  })
31
+ },
32
+ contentType: {
33
+ getMany: jest.fn().mockResolvedValue({
34
+ items: [
35
+ {
36
+ sys: {
37
+ id: contentTypeId
38
+ },
39
+ name: 'My Content Type',
40
+ displayField,
41
+ fields: [
42
+ {
43
+ id: displayField,
44
+ name: 'Title',
45
+ type: 'Symbol'
46
+ }
47
+ ]
48
+ }
49
+ ]
50
+ })
44
51
  }
45
52
  };
46
53
  describe('ValidationErrors', ()=>{
@@ -50,7 +57,6 @@ describe('ValidationErrors', ()=>{
50
57
  const { container } = render(/*#__PURE__*/ React.createElement(ValidationErrors, {
51
58
  field: field,
52
59
  cma: cma,
53
- space: utils.createFakeSpaceAPI(),
54
60
  locales: utils.createFakeLocalesAPI(),
55
61
  getEntryURL: (entry)=>`url.${entry.sys.id}`
56
62
  }));
@@ -68,7 +74,6 @@ describe('ValidationErrors', ()=>{
68
74
  const { findByText } = render(/*#__PURE__*/ React.createElement(ValidationErrors, {
69
75
  field: field,
70
76
  cma: cma,
71
- space: utils.createFakeSpaceAPI(),
72
77
  locales: utils.createFakeLocalesAPI(),
73
78
  getEntryURL: (entry)=>`url.${entry.sys.id}`
74
79
  }));
@@ -104,17 +109,12 @@ describe('ValidationErrors', ()=>{
104
109
  }
105
110
  ];
106
111
  const [field, emitter] = utils.createFakeFieldAPI();
107
- const space = utils.createFakeSpaceAPI((api)=>({
108
- ...api,
109
- getCachedContentTypes
110
- }));
111
112
  cma.entry.getMany.mockResolvedValue({
112
113
  items: ids.map(createEntry)
113
114
  });
114
115
  const { findByText, findAllByTestId } = render(/*#__PURE__*/ React.createElement(ValidationErrors, {
115
116
  field: field,
116
117
  cma: cma,
117
- space: space,
118
118
  locales: utils.createFakeLocalesAPI(),
119
119
  getEntryURL: (entry)=>`url.${entry.sys.id}`
120
120
  }));
@@ -1,12 +1,11 @@
1
1
  import * as React from 'react';
2
- import type { Entry, FieldAPI, LocalesAPI, SpaceAPI } from '@contentful/field-editor-shared';
2
+ import type { Entry, FieldAPI, LocalesAPI } from '@contentful/field-editor-shared';
3
3
  import type { PlainClientAPI } from 'contentful-management';
4
4
  export interface ValidationErrorsProps {
5
5
  field: FieldAPI;
6
- space: SpaceAPI;
7
6
  cma: PlainClientAPI;
8
7
  locales: LocalesAPI;
9
8
  errorMessageOverride?: (message: string | undefined) => React.ReactNode;
10
9
  getEntryURL: (entry: Entry) => string;
11
10
  }
12
- export declare function ValidationErrors({ field, space, cma, locales, errorMessageOverride, getEntryURL, }: ValidationErrorsProps): React.JSX.Element | null;
11
+ export declare function ValidationErrors(props: ValidationErrorsProps): React.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/field-editor-validation-errors",
3
- "version": "2.0.7-alpha.0",
3
+ "version": "2.0.7-canary.59+54b401aa",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "@contentful/f36-components": "^5.4.1",
40
40
  "@contentful/f36-icons": "^5.4.1",
41
41
  "@contentful/f36-tokens": "^5.1.0",
42
- "@contentful/field-editor-shared": "^2.17.1-alpha.0",
42
+ "@contentful/field-editor-shared": "^2.17.1-canary.59+54b401aa",
43
43
  "emotion": "^10.0.17"
44
44
  },
45
45
  "devDependencies": {
@@ -53,5 +53,5 @@
53
53
  "publishConfig": {
54
54
  "registry": "https://npm.pkg.github.com/"
55
55
  },
56
- "gitHead": "447875c5a2ef25eb4552c29b990d90ec40bc6985"
56
+ "gitHead": "54b401aa9908c8380c3801bf25fa38e23dff72d2"
57
57
  }