@plone/volto 18.2.3 → 18.3.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.
- package/CHANGELOG.md +13 -0
- package/locales/ca/LC_MESSAGES/volto.po +47 -11
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +47 -11
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +47 -11
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +47 -11
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +47 -11
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +47 -11
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +47 -11
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +47 -11
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +71 -35
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +47 -11
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +47 -11
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +47 -11
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +47 -11
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +47 -11
- package/locales/ro.json +1 -1
- package/locales/volto.pot +48 -12
- package/locales/zh_CN/LC_MESSAGES/volto.po +47 -11
- package/locales/zh_CN.json +1 -1
- package/package.json +4 -4
- package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +4 -1
- package/src/components/manage/Contents/Contents.jsx +6 -354
- package/src/components/manage/Contents/ContentsDeleteModal.jsx +380 -0
- package/src/components/manage/Rules/Rules.jsx +7 -1
- package/src/components/theme/SlotRenderer/SlotRenderer.tsx +1 -1
- package/src/helpers/ScrollToTop/ScrollToTop.jsx +1 -0
- package/src/reducers/index.js +2 -0
- package/src/reducers/linkIntegrity/linkIntegrity.js +51 -0
- package/src/reducers/linkIntegrity/linkIntegrity.test.js +54 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
4
|
+
import { Link } from 'react-router-dom';
|
|
5
|
+
import map from 'lodash/map';
|
|
6
|
+
import find from 'lodash/find';
|
|
7
|
+
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
|
8
|
+
import { linkIntegrityCheck } from '@plone/volto/actions/content/content';
|
|
9
|
+
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
10
|
+
|
|
11
|
+
import { Confirm, Dimmer, Loader, Table } from 'semantic-ui-react';
|
|
12
|
+
|
|
13
|
+
const messages = defineMessages({
|
|
14
|
+
deleteConfirmSingleItem: {
|
|
15
|
+
id: 'Delete this item?',
|
|
16
|
+
defaultMessage: 'Delete this item?',
|
|
17
|
+
},
|
|
18
|
+
deleteConfirmMultipleItems: {
|
|
19
|
+
id: 'Delete selected items?',
|
|
20
|
+
defaultMessage: 'Delete selected items?',
|
|
21
|
+
},
|
|
22
|
+
navigate_to_this_item: {
|
|
23
|
+
id: 'Navigate to this item',
|
|
24
|
+
defaultMessage: 'Navigate to this item',
|
|
25
|
+
},
|
|
26
|
+
loading: {
|
|
27
|
+
id: 'link-integrity: loading references',
|
|
28
|
+
defaultMessage: 'Checking references...',
|
|
29
|
+
},
|
|
30
|
+
delete: {
|
|
31
|
+
id: 'link-integrity: Delete',
|
|
32
|
+
defaultMessage: 'Delete',
|
|
33
|
+
},
|
|
34
|
+
delete_and_broken_links: {
|
|
35
|
+
id: 'link-integrity: Delete item and break links',
|
|
36
|
+
defaultMessage: 'Delete item and break links',
|
|
37
|
+
},
|
|
38
|
+
cancel: {
|
|
39
|
+
id: 'Cancel',
|
|
40
|
+
defaultMessage: 'Cancel',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const ContentsDeleteModal = (props) => {
|
|
45
|
+
const { itemsToDelete = [], open, onCancel, onOk, items } = props;
|
|
46
|
+
const intl = useIntl();
|
|
47
|
+
const dispatch = useDispatch();
|
|
48
|
+
const linkintegrityInfo = useSelector((state) => state.linkIntegrity?.result);
|
|
49
|
+
const loading = useSelector((state) => state.linkIntegrity?.loading);
|
|
50
|
+
|
|
51
|
+
const [brokenReferences, setBrokenReferences] = useState(0);
|
|
52
|
+
const [containedItemsToDelete, setContainedItemsToDelete] = useState([]);
|
|
53
|
+
const [breaches, setBreaches] = useState([]);
|
|
54
|
+
|
|
55
|
+
const [linksAndReferencesViewLink, setLinkAndReferencesViewLink] =
|
|
56
|
+
useState(null);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const getFieldById = (id, field) => {
|
|
60
|
+
const item = find(items, { '@id': id });
|
|
61
|
+
return item ? item[field] : '';
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (itemsToDelete.length > 0 && open) {
|
|
65
|
+
dispatch(
|
|
66
|
+
linkIntegrityCheck(
|
|
67
|
+
map(itemsToDelete, (item) => getFieldById(item, 'UID')),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}, [itemsToDelete, items, open, dispatch]);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (linkintegrityInfo) {
|
|
75
|
+
const containedItems = linkintegrityInfo
|
|
76
|
+
.map((result) => result.items_total ?? 0)
|
|
77
|
+
.reduce((acc, value) => acc + value, 0);
|
|
78
|
+
const breaches = linkintegrityInfo.flatMap((result) =>
|
|
79
|
+
result.breaches.map((source) => ({
|
|
80
|
+
source: source,
|
|
81
|
+
target: result,
|
|
82
|
+
})),
|
|
83
|
+
);
|
|
84
|
+
const source_by_uid = breaches.reduce(
|
|
85
|
+
(acc, value) => acc.set(value.source.uid, value.source),
|
|
86
|
+
new Map(),
|
|
87
|
+
);
|
|
88
|
+
const by_source = breaches.reduce((acc, value) => {
|
|
89
|
+
if (acc.get(value.source.uid) === undefined) {
|
|
90
|
+
acc.set(value.source.uid, new Set());
|
|
91
|
+
}
|
|
92
|
+
acc.get(value.source.uid).add(value.target);
|
|
93
|
+
return acc;
|
|
94
|
+
}, new Map());
|
|
95
|
+
|
|
96
|
+
setContainedItemsToDelete(containedItems);
|
|
97
|
+
setBrokenReferences(by_source.size);
|
|
98
|
+
setLinkAndReferencesViewLink(
|
|
99
|
+
linkintegrityInfo.length
|
|
100
|
+
? linkintegrityInfo[0]['@id'] + '/links-to-item'
|
|
101
|
+
: null,
|
|
102
|
+
);
|
|
103
|
+
setBreaches(
|
|
104
|
+
Array.from(by_source, (entry) => ({
|
|
105
|
+
source: source_by_uid.get(entry[0]),
|
|
106
|
+
targets: Array.from(entry[1]),
|
|
107
|
+
})),
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
setContainedItemsToDelete([]);
|
|
111
|
+
setBrokenReferences(0);
|
|
112
|
+
setLinkAndReferencesViewLink(null);
|
|
113
|
+
setBreaches([]);
|
|
114
|
+
}
|
|
115
|
+
}, [linkintegrityInfo]);
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
open && (
|
|
119
|
+
<Confirm
|
|
120
|
+
open={open}
|
|
121
|
+
confirmButton={
|
|
122
|
+
brokenReferences === 0
|
|
123
|
+
? intl.formatMessage(messages.delete)
|
|
124
|
+
: intl.formatMessage(messages.delete_and_broken_links)
|
|
125
|
+
}
|
|
126
|
+
cancelButton={intl.formatMessage(messages.cancel)}
|
|
127
|
+
header={
|
|
128
|
+
itemsToDelete.length === 1
|
|
129
|
+
? intl.formatMessage(messages.deleteConfirmSingleItem)
|
|
130
|
+
: intl.formatMessage(messages.deleteConfirmMultipleItems)
|
|
131
|
+
}
|
|
132
|
+
content={
|
|
133
|
+
<div className="content">
|
|
134
|
+
<Dimmer active={loading} inverted>
|
|
135
|
+
<Loader indeterminate size="massive">
|
|
136
|
+
{intl.formatMessage(messages.loading)}
|
|
137
|
+
</Loader>
|
|
138
|
+
</Dimmer>
|
|
139
|
+
|
|
140
|
+
{itemsToDelete.length > 1 ? (
|
|
141
|
+
containedItemsToDelete > 0 ? (
|
|
142
|
+
<>
|
|
143
|
+
<FormattedMessage
|
|
144
|
+
id="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
|
|
145
|
+
defaultMessage="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
|
|
146
|
+
values={{
|
|
147
|
+
containedItemsToDelete: (
|
|
148
|
+
<span>{containedItemsToDelete}</span>
|
|
149
|
+
),
|
|
150
|
+
variation: (
|
|
151
|
+
<span>
|
|
152
|
+
{containedItemsToDelete === 1 ? (
|
|
153
|
+
<FormattedMessage id="item" defaultMessage="item" />
|
|
154
|
+
) : (
|
|
155
|
+
<FormattedMessage
|
|
156
|
+
id="items"
|
|
157
|
+
defaultMessage="items"
|
|
158
|
+
/>
|
|
159
|
+
)}
|
|
160
|
+
</span>
|
|
161
|
+
),
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
{brokenReferences > 0 && (
|
|
165
|
+
<>
|
|
166
|
+
<br />
|
|
167
|
+
<FormattedMessage
|
|
168
|
+
id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
169
|
+
defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
170
|
+
values={{
|
|
171
|
+
brokenReferences: <span>{brokenReferences}</span>,
|
|
172
|
+
variation: (
|
|
173
|
+
<span>
|
|
174
|
+
{brokenReferences === 1 ? (
|
|
175
|
+
<FormattedMessage
|
|
176
|
+
id="reference"
|
|
177
|
+
defaultMessage="reference"
|
|
178
|
+
/>
|
|
179
|
+
) : (
|
|
180
|
+
<FormattedMessage
|
|
181
|
+
id="references"
|
|
182
|
+
defaultMessage="references"
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
</span>
|
|
186
|
+
),
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
</>
|
|
190
|
+
)}
|
|
191
|
+
</>
|
|
192
|
+
) : (
|
|
193
|
+
<>
|
|
194
|
+
{brokenReferences > 0 && (
|
|
195
|
+
<>
|
|
196
|
+
<FormattedMessage
|
|
197
|
+
id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
198
|
+
defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
199
|
+
values={{
|
|
200
|
+
brokenReferences: <span>{brokenReferences}</span>,
|
|
201
|
+
variation: (
|
|
202
|
+
<span>
|
|
203
|
+
{brokenReferences === 1 ? (
|
|
204
|
+
<FormattedMessage
|
|
205
|
+
id="reference"
|
|
206
|
+
defaultMessage="reference"
|
|
207
|
+
/>
|
|
208
|
+
) : (
|
|
209
|
+
<FormattedMessage
|
|
210
|
+
id="references"
|
|
211
|
+
defaultMessage="references"
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
214
|
+
</span>
|
|
215
|
+
),
|
|
216
|
+
}}
|
|
217
|
+
/>
|
|
218
|
+
</>
|
|
219
|
+
)}
|
|
220
|
+
</>
|
|
221
|
+
)
|
|
222
|
+
) : containedItemsToDelete > 0 ? (
|
|
223
|
+
<>
|
|
224
|
+
<FormattedMessage
|
|
225
|
+
id="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
|
|
226
|
+
defaultMessage="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
|
|
227
|
+
values={{
|
|
228
|
+
containedItemsToDelete: (
|
|
229
|
+
<span>{containedItemsToDelete}</span>
|
|
230
|
+
),
|
|
231
|
+
variation: (
|
|
232
|
+
<span>
|
|
233
|
+
{containedItemsToDelete === 1 ? (
|
|
234
|
+
<FormattedMessage id="item" defaultMessage="item" />
|
|
235
|
+
) : (
|
|
236
|
+
<FormattedMessage id="items" defaultMessage="items" />
|
|
237
|
+
)}
|
|
238
|
+
</span>
|
|
239
|
+
),
|
|
240
|
+
}}
|
|
241
|
+
/>
|
|
242
|
+
{brokenReferences > 0 && (
|
|
243
|
+
<>
|
|
244
|
+
<br />
|
|
245
|
+
<FormattedMessage
|
|
246
|
+
id="Deleting this item breaks {brokenReferences} {variation}."
|
|
247
|
+
defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
|
|
248
|
+
values={{
|
|
249
|
+
brokenReferences: <span>{brokenReferences}</span>,
|
|
250
|
+
variation: (
|
|
251
|
+
<span>
|
|
252
|
+
{brokenReferences === 1 ? (
|
|
253
|
+
<FormattedMessage
|
|
254
|
+
id="reference"
|
|
255
|
+
defaultMessage="reference"
|
|
256
|
+
/>
|
|
257
|
+
) : (
|
|
258
|
+
<FormattedMessage
|
|
259
|
+
id="references"
|
|
260
|
+
defaultMessage="references"
|
|
261
|
+
/>
|
|
262
|
+
)}
|
|
263
|
+
</span>
|
|
264
|
+
),
|
|
265
|
+
}}
|
|
266
|
+
/>
|
|
267
|
+
<BrokenLinksList
|
|
268
|
+
intl={intl}
|
|
269
|
+
breaches={breaches}
|
|
270
|
+
linksAndReferencesViewLink={linksAndReferencesViewLink}
|
|
271
|
+
/>
|
|
272
|
+
</>
|
|
273
|
+
)}
|
|
274
|
+
</>
|
|
275
|
+
) : brokenReferences > 0 ? (
|
|
276
|
+
<>
|
|
277
|
+
<FormattedMessage
|
|
278
|
+
id="Deleting this item breaks {brokenReferences} {variation}."
|
|
279
|
+
defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
|
|
280
|
+
values={{
|
|
281
|
+
brokenReferences: <span>{brokenReferences}</span>,
|
|
282
|
+
variation: (
|
|
283
|
+
<span>
|
|
284
|
+
{brokenReferences === 1 ? (
|
|
285
|
+
<FormattedMessage
|
|
286
|
+
id="reference"
|
|
287
|
+
defaultMessage="reference"
|
|
288
|
+
/>
|
|
289
|
+
) : (
|
|
290
|
+
<FormattedMessage
|
|
291
|
+
id="references"
|
|
292
|
+
defaultMessage="references"
|
|
293
|
+
/>
|
|
294
|
+
)}
|
|
295
|
+
</span>
|
|
296
|
+
),
|
|
297
|
+
}}
|
|
298
|
+
/>
|
|
299
|
+
<BrokenLinksList
|
|
300
|
+
intl={intl}
|
|
301
|
+
breaches={breaches}
|
|
302
|
+
linksAndReferencesViewLink={linksAndReferencesViewLink}
|
|
303
|
+
/>
|
|
304
|
+
</>
|
|
305
|
+
) : null}
|
|
306
|
+
</div>
|
|
307
|
+
}
|
|
308
|
+
onCancel={onCancel}
|
|
309
|
+
onConfirm={onOk}
|
|
310
|
+
size="medium"
|
|
311
|
+
/>
|
|
312
|
+
)
|
|
313
|
+
);
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const BrokenLinksList = ({ intl, breaches, linksAndReferencesViewLink }) => {
|
|
317
|
+
return (
|
|
318
|
+
<div className="broken-links-list">
|
|
319
|
+
<FormattedMessage
|
|
320
|
+
id="These items will have broken links"
|
|
321
|
+
defaultMessage="These items will have broken links"
|
|
322
|
+
/>
|
|
323
|
+
:
|
|
324
|
+
<Table compact>
|
|
325
|
+
<Table.Body>
|
|
326
|
+
{breaches.map((breach) => (
|
|
327
|
+
<Table.Row key={breach.source['@id']} verticalAlign="top">
|
|
328
|
+
<Table.Cell>
|
|
329
|
+
<Link
|
|
330
|
+
to={flattenToAppURL(breach.source['@id'])}
|
|
331
|
+
title={intl.formatMessage(messages.navigate_to_this_item)}
|
|
332
|
+
>
|
|
333
|
+
{breach.source.title}
|
|
334
|
+
</Link>
|
|
335
|
+
</Table.Cell>
|
|
336
|
+
<Table.Cell style={{ minWidth: '140px' }}>
|
|
337
|
+
<FormattedMessage id="refers to" defaultMessage="refers to" />:
|
|
338
|
+
</Table.Cell>
|
|
339
|
+
<Table.Cell>
|
|
340
|
+
<ul style={{ margin: 0 }}>
|
|
341
|
+
{breach.targets.map((target) => (
|
|
342
|
+
<li key={target['@id']}>
|
|
343
|
+
<Link
|
|
344
|
+
to={flattenToAppURL(target['@id'])}
|
|
345
|
+
title={intl.formatMessage(
|
|
346
|
+
messages.navigate_to_this_item,
|
|
347
|
+
)}
|
|
348
|
+
>
|
|
349
|
+
{target.title}
|
|
350
|
+
</Link>
|
|
351
|
+
</li>
|
|
352
|
+
))}
|
|
353
|
+
</ul>
|
|
354
|
+
</Table.Cell>
|
|
355
|
+
</Table.Row>
|
|
356
|
+
))}
|
|
357
|
+
</Table.Body>
|
|
358
|
+
</Table>
|
|
359
|
+
{linksAndReferencesViewLink && (
|
|
360
|
+
<Link to={flattenToAppURL(linksAndReferencesViewLink)}>
|
|
361
|
+
<FormattedMessage
|
|
362
|
+
id="View links and references to this item"
|
|
363
|
+
defaultMessage="View links and references to this item"
|
|
364
|
+
/>
|
|
365
|
+
</Link>
|
|
366
|
+
)}
|
|
367
|
+
</div>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
ContentsDeleteModal.propTypes = {
|
|
371
|
+
itemsToDelete: PropTypes.arrayOf(
|
|
372
|
+
PropTypes.shape({
|
|
373
|
+
UID: PropTypes.string,
|
|
374
|
+
}),
|
|
375
|
+
).isRequired,
|
|
376
|
+
open: PropTypes.bool.isRequired,
|
|
377
|
+
onOk: PropTypes.func.isRequired,
|
|
378
|
+
onCancel: PropTypes.func.isRequired,
|
|
379
|
+
};
|
|
380
|
+
export default ContentsDeleteModal;
|
|
@@ -76,6 +76,10 @@ const messages = defineMessages({
|
|
|
76
76
|
id: 'Unassigned',
|
|
77
77
|
defaultMessage: 'Unassigned',
|
|
78
78
|
},
|
|
79
|
+
select_rule: {
|
|
80
|
+
id: 'Select rule',
|
|
81
|
+
defaultMessage: 'Select rule',
|
|
82
|
+
},
|
|
79
83
|
});
|
|
80
84
|
|
|
81
85
|
/**
|
|
@@ -366,7 +370,9 @@ class Rules extends Component {
|
|
|
366
370
|
/>
|
|
367
371
|
<div style={{ display: 'flex' }}>
|
|
368
372
|
<Select
|
|
369
|
-
placeholder=
|
|
373
|
+
placeholder={this.props.intl.formatMessage(
|
|
374
|
+
messages.select_rule,
|
|
375
|
+
)}
|
|
370
376
|
value={this.state.newRule}
|
|
371
377
|
onChange={(e, { value }) => this.setState({ newRule: value })}
|
|
372
378
|
options={assignable_rules.map((rule, i) => {
|
package/src/reducers/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import emailNotification from '@plone/volto/reducers/emailNotification/emailNoti
|
|
|
20
20
|
import emailSend from '@plone/volto/reducers/emailSend/emailSend';
|
|
21
21
|
import form from '@plone/volto/reducers/form/form';
|
|
22
22
|
import history from '@plone/volto/reducers/history/history';
|
|
23
|
+
import linkIntegrity from '@plone/volto/reducers/linkIntegrity/linkIntegrity';
|
|
23
24
|
import groups from '@plone/volto/reducers/groups/groups';
|
|
24
25
|
import messages from '@plone/volto/reducers/messages/messages';
|
|
25
26
|
import navigation from '@plone/volto/reducers/navigation/navigation';
|
|
@@ -79,6 +80,7 @@ const reducers = {
|
|
|
79
80
|
form,
|
|
80
81
|
groups,
|
|
81
82
|
history,
|
|
83
|
+
linkIntegrity,
|
|
82
84
|
messages,
|
|
83
85
|
navigation,
|
|
84
86
|
querystring,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linkintegrity reducer.
|
|
3
|
+
* @module reducers/linkIntegrity/linkIntegrity
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { LINK_INTEGRITY_CHECK } from '@plone/volto/constants/ActionTypes';
|
|
7
|
+
|
|
8
|
+
const initialState = {
|
|
9
|
+
error: null,
|
|
10
|
+
loaded: false,
|
|
11
|
+
loading: false,
|
|
12
|
+
result: null,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* History reducer.
|
|
17
|
+
* @function linkIntegrity
|
|
18
|
+
* @param {Object} state Current state.
|
|
19
|
+
* @param {Object} action Action to be handled.
|
|
20
|
+
* @returns {Object} New state.
|
|
21
|
+
*/
|
|
22
|
+
export default function linkIntegrity(state = initialState, action = {}) {
|
|
23
|
+
switch (action.type) {
|
|
24
|
+
case `${LINK_INTEGRITY_CHECK}_PENDING`:
|
|
25
|
+
return {
|
|
26
|
+
...state,
|
|
27
|
+
error: null,
|
|
28
|
+
loaded: false,
|
|
29
|
+
loading: true,
|
|
30
|
+
result: null,
|
|
31
|
+
};
|
|
32
|
+
case `${LINK_INTEGRITY_CHECK}_SUCCESS`:
|
|
33
|
+
return {
|
|
34
|
+
...state,
|
|
35
|
+
error: null,
|
|
36
|
+
loaded: true,
|
|
37
|
+
loading: false,
|
|
38
|
+
result: action.result,
|
|
39
|
+
};
|
|
40
|
+
case `${LINK_INTEGRITY_CHECK}_FAIL`:
|
|
41
|
+
return {
|
|
42
|
+
...state,
|
|
43
|
+
error: action.error,
|
|
44
|
+
loaded: true,
|
|
45
|
+
loading: false,
|
|
46
|
+
result: null,
|
|
47
|
+
};
|
|
48
|
+
default:
|
|
49
|
+
return state;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import linkIntegrity from './linkIntegrity';
|
|
2
|
+
import { LINK_INTEGRITY_CHECK } from '@plone/volto/constants/ActionTypes';
|
|
3
|
+
|
|
4
|
+
describe('Link integrity reducer', () => {
|
|
5
|
+
it('should return the initial state', () => {
|
|
6
|
+
expect(linkIntegrity()).toEqual({
|
|
7
|
+
error: null,
|
|
8
|
+
loaded: false,
|
|
9
|
+
loading: false,
|
|
10
|
+
result: null,
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should handle LINK_INTEGRITY_CHECK_PENDING', () => {
|
|
15
|
+
expect(
|
|
16
|
+
linkIntegrity(undefined, {
|
|
17
|
+
type: `${LINK_INTEGRITY_CHECK}_PENDING`,
|
|
18
|
+
}),
|
|
19
|
+
).toEqual({
|
|
20
|
+
error: null,
|
|
21
|
+
loaded: false,
|
|
22
|
+
loading: true,
|
|
23
|
+
result: null,
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should handle LINK_INTEGRITY_CHECK_SUCCESS', () => {
|
|
28
|
+
expect(
|
|
29
|
+
linkIntegrity(undefined, {
|
|
30
|
+
type: `${LINK_INTEGRITY_CHECK}_SUCCESS`,
|
|
31
|
+
result: 'result',
|
|
32
|
+
}),
|
|
33
|
+
).toEqual({
|
|
34
|
+
error: null,
|
|
35
|
+
loaded: true,
|
|
36
|
+
loading: false,
|
|
37
|
+
result: 'result',
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should handle LINK_INTEGRITY_CHECK_FAIL', () => {
|
|
42
|
+
expect(
|
|
43
|
+
linkIntegrity(undefined, {
|
|
44
|
+
type: `${LINK_INTEGRITY_CHECK}_FAIL`,
|
|
45
|
+
error: 'failed',
|
|
46
|
+
}),
|
|
47
|
+
).toEqual({
|
|
48
|
+
error: 'failed',
|
|
49
|
+
loaded: true,
|
|
50
|
+
loading: false,
|
|
51
|
+
result: null,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|