@plone/volto 16.27.0 → 16.28.1
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.draft +4 -3
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +18 -0
- package/README.md +3 -19
- package/locales/ca/LC_MESSAGES/volto.po +94 -30
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +94 -30
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +95 -31
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +94 -30
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +94 -30
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +94 -30
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +94 -30
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +94 -30
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +94 -30
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +94 -30
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +94 -30
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +94 -30
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +94 -30
- package/locales/ro.json +1 -1
- package/locales/volto.pot +95 -31
- package/locales/zh_CN/LC_MESSAGES/volto.po +94 -30
- package/locales/zh_CN.json +1 -1
- package/package.json +1 -1
- package/packages/volto-slate/news/5347.bugfix +1 -0
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/editor/extensions/insertData.js +3 -1
- package/packages/volto-slate/src/editor/extensions/normalizeExternalData.js +1 -1
- package/packages/volto-slate/src/utils/blocks.js +6 -2
- package/src/actions/index.js +7 -0
- package/src/actions/relations/rebuild.js +25 -0
- package/src/actions/relations/relations.js +103 -0
- package/src/actions/relations/relations.test.js +15 -0
- package/src/components/index.js +1 -0
- package/src/components/manage/Contents/Contents.jsx +320 -110
- package/src/components/manage/LinksToItem/LinksToItem.jsx +185 -0
- package/src/components/manage/LinksToItem/LinksToItem.test.jsx +97 -0
- package/src/components/manage/Toolbar/More.jsx +15 -0
- package/src/config/NonContentRoutes.jsx +1 -0
- package/src/config/index.js +2 -0
- package/src/constants/ActionTypes.js +5 -0
- package/src/reducers/index.js +2 -0
- package/src/reducers/relations/relations.js +201 -0
- package/src/routes.js +9 -0
- package/src/start-server.js +4 -0
- package/theme/themes/pastanaga/extras/contents.less +4 -0
- package/.yarn/releases/yarn-4.0.2.cjs +0 -893
- package/apps/plone/node_modules/.bin/acorn +0 -17
- package/apps/plone/node_modules/.bin/addon +0 -17
- package/apps/plone/node_modules/.bin/autoprefixer +0 -17
- package/apps/plone/node_modules/.bin/browserslist +0 -17
- package/apps/plone/node_modules/.bin/build-storybook +0 -17
- package/apps/plone/node_modules/.bin/changelogupdater +0 -17
- package/apps/plone/node_modules/.bin/eslint +0 -17
- package/apps/plone/node_modules/.bin/eslint-config-prettier +0 -17
- package/apps/plone/node_modules/.bin/i18n +0 -17
- package/apps/plone/node_modules/.bin/jest +0 -17
- package/apps/plone/node_modules/.bin/lessc +0 -17
- package/apps/plone/node_modules/.bin/missdev +0 -17
- package/apps/plone/node_modules/.bin/prettier +0 -17
- package/apps/plone/node_modules/.bin/razzle +0 -17
- package/apps/plone/node_modules/.bin/server-test +0 -17
- package/apps/plone/node_modules/.bin/start-server-and-test +0 -17
- package/apps/plone/node_modules/.bin/start-storybook +0 -17
- package/apps/plone/node_modules/.bin/start-test +0 -17
- package/apps/plone/node_modules/.bin/storybook-server +0 -17
- package/apps/plone/node_modules/.bin/stylelint +0 -17
- package/apps/plone/node_modules/.bin/tlds +0 -17
- package/apps/plone/node_modules/.bin/ts-jest +0 -17
- package/apps/plone/node_modules/.bin/tsc +0 -17
- package/apps/plone/node_modules/.bin/tsserver +0 -17
- package/apps/plone/node_modules/.bin/uuid +0 -17
- package/apps/plone/node_modules/.bin/webpack +0 -17
- package/apps/plone/node_modules/.bin/webpack-dev-server +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/acorn +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/addon +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/browserslist +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/changelogupdater +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/eslint +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/eslint-config-prettier +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/i18n +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/prettier +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/release-it +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/stylelint +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/tsc +0 -17
- package/apps/plone/src/addons/volto-volto-project/node_modules/.bin/tsserver +0 -17
- package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +0 -90
- package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +0 -6
- package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +0 -6
- package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +0 -6
- package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +0 -10
- package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +0 -10
- package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +0 -30
- package/packages/volto-slate/build/messages/src/elementEditor/messages.json +0 -10
- package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +0 -6
- package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +0 -6
- package/pyvenv.cfg +0 -5
- package/share/man/man1/ttx.1 +0 -225
- package/styles/Microsoft/AMPM.yml +0 -9
- package/styles/Microsoft/Accessibility.yml +0 -25
- package/styles/Microsoft/Acronyms.yml +0 -64
- package/styles/Microsoft/Adverbs.yml +0 -270
- package/styles/Microsoft/Auto.yml +0 -11
- package/styles/Microsoft/Avoid.yml +0 -14
- package/styles/Microsoft/ComplexWords.yml +0 -120
- package/styles/Microsoft/Contractions.yml +0 -50
- package/styles/Microsoft/Dashes.yml +0 -13
- package/styles/Microsoft/DateFormat.yml +0 -8
- package/styles/Microsoft/DateNumbers.yml +0 -40
- package/styles/Microsoft/DateOrder.yml +0 -8
- package/styles/Microsoft/Ellipses.yml +0 -9
- package/styles/Microsoft/FirstPerson.yml +0 -16
- package/styles/Microsoft/Foreign.yml +0 -13
- package/styles/Microsoft/Gender.yml +0 -8
- package/styles/Microsoft/GenderBias.yml +0 -44
- package/styles/Microsoft/GeneralURL.yml +0 -11
- package/styles/Microsoft/HeadingAcronyms.yml +0 -7
- package/styles/Microsoft/HeadingColons.yml +0 -8
- package/styles/Microsoft/HeadingPunctuation.yml +0 -13
- package/styles/Microsoft/Headings.yml +0 -28
- package/styles/Microsoft/Hyphens.yml +0 -14
- package/styles/Microsoft/Negative.yml +0 -13
- package/styles/Microsoft/Ordinal.yml +0 -13
- package/styles/Microsoft/OxfordComma.yml +0 -8
- package/styles/Microsoft/Passive.yml +0 -183
- package/styles/Microsoft/Percentages.yml +0 -7
- package/styles/Microsoft/Quotes.yml +0 -7
- package/styles/Microsoft/RangeFormat.yml +0 -13
- package/styles/Microsoft/RangeTime.yml +0 -13
- package/styles/Microsoft/Ranges.yml +0 -7
- package/styles/Microsoft/Semicolon.yml +0 -8
- package/styles/Microsoft/SentenceLength.yml +0 -7
- package/styles/Microsoft/Spacing.yml +0 -8
- package/styles/Microsoft/Suspended.yml +0 -7
- package/styles/Microsoft/Terms.yml +0 -41
- package/styles/Microsoft/URLFormat.yml +0 -10
- package/styles/Microsoft/Units.yml +0 -16
- package/styles/Microsoft/Vocab.yml +0 -25
- package/styles/Microsoft/We.yml +0 -11
- package/styles/Microsoft/Wordiness.yml +0 -122
- package/styles/Microsoft/meta.json +0 -4
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
} from 'lodash';
|
|
35
35
|
import move from 'lodash-move';
|
|
36
36
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
37
|
-
import { asyncConnect } from '@plone/volto/helpers';
|
|
37
|
+
import { asyncConnect, flattenToAppURL } from '@plone/volto/helpers';
|
|
38
38
|
|
|
39
39
|
import {
|
|
40
40
|
searchContent,
|
|
@@ -118,9 +118,13 @@ const messages = defineMessages({
|
|
|
118
118
|
id: 'Delete',
|
|
119
119
|
defaultMessage: 'Delete',
|
|
120
120
|
},
|
|
121
|
-
|
|
122
|
-
id: '
|
|
123
|
-
defaultMessage: '
|
|
121
|
+
deleteConfirmSingleItem: {
|
|
122
|
+
id: 'Delete this item?',
|
|
123
|
+
defaultMessage: 'Delete this item?',
|
|
124
|
+
},
|
|
125
|
+
deleteConfirmMultipleItems: {
|
|
126
|
+
id: 'Delete selected items?',
|
|
127
|
+
defaultMessage: 'Delete selected items?',
|
|
124
128
|
},
|
|
125
129
|
deleteError: {
|
|
126
130
|
id: 'The item could not be deleted.',
|
|
@@ -270,35 +274,6 @@ const messages = defineMessages({
|
|
|
270
274
|
id: 'All',
|
|
271
275
|
defaultMessage: 'All',
|
|
272
276
|
},
|
|
273
|
-
linkIntegrityMessageHeader: {
|
|
274
|
-
id: 'Potential link breakage',
|
|
275
|
-
defaultMessage: 'Potential link breakage',
|
|
276
|
-
},
|
|
277
|
-
linkIntegrityMessageBody: {
|
|
278
|
-
id:
|
|
279
|
-
'By deleting this item, you will break ' +
|
|
280
|
-
'links that exist in the items listed below. ' +
|
|
281
|
-
'If this is indeed what you want to do, ' +
|
|
282
|
-
'we recommend that remove these references first.',
|
|
283
|
-
defaultMessage:
|
|
284
|
-
'By deleting this item, ' +
|
|
285
|
-
'you will break links that exist in the items ' +
|
|
286
|
-
'listed below. If this is indeed what you ' +
|
|
287
|
-
'want to do, we recommend that remove ' +
|
|
288
|
-
'these references first.',
|
|
289
|
-
},
|
|
290
|
-
linkIntegrityMessageExtra: {
|
|
291
|
-
id: 'This Page is referenced by the following items:',
|
|
292
|
-
defaultMessage: 'This Page is referenced by the following items:',
|
|
293
|
-
},
|
|
294
|
-
deleteItemCountMessage: {
|
|
295
|
-
id: 'Total items to be deleted:',
|
|
296
|
-
defaultMessage: 'Total items to be deleted:',
|
|
297
|
-
},
|
|
298
|
-
deleteItemMessage: {
|
|
299
|
-
id: 'Items to be deleted:',
|
|
300
|
-
defaultMessage: 'Items to be deleted:',
|
|
301
|
-
},
|
|
302
277
|
});
|
|
303
278
|
|
|
304
279
|
/**
|
|
@@ -434,6 +409,9 @@ class Contents extends Component {
|
|
|
434
409
|
showProperties: false,
|
|
435
410
|
showWorkflow: false,
|
|
436
411
|
itemsToDelete: [],
|
|
412
|
+
containedItemsToDelete: [],
|
|
413
|
+
brokenReferences: 0,
|
|
414
|
+
breaches: [],
|
|
437
415
|
showAllItemsToDelete: true,
|
|
438
416
|
items: this.props.items,
|
|
439
417
|
filter: '',
|
|
@@ -469,12 +447,40 @@ class Contents extends Component {
|
|
|
469
447
|
this.state.itemsToDelete !== prevState.itemsToDelete &&
|
|
470
448
|
this.state.itemsToDelete.length > 0
|
|
471
449
|
) {
|
|
450
|
+
const linkintegrityInfo = await this.props.linkIntegrityCheck(
|
|
451
|
+
map(this.state.itemsToDelete, (item) => this.getFieldById(item, 'UID')),
|
|
452
|
+
);
|
|
453
|
+
const containedItems = linkintegrityInfo
|
|
454
|
+
.map((result) => result.items_total ?? 0)
|
|
455
|
+
.reduce((acc, value) => acc + value, 0);
|
|
456
|
+
const breaches = linkintegrityInfo.flatMap((result) =>
|
|
457
|
+
result.breaches.map((source) => ({
|
|
458
|
+
source: source,
|
|
459
|
+
target: result,
|
|
460
|
+
})),
|
|
461
|
+
);
|
|
462
|
+
const source_by_uid = breaches.reduce(
|
|
463
|
+
(acc, value) => acc.set(value.source.uid, value.source),
|
|
464
|
+
new Map(),
|
|
465
|
+
);
|
|
466
|
+
const by_source = breaches.reduce((acc, value) => {
|
|
467
|
+
if (acc.get(value.source.uid) === undefined) {
|
|
468
|
+
acc.set(value.source.uid, new Set());
|
|
469
|
+
}
|
|
470
|
+
acc.get(value.source.uid).add(value.target);
|
|
471
|
+
return acc;
|
|
472
|
+
}, new Map());
|
|
473
|
+
|
|
472
474
|
this.setState({
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
475
|
+
containedItemsToDelete: containedItems,
|
|
476
|
+
brokenReferences: by_source.size,
|
|
477
|
+
linksAndReferencesViewLink: linkintegrityInfo.length
|
|
478
|
+
? linkintegrityInfo[0]['@id'] + '/links-to-item'
|
|
479
|
+
: null,
|
|
480
|
+
breaches: Array.from(by_source, (entry) => ({
|
|
481
|
+
source: source_by_uid.get(entry[0]),
|
|
482
|
+
targets: Array.from(entry[1]),
|
|
483
|
+
})),
|
|
478
484
|
showAllItemsToDelete:
|
|
479
485
|
this.state.itemsToDelete.length < this.deleteItemsToShowThreshold,
|
|
480
486
|
});
|
|
@@ -1199,85 +1205,289 @@ class Contents extends Component {
|
|
|
1199
1205
|
<article id="content">
|
|
1200
1206
|
<Confirm
|
|
1201
1207
|
open={this.state.showDelete}
|
|
1202
|
-
confirmButton=
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1208
|
+
confirmButton={
|
|
1209
|
+
this.state.brokenReferences === 0
|
|
1210
|
+
? 'Delete'
|
|
1211
|
+
: 'Delete item and break links'
|
|
1212
|
+
}
|
|
1213
|
+
header={
|
|
1214
|
+
this.state.itemsToDelete.length === 1
|
|
1215
|
+
? this.props.intl.formatMessage(
|
|
1216
|
+
messages.deleteConfirmSingleItem,
|
|
1217
|
+
)
|
|
1218
|
+
: this.props.intl.formatMessage(
|
|
1219
|
+
messages.deleteConfirmMultipleItems,
|
|
1220
|
+
)
|
|
1221
|
+
}
|
|
1206
1222
|
content={
|
|
1207
1223
|
<div className="content">
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1224
|
+
{this.state.itemsToDelete.length > 1 ? (
|
|
1225
|
+
this.state.containedItemsToDelete > 0 ? (
|
|
1226
|
+
<>
|
|
1227
|
+
<FormattedMessage
|
|
1228
|
+
id="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
|
|
1229
|
+
defaultMessage="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
|
|
1230
|
+
values={{
|
|
1231
|
+
containedItemsToDelete: (
|
|
1232
|
+
<span>
|
|
1233
|
+
{this.state.containedItemsToDelete}
|
|
1234
|
+
</span>
|
|
1235
|
+
),
|
|
1236
|
+
variation: (
|
|
1237
|
+
<span>
|
|
1238
|
+
{this.state.containedItemsToDelete ===
|
|
1239
|
+
1 ? (
|
|
1240
|
+
<FormattedMessage
|
|
1241
|
+
id="item"
|
|
1242
|
+
defaultMessage="item"
|
|
1243
|
+
/>
|
|
1244
|
+
) : (
|
|
1245
|
+
<FormattedMessage
|
|
1246
|
+
id="items"
|
|
1247
|
+
defaultMessage="items"
|
|
1248
|
+
/>
|
|
1249
|
+
)}
|
|
1250
|
+
</span>
|
|
1251
|
+
),
|
|
1252
|
+
}}
|
|
1253
|
+
/>
|
|
1254
|
+
{this.state.brokenReferences > 0 && (
|
|
1255
|
+
<>
|
|
1256
|
+
<br />
|
|
1257
|
+
<FormattedMessage
|
|
1258
|
+
id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
1259
|
+
defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
1260
|
+
values={{
|
|
1261
|
+
brokenReferences: (
|
|
1262
|
+
<span>
|
|
1263
|
+
{this.state.brokenReferences}
|
|
1264
|
+
</span>
|
|
1265
|
+
),
|
|
1266
|
+
variation: (
|
|
1267
|
+
<span>
|
|
1268
|
+
{this.state.brokenReferences === 1 ? (
|
|
1269
|
+
<FormattedMessage
|
|
1270
|
+
id="reference"
|
|
1271
|
+
defaultMessage="reference"
|
|
1272
|
+
/>
|
|
1273
|
+
) : (
|
|
1274
|
+
<FormattedMessage
|
|
1275
|
+
id="references"
|
|
1276
|
+
defaultMessage="references"
|
|
1277
|
+
/>
|
|
1278
|
+
)}
|
|
1279
|
+
</span>
|
|
1280
|
+
),
|
|
1281
|
+
}}
|
|
1282
|
+
/>
|
|
1283
|
+
</>
|
|
1247
1284
|
)}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1285
|
+
</>
|
|
1286
|
+
) : (
|
|
1287
|
+
<>
|
|
1288
|
+
{this.state.brokenReferences > 0 && (
|
|
1289
|
+
<>
|
|
1290
|
+
<FormattedMessage
|
|
1291
|
+
id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
1292
|
+
defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
|
|
1293
|
+
values={{
|
|
1294
|
+
brokenReferences: (
|
|
1295
|
+
<span>
|
|
1296
|
+
{this.state.brokenReferences}
|
|
1297
|
+
</span>
|
|
1298
|
+
),
|
|
1299
|
+
variation: (
|
|
1300
|
+
<span>
|
|
1301
|
+
{this.state.brokenReferences === 1 ? (
|
|
1302
|
+
<FormattedMessage
|
|
1303
|
+
id="reference"
|
|
1304
|
+
defaultMessage="reference"
|
|
1305
|
+
/>
|
|
1306
|
+
) : (
|
|
1307
|
+
<FormattedMessage
|
|
1308
|
+
id="references"
|
|
1309
|
+
defaultMessage="references"
|
|
1310
|
+
/>
|
|
1311
|
+
)}
|
|
1312
|
+
</span>
|
|
1313
|
+
),
|
|
1314
|
+
}}
|
|
1315
|
+
/>
|
|
1316
|
+
</>
|
|
1252
1317
|
)}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1318
|
+
</>
|
|
1319
|
+
)
|
|
1320
|
+
) : this.state.containedItemsToDelete > 0 ? (
|
|
1321
|
+
<>
|
|
1322
|
+
<FormattedMessage
|
|
1323
|
+
id="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
|
|
1324
|
+
defaultMessage="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
|
|
1325
|
+
values={{
|
|
1326
|
+
containedItemsToDelete: (
|
|
1327
|
+
<span>
|
|
1328
|
+
{this.state.containedItemsToDelete}
|
|
1329
|
+
</span>
|
|
1330
|
+
),
|
|
1331
|
+
variation: (
|
|
1332
|
+
<span>
|
|
1333
|
+
{this.state.containedItemsToDelete === 1 ? (
|
|
1334
|
+
<FormattedMessage
|
|
1335
|
+
id="item"
|
|
1336
|
+
defaultMessage="item"
|
|
1337
|
+
/>
|
|
1338
|
+
) : (
|
|
1339
|
+
<FormattedMessage
|
|
1340
|
+
id="items"
|
|
1341
|
+
defaultMessage="items"
|
|
1342
|
+
/>
|
|
1343
|
+
)}
|
|
1344
|
+
</span>
|
|
1345
|
+
),
|
|
1346
|
+
}}
|
|
1347
|
+
/>
|
|
1348
|
+
{this.state.brokenReferences > 0 && (
|
|
1349
|
+
<>
|
|
1350
|
+
<br />
|
|
1351
|
+
<FormattedMessage
|
|
1352
|
+
id="Deleting this item breaks {brokenReferences} {variation}."
|
|
1353
|
+
defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
|
|
1354
|
+
values={{
|
|
1355
|
+
brokenReferences: (
|
|
1356
|
+
<span>{this.state.brokenReferences}</span>
|
|
1357
|
+
),
|
|
1358
|
+
variation: (
|
|
1359
|
+
<span>
|
|
1360
|
+
{this.state.brokenReferences === 1 ? (
|
|
1361
|
+
<FormattedMessage
|
|
1362
|
+
id="reference"
|
|
1363
|
+
defaultMessage="reference"
|
|
1364
|
+
/>
|
|
1365
|
+
) : (
|
|
1366
|
+
<FormattedMessage
|
|
1367
|
+
id="references"
|
|
1368
|
+
defaultMessage="references"
|
|
1369
|
+
/>
|
|
1370
|
+
)}
|
|
1371
|
+
</span>
|
|
1372
|
+
),
|
|
1373
|
+
}}
|
|
1374
|
+
/>
|
|
1375
|
+
<div className="broken-links-list">
|
|
1376
|
+
<FormattedMessage id="These items will have broken links" />
|
|
1377
|
+
<ul>
|
|
1378
|
+
{this.state.breaches.map((breach) => (
|
|
1379
|
+
<li key={breach.source['@id']}>
|
|
1380
|
+
<Link
|
|
1381
|
+
to={flattenToAppURL(
|
|
1382
|
+
breach.source['@id'],
|
|
1383
|
+
)}
|
|
1384
|
+
title="Navigate to this item"
|
|
1385
|
+
>
|
|
1386
|
+
{breach.source.title}
|
|
1387
|
+
</Link>{' '}
|
|
1388
|
+
refers to{' '}
|
|
1389
|
+
{breach.targets
|
|
1390
|
+
.map((target) => (
|
|
1391
|
+
<Link
|
|
1392
|
+
to={flattenToAppURL(
|
|
1393
|
+
target['@id'],
|
|
1394
|
+
)}
|
|
1395
|
+
title="Navigate to this item"
|
|
1396
|
+
>
|
|
1397
|
+
{target.title}
|
|
1398
|
+
</Link>
|
|
1399
|
+
))
|
|
1400
|
+
.reduce((result, item) => (
|
|
1401
|
+
<>
|
|
1402
|
+
{result}, {item}
|
|
1403
|
+
</>
|
|
1404
|
+
))}
|
|
1405
|
+
</li>
|
|
1406
|
+
))}
|
|
1407
|
+
</ul>
|
|
1408
|
+
{this.state.linksAndReferencesViewLink && (
|
|
1409
|
+
<Link
|
|
1410
|
+
to={flattenToAppURL(
|
|
1411
|
+
this.state.linksAndReferencesViewLink,
|
|
1262
1412
|
)}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1413
|
+
>
|
|
1414
|
+
<FormattedMessage
|
|
1415
|
+
id="View links and references to this item"
|
|
1416
|
+
defaultMessage="View links and references to this item"
|
|
1417
|
+
/>
|
|
1418
|
+
</Link>
|
|
1419
|
+
)}
|
|
1420
|
+
</div>
|
|
1421
|
+
</>
|
|
1422
|
+
)}
|
|
1423
|
+
</>
|
|
1424
|
+
) : this.state.brokenReferences > 0 ? (
|
|
1425
|
+
<>
|
|
1426
|
+
<FormattedMessage
|
|
1427
|
+
id="Deleting this item breaks {brokenReferences} {variation}."
|
|
1428
|
+
defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
|
|
1429
|
+
values={{
|
|
1430
|
+
brokenReferences: (
|
|
1431
|
+
<span>{this.state.brokenReferences}</span>
|
|
1432
|
+
),
|
|
1433
|
+
variation: (
|
|
1434
|
+
<span>
|
|
1435
|
+
{this.state.brokenReferences === 1 ? (
|
|
1436
|
+
<FormattedMessage
|
|
1437
|
+
id="reference"
|
|
1438
|
+
defaultMessage="reference"
|
|
1439
|
+
/>
|
|
1440
|
+
) : (
|
|
1441
|
+
<FormattedMessage id="references" />
|
|
1442
|
+
)}
|
|
1443
|
+
</span>
|
|
1444
|
+
),
|
|
1445
|
+
}}
|
|
1446
|
+
/>
|
|
1447
|
+
<div className="broken-links-list">
|
|
1448
|
+
<FormattedMessage id="These items will have broken links" />
|
|
1449
|
+
<ul>
|
|
1450
|
+
{this.state.breaches.map((breach) => (
|
|
1451
|
+
<li key={breach.source['@id']}>
|
|
1452
|
+
<Link
|
|
1453
|
+
to={flattenToAppURL(breach.source['@id'])}
|
|
1454
|
+
title="Navigate to this item"
|
|
1455
|
+
>
|
|
1456
|
+
{breach.source.title}
|
|
1457
|
+
</Link>{' '}
|
|
1458
|
+
refers to{' '}
|
|
1459
|
+
{breach.targets
|
|
1460
|
+
.map((target) => (
|
|
1461
|
+
<Link
|
|
1462
|
+
to={flattenToAppURL(target['@id'])}
|
|
1463
|
+
title="Navigate to this item"
|
|
1464
|
+
>
|
|
1465
|
+
{target.title}
|
|
1466
|
+
</Link>
|
|
1467
|
+
))
|
|
1468
|
+
.reduce((result, item) => (
|
|
1469
|
+
<>
|
|
1470
|
+
{result}, {item}
|
|
1471
|
+
</>
|
|
1271
1472
|
))}
|
|
1272
|
-
</ul>
|
|
1273
1473
|
</li>
|
|
1274
|
-
)
|
|
1474
|
+
))}
|
|
1475
|
+
</ul>
|
|
1476
|
+
{this.state.linksAndReferencesViewLink && (
|
|
1477
|
+
<Link
|
|
1478
|
+
to={flattenToAppURL(
|
|
1479
|
+
this.state.linksAndReferencesViewLink,
|
|
1480
|
+
)}
|
|
1481
|
+
>
|
|
1482
|
+
<FormattedMessage
|
|
1483
|
+
id="View links and references to this item"
|
|
1484
|
+
defaultMessage="View links and references to this item"
|
|
1485
|
+
/>
|
|
1486
|
+
</Link>
|
|
1275
1487
|
)}
|
|
1276
|
-
</
|
|
1277
|
-
|
|
1278
|
-
) :
|
|
1279
|
-
<div></div>
|
|
1280
|
-
)}
|
|
1488
|
+
</div>
|
|
1489
|
+
</>
|
|
1490
|
+
) : null}
|
|
1281
1491
|
</div>
|
|
1282
1492
|
}
|
|
1283
1493
|
onCancel={this.onDeleteCancel}
|
|
@@ -2079,7 +2289,7 @@ export default compose(
|
|
|
2079
2289
|
asyncConnect([
|
|
2080
2290
|
{
|
|
2081
2291
|
key: 'actions',
|
|
2082
|
-
// Dispatch async/await to make the operation
|
|
2292
|
+
// Dispatch async/await to make the operation synchronous, otherwise it returns
|
|
2083
2293
|
// before the promise is resolved
|
|
2084
2294
|
promise: async ({ location, store: { dispatch } }) =>
|
|
2085
2295
|
await dispatch(listActions(getBaseUrl(location.pathname))),
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinksToItem component
|
|
3
|
+
* @module components/manage/LinksToItem/LinksToItem
|
|
4
|
+
*/
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
import { Helmet } from '@plone/volto/helpers';
|
|
7
|
+
import { Link } from 'react-router-dom';
|
|
8
|
+
import { Portal } from 'react-portal';
|
|
9
|
+
import { Container, Segment, Table } from 'semantic-ui-react';
|
|
10
|
+
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|
11
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
12
|
+
import { getContent, queryRelations } from '@plone/volto/actions';
|
|
13
|
+
import {
|
|
14
|
+
Icon as IconNext,
|
|
15
|
+
Toolbar,
|
|
16
|
+
UniversalLink,
|
|
17
|
+
} from '@plone/volto/components';
|
|
18
|
+
|
|
19
|
+
import { getBaseUrl } from '@plone/volto/helpers';
|
|
20
|
+
import backSVG from '@plone/volto/icons/back.svg';
|
|
21
|
+
|
|
22
|
+
const messages = defineMessages({
|
|
23
|
+
back: {
|
|
24
|
+
id: 'Back',
|
|
25
|
+
defaultMessage: 'Back',
|
|
26
|
+
},
|
|
27
|
+
linkstoitem: {
|
|
28
|
+
id: 'Links and references',
|
|
29
|
+
defaultMessage: 'Links and references',
|
|
30
|
+
},
|
|
31
|
+
helpLinkRelationsControlPanel: {
|
|
32
|
+
id: 'Overview of relations of all content items',
|
|
33
|
+
defaultMessage: 'Overview of relations of all content items',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const LinksToItem = (props) => {
|
|
38
|
+
const intl = useIntl();
|
|
39
|
+
const dispatch = useDispatch();
|
|
40
|
+
const pathname = props.location.pathname;
|
|
41
|
+
const itempath = getBaseUrl(pathname);
|
|
42
|
+
|
|
43
|
+
const title = useSelector((state) => state.content.data?.title || '');
|
|
44
|
+
const myrelations = useSelector(
|
|
45
|
+
(state) => state.relations.subrequests[itempath]?.data,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
dispatch(queryRelations(null, false, itempath, null, [itempath]));
|
|
50
|
+
}, [dispatch, itempath]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!title) dispatch(getContent(itempath));
|
|
54
|
+
}, [dispatch, itempath, title]);
|
|
55
|
+
|
|
56
|
+
let links = {};
|
|
57
|
+
if (myrelations) {
|
|
58
|
+
Object.keys(myrelations).forEach((relationtype) => {
|
|
59
|
+
links[relationtype] = {};
|
|
60
|
+
myrelations[relationtype].items.forEach((item) => {
|
|
61
|
+
links[relationtype][item.source.UID] = item.source;
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let links_ordered = {};
|
|
67
|
+
Object.keys(links).forEach((relationtype) => {
|
|
68
|
+
links_ordered[relationtype] = Object.values(links[relationtype]).sort(
|
|
69
|
+
(link) => link['@id'],
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const relations_found = Object.keys(links_ordered).length > 0;
|
|
74
|
+
return (
|
|
75
|
+
<Container id="linkstoitem">
|
|
76
|
+
<Helmet title={intl.formatMessage(messages.linkstoitem)} />
|
|
77
|
+
<Segment.Group raised>
|
|
78
|
+
<Segment className="primary">
|
|
79
|
+
<FormattedMessage
|
|
80
|
+
id="Content that links to or references {title}"
|
|
81
|
+
defaultMessage="Content that links to or references {title}"
|
|
82
|
+
values={{ title: <q>{title}</q> }}
|
|
83
|
+
/>
|
|
84
|
+
</Segment>
|
|
85
|
+
{relations_found ? (
|
|
86
|
+
<Table selectable compact singleLine attached>
|
|
87
|
+
{
|
|
88
|
+
<Table.Body>
|
|
89
|
+
{Object.keys(links_ordered).map((relationtype) => {
|
|
90
|
+
return [].concat(
|
|
91
|
+
[
|
|
92
|
+
<Table.Row>
|
|
93
|
+
<Table.HeaderCell>
|
|
94
|
+
{relationtype === 'isReferencing' ? (
|
|
95
|
+
<FormattedMessage
|
|
96
|
+
id="Linking this item with hyperlink in text"
|
|
97
|
+
defaultMessage="Linking this item with hyperlink in text"
|
|
98
|
+
/>
|
|
99
|
+
) : relationtype === 'relatedItems' ? (
|
|
100
|
+
<FormattedMessage
|
|
101
|
+
id="Referencing this item as related item"
|
|
102
|
+
defaultMessage="Referencing this item as related item"
|
|
103
|
+
/>
|
|
104
|
+
) : (
|
|
105
|
+
<>
|
|
106
|
+
<FormattedMessage
|
|
107
|
+
id="Referencing this item with {relationship}"
|
|
108
|
+
defaultMessage="Referencing this item with {relationship}"
|
|
109
|
+
values={{ relationship: <q>{relationtype}</q> }}
|
|
110
|
+
/>
|
|
111
|
+
</>
|
|
112
|
+
)}
|
|
113
|
+
</Table.HeaderCell>
|
|
114
|
+
<Table.HeaderCell>
|
|
115
|
+
<FormattedMessage
|
|
116
|
+
id="Review state"
|
|
117
|
+
defaultMessage="Review state"
|
|
118
|
+
/>
|
|
119
|
+
</Table.HeaderCell>
|
|
120
|
+
<Table.HeaderCell>
|
|
121
|
+
<FormattedMessage id="Type" defaultMessage="Type" />
|
|
122
|
+
</Table.HeaderCell>
|
|
123
|
+
</Table.Row>,
|
|
124
|
+
],
|
|
125
|
+
links_ordered[relationtype].map((link) => {
|
|
126
|
+
return (
|
|
127
|
+
<Table.Row key={link['@id']}>
|
|
128
|
+
<Table.Cell>
|
|
129
|
+
<UniversalLink
|
|
130
|
+
href={link['@id']}
|
|
131
|
+
className={`source ${link.review_state}`}
|
|
132
|
+
>
|
|
133
|
+
<span className="label" title={link.type_title}>
|
|
134
|
+
{link.title}
|
|
135
|
+
</span>
|
|
136
|
+
</UniversalLink>
|
|
137
|
+
</Table.Cell>
|
|
138
|
+
<Table.Cell>
|
|
139
|
+
<span>{link.review_state}</span>
|
|
140
|
+
</Table.Cell>
|
|
141
|
+
<Table.Cell>
|
|
142
|
+
<span>{link.type_title || ''}</span>
|
|
143
|
+
</Table.Cell>
|
|
144
|
+
</Table.Row>
|
|
145
|
+
);
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
148
|
+
})}
|
|
149
|
+
</Table.Body>
|
|
150
|
+
}
|
|
151
|
+
</Table>
|
|
152
|
+
) : (
|
|
153
|
+
<Segment secondary>
|
|
154
|
+
<FormattedMessage
|
|
155
|
+
id="No links to this item found."
|
|
156
|
+
defaultMessage="No links to this item found."
|
|
157
|
+
/>
|
|
158
|
+
</Segment>
|
|
159
|
+
)}
|
|
160
|
+
</Segment.Group>
|
|
161
|
+
{__CLIENT__ && (
|
|
162
|
+
<Portal node={document.getElementById('toolbar')}>
|
|
163
|
+
<Toolbar
|
|
164
|
+
pathname={pathname}
|
|
165
|
+
hideDefaultViewButtons
|
|
166
|
+
inner={
|
|
167
|
+
<>
|
|
168
|
+
<Link to={itempath} className="item">
|
|
169
|
+
<IconNext
|
|
170
|
+
name={backSVG}
|
|
171
|
+
className="contents circled"
|
|
172
|
+
size="30px"
|
|
173
|
+
title={intl.formatMessage(messages.back)}
|
|
174
|
+
/>
|
|
175
|
+
</Link>
|
|
176
|
+
</>
|
|
177
|
+
}
|
|
178
|
+
/>
|
|
179
|
+
</Portal>
|
|
180
|
+
)}
|
|
181
|
+
</Container>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export default LinksToItem;
|