diff --git a/src/components/manage/Contents/Contents.jsx b/src/components/manage/Contents/Contents.jsx
index caa61529ad..b190fcdaf9 100644
--- a/src/components/manage/Contents/Contents.jsx
+++ b/src/components/manage/Contents/Contents.jsx
@@ -1,2305 +1,2309 @@
-/**
- * Contents component.
- * @module components/manage/Contents/Contents
- */
-
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-import { compose } from 'redux';
-import { Portal } from 'react-portal';
-import { Link } from 'react-router-dom';
-import {
- Button,
- Confirm,
- Container as SemanticContainer,
- Divider,
- Dropdown,
- Menu,
- Input,
- Segment,
- Table,
- Loader,
- Dimmer,
-} from 'semantic-ui-react';
-import {
- concat,
- filter,
- find,
- indexOf,
- keys,
- map,
- mapValues,
- pull,
-} from 'lodash';
-import move from 'lodash-move';
-import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
-import { asyncConnect } from '@plone/volto/helpers';
-import { flattenToAppURL } from '@plone/volto/helpers';
-
-import {
- searchContent,
- cut,
- copy,
- copyContent,
- deleteContent,
- listActions,
- moveContent,
- orderContent,
- sortContent,
- updateColumnsContent,
- linkIntegrityCheck,
- getContent,
-} from '@plone/volto/actions';
-import Indexes, { defaultIndexes } from '@plone/volto/constants/Indexes';
-import {
- ContentsBreadcrumbs,
- ContentsIndexHeader,
- ContentsItem,
- ContentsRenameModal,
- ContentsUploadModal,
- ContentsWorkflowModal,
- ContentsTagsModal,
- ContentsPropertiesModal,
- Pagination,
- Popup,
- Toolbar,
- Toast,
- Icon,
- Unauthorized,
-} from '@plone/volto/components';
-
-import { Helmet, getBaseUrl } from '@plone/volto/helpers';
-import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
-import config from '@plone/volto/registry';
-
-import backSVG from '@plone/volto/icons/back.svg';
-import cutSVG from '@plone/volto/icons/cut.svg';
-import deleteSVG from '@plone/volto/icons/delete.svg';
-import copySVG from '@plone/volto/icons/copy.svg';
-import tagSVG from '@plone/volto/icons/tag.svg';
-import renameSVG from '@plone/volto/icons/rename.svg';
-import semaphoreSVG from '@plone/volto/icons/semaphore.svg';
-import uploadSVG from '@plone/volto/icons/upload.svg';
-import propertiesSVG from '@plone/volto/icons/properties.svg';
-import pasteSVG from '@plone/volto/icons/paste.svg';
-import zoomSVG from '@plone/volto/icons/zoom.svg';
-import checkboxUncheckedSVG from '@plone/volto/icons/checkbox-unchecked.svg';
-import checkboxCheckedSVG from '@plone/volto/icons/checkbox-checked.svg';
-import checkboxIndeterminateSVG from '@plone/volto/icons/checkbox-indeterminate.svg';
-import configurationSVG from '@plone/volto/icons/configuration-app.svg';
-import sortDownSVG from '@plone/volto/icons/sort-down.svg';
-import sortUpSVG from '@plone/volto/icons/sort-up.svg';
-import downKeySVG from '@plone/volto/icons/down-key.svg';
-import moreSVG from '@plone/volto/icons/more.svg';
-import clearSVG from '@plone/volto/icons/clear.svg';
-
-const messages = defineMessages({
- back: {
- id: 'Back',
- defaultMessage: 'Back',
- },
- contents: {
- id: 'Contents',
- defaultMessage: 'Contents',
- },
- copy: {
- id: 'Copy',
- defaultMessage: 'Copy',
- },
- cut: {
- id: 'Cut',
- defaultMessage: 'Cut',
- },
- error: {
- id: "You can't paste this content here",
- defaultMessage: "You can't paste this content here",
- },
- delete: {
- id: 'Delete',
- defaultMessage: 'Delete',
- },
- deleteConfirmSingleItem: {
- id: 'Delete this item?',
- defaultMessage: 'Delete this item?',
- },
- deleteConfirmMultipleItems: {
- id: 'Delete selected items?',
- defaultMessage: 'Delete selected items?',
- },
- deleteError: {
- id: 'The item could not be deleted.',
- defaultMessage: 'The item could not be deleted.',
- },
- loading: {
- id: 'loading',
- defaultMessage: 'Loading',
- },
- home: {
- id: 'Home',
- defaultMessage: 'Home',
- },
- filter: {
- id: 'Filter…',
- defaultMessage: 'Filter…',
- },
- messageCopied: {
- id: 'Item(s) copied.',
- defaultMessage: 'Item(s) copied.',
- },
- messageCut: {
- id: 'Item(s) cut.',
- defaultMessage: 'Item(s) cut.',
- },
- messageUpdate: {
- id: 'Item(s) has been updated.',
- defaultMessage: 'Item(s) has been updated.',
- },
- messageReorder: {
- id: 'Item succesfully moved.',
- defaultMessage: 'Item successfully moved.',
- },
- messagePasted: {
- id: 'Item(s) pasted.',
- defaultMessage: 'Item(s) pasted.',
- },
- messageWorkflowUpdate: {
- id: 'Item(s) state has been updated.',
- defaultMessage: 'Item(s) state has been updated.',
- },
- paste: {
- id: 'Paste',
- defaultMessage: 'Paste',
- },
- properties: {
- id: 'Properties',
- defaultMessage: 'Properties',
- },
- rearrangeBy: {
- id: 'Rearrange items by…',
- defaultMessage: 'Rearrange items by…',
- },
- rename: {
- id: 'Rename',
- defaultMessage: 'Rename',
- },
- select: {
- id: 'Select…',
- defaultMessage: 'Select…',
- },
- selected: {
- id: '{count} selected',
- defaultMessage: '{count} selected',
- },
- selectColumns: {
- id: 'Select columns to show',
- defaultMessage: 'Select columns to show',
- },
- sort: {
- id: 'sort',
- defaultMessage: 'sort',
- },
- state: {
- id: 'State',
- defaultMessage: 'State',
- },
- tags: {
- id: 'Tags',
- defaultMessage: 'Tags',
- },
- upload: {
- id: 'Upload',
- defaultMessage: 'Upload',
- },
- success: {
- id: 'Success',
- defaultMessage: 'Success',
- },
- publicationDate: {
- id: 'Publication date',
- defaultMessage: 'Publication date',
- },
- createdOn: {
- id: 'Created on',
- defaultMessage: 'Created on',
- },
- expirationDate: {
- id: 'Expiration date',
- defaultMessage: 'Expiration date',
- },
- id: {
- id: 'ID',
- defaultMessage: 'ID',
- },
- uid: {
- id: 'UID',
- defaultMessage: 'UID',
- },
- reviewState: {
- id: 'Review state',
- defaultMessage: 'Review state',
- },
- folder: {
- id: 'Folder',
- defaultMessage: 'Folder',
- },
- excludedFromNavigation: {
- id: 'Excluded from navigation',
- defaultMessage: 'Excluded from navigation',
- },
- objectSize: {
- id: 'Object Size',
- defaultMessage: 'Object Size',
- },
- lastCommentedDate: {
- id: 'Last comment date',
- defaultMessage: 'Last comment date',
- },
- totalComments: {
- id: 'Total comments',
- defaultMessage: 'Total comments',
- },
- creator: {
- id: 'Creator',
- defaultMessage: 'Creator',
- },
- endDate: {
- id: 'End Date',
- defaultMessage: 'End Date',
- },
- startDate: {
- id: 'Start Date',
- defaultMessage: 'Start Date',
- },
- all: {
- id: 'All',
- defaultMessage: 'All',
- },
-});
-
-/**
- * Contents class.
- * @class Contents
- * @extends Component
- */
-class Contents extends Component {
- /**
- * Property types.
- * @property {Object} propTypes Property types.
- * @static
- */
- static propTypes = {
- action: PropTypes.string,
- source: PropTypes.arrayOf(PropTypes.string),
- searchContent: PropTypes.func.isRequired,
- cut: PropTypes.func.isRequired,
- copy: PropTypes.func.isRequired,
- copyContent: PropTypes.func.isRequired,
- deleteContent: PropTypes.func.isRequired,
- moveContent: PropTypes.func.isRequired,
- orderContent: PropTypes.func.isRequired,
- sortContent: PropTypes.func.isRequired,
- updateColumnsContent: PropTypes.func.isRequired,
- linkIntegrityCheck: PropTypes.func.isRequired,
- clipboardRequest: PropTypes.shape({
- loading: PropTypes.bool,
- loaded: PropTypes.bool,
- }).isRequired,
- deleteRequest: PropTypes.shape({
- loading: PropTypes.bool,
- loaded: PropTypes.bool,
- }).isRequired,
- updateRequest: PropTypes.shape({
- loading: PropTypes.bool,
- loaded: PropTypes.bool,
- }).isRequired,
- searchRequest: PropTypes.shape({
- loading: PropTypes.bool,
- loaded: PropTypes.bool,
- }).isRequired,
- items: PropTypes.arrayOf(
- PropTypes.shape({
- '@id': PropTypes.string,
- '@type': PropTypes.string,
- title: PropTypes.string,
- description: PropTypes.string,
- }),
- ),
- breadcrumbs: PropTypes.arrayOf(
- PropTypes.shape({
- title: PropTypes.string,
- url: PropTypes.string,
- }),
- ).isRequired,
- total: PropTypes.number.isRequired,
- pathname: PropTypes.string.isRequired,
- };
-
- /**
- * Default properties.
- * @property {Object} defaultProps Default properties.
- * @static
- */
- static defaultProps = {
- items: [],
- action: null,
- source: null,
- index: {
- order: keys(Indexes),
- values: mapValues(Indexes, (value, key) => ({
- ...value,
- selected: indexOf(defaultIndexes, key) !== -1,
- })),
- selectedCount: defaultIndexes.length + 1,
- },
- };
-
- /**
- * Constructor
- * @method constructor
- * @param {Object} props Component properties
- * @constructs ContentsComponent
- */
- constructor(props) {
- super(props);
- this.onDeselect = this.onDeselect.bind(this);
- this.onSelect = this.onSelect.bind(this);
- this.onSelectAll = this.onSelectAll.bind(this);
- this.onSelectIndex = this.onSelectIndex.bind(this);
- this.onSelectNone = this.onSelectNone.bind(this);
- this.onDeleteOk = this.onDeleteOk.bind(this);
- this.onDeleteCancel = this.onDeleteCancel.bind(this);
- this.onUploadOk = this.onUploadOk.bind(this);
- this.onUploadCancel = this.onUploadCancel.bind(this);
- this.onRenameOk = this.onRenameOk.bind(this);
- this.onRenameCancel = this.onRenameCancel.bind(this);
- this.onTagsOk = this.onTagsOk.bind(this);
- this.onTagsCancel = this.onTagsCancel.bind(this);
- this.onPropertiesOk = this.onPropertiesOk.bind(this);
- this.onPropertiesCancel = this.onPropertiesCancel.bind(this);
- this.onWorkflowOk = this.onWorkflowOk.bind(this);
- this.onWorkflowCancel = this.onWorkflowCancel.bind(this);
- this.onChangeFilter = this.onChangeFilter.bind(this);
- this.onChangePage = this.onChangePage.bind(this);
- this.onChangePageSize = this.onChangePageSize.bind(this);
- this.onOrderIndex = this.onOrderIndex.bind(this);
- this.onOrderItem = this.onOrderItem.bind(this);
- this.onSortItems = this.onSortItems.bind(this);
- this.onMoveToTop = this.onMoveToTop.bind(this);
- this.onChangeSelected = this.onChangeSelected.bind(this);
- this.onMoveToBottom = this.onMoveToBottom.bind(this);
- this.cut = this.cut.bind(this);
- this.copy = this.copy.bind(this);
- this.delete = this.delete.bind(this);
- this.upload = this.upload.bind(this);
- this.rename = this.rename.bind(this);
- this.tags = this.tags.bind(this);
- this.properties = this.properties.bind(this);
- this.workflow = this.workflow.bind(this);
- this.paste = this.paste.bind(this);
- this.fetchContents = this.fetchContents.bind(this);
- this.orderTimeout = null;
- this.deleteItemsToShowThreshold = 10;
-
- this.state = {
- selected: [],
- showDelete: false,
- showUpload: false,
- showRename: false,
- showTags: false,
- showProperties: false,
- showWorkflow: false,
- itemsToDelete: [],
- containedItemsToDelete: [],
- brokenReferences: 0,
- breaches: [],
- showAllItemsToDelete: true,
- items: this.props.items,
- filter: '',
- currentPage: 0,
- pageSize: 50,
- index: this.props.index || {
- order: keys(Indexes),
- values: mapValues(Indexes, (value, key) => ({
- ...value,
- selected: indexOf(defaultIndexes, key) !== -1,
- })),
- selectedCount: defaultIndexes.length + 1,
- },
- sort_on: this.props.sort?.on || 'getObjPositionInParent',
- sort_order: this.props.sort?.order || 'ascending',
- isClient: false,
- linkIntegrityBreakages: [],
- };
- this.filterTimeout = null;
- }
-
- /**
- * Component did mount
- * @method componentDidMount
- * @returns {undefined}
- */
- componentDidMount() {
- this.fetchContents();
- this.setState({ isClient: true });
- }
- async componentDidUpdate(_, prevState) {
- if (
- this.state.itemsToDelete !== prevState.itemsToDelete &&
- this.state.itemsToDelete.length > 0
- ) {
- const linkintegrityInfo = await this.props.linkIntegrityCheck(
- map(this.state.itemsToDelete, (item) => this.getFieldById(item, 'UID')),
- );
- const containedItems = linkintegrityInfo
- .map((result) => result.items_total ?? 0)
- .reduce((acc, value) => acc + value, 0);
- const breaches = linkintegrityInfo.flatMap((result) =>
- result.breaches.map((source) => ({
- source: source,
- target: result,
- })),
- );
- const source_by_uid = breaches.reduce(
- (acc, value) => acc.set(value.source.uid, value.source),
- new Map(),
- );
- const by_source = breaches.reduce((acc, value) => {
- if (acc.get(value.source.uid) === undefined) {
- acc.set(value.source.uid, new Set());
- }
- acc.get(value.source.uid).add(value.target);
- return acc;
- }, new Map());
-
- this.setState({
- containedItemsToDelete: containedItems,
- brokenReferences: by_source.size,
- linksAndReferencesViewLink: linkintegrityInfo.length
- ? linkintegrityInfo[0]['@id'] + '/links-to-item'
- : null,
- breaches: Array.from(by_source, (entry) => ({
- source: source_by_uid.get(entry[0]),
- targets: Array.from(entry[1]),
- })),
- showAllItemsToDelete:
- this.state.itemsToDelete.length < this.deleteItemsToShowThreshold,
- });
- }
- }
-
- /**
- * Component will receive props
- * @method componentWillReceiveProps
- * @param {Object} nextProps Next properties
- * @returns {undefined}
- */
- UNSAFE_componentWillReceiveProps(nextProps) {
- if (
- (this.props.clipboardRequest.loading &&
- nextProps.clipboardRequest.loaded) ||
- (this.props.deleteRequest.loading && nextProps.deleteRequest.loaded) ||
- (this.props.updateRequest.loading && nextProps.updateRequest.loaded)
- ) {
- this.fetchContents(nextProps.pathname);
- }
- if (this.props.updateRequest.loading && nextProps.updateRequest.loaded) {
- this.props.toastify.toast.success(
- ,
- );
- }
- if (this.props.pathname !== nextProps.pathname) {
- // Refetching content to sync the current object in the toolbar
- this.props.getContent(getBaseUrl(nextProps.pathname));
- this.setState(
- {
- currentPage: 0,
- },
- () =>
- this.setState({ filter: '' }, () =>
- this.fetchContents(nextProps.pathname),
- ),
- );
- }
- if (this.props.searchRequest.loading && nextProps.searchRequest.loaded) {
- this.setState({
- items: nextProps.items,
- });
- }
- if (
- this.props.clipboardRequest.loading &&
- nextProps.clipboardRequest.error
- ) {
- this.props.toastify.toast.error(
- ,
- );
- }
-
- if (
- this.props.clipboardRequest.loading &&
- nextProps.clipboardRequest.loaded
- ) {
- this.props.toastify.toast.success(
- ,
- );
- }
-
- if (this.props.deleteRequest.loading && nextProps.deleteRequest.error) {
- this.props.toastify.toast.error(
- ,
- );
- }
-
- if (this.props.orderRequest.loading && nextProps.orderRequest.loaded) {
- this.props.toastify.toast.success(
- ,
- );
- }
- }
-
- /**
- * On deselect handler
- * @method onDeselect
- * @param {object} event Event object
- * @param {string} value Value
- * @returns {undefined}
- */
- onDeselect(event, { value }) {
- this.setState({
- selected: pull(this.state.selected, value),
- });
- }
-
- /**
- * On select handler
- * @method onSelect
- * @param {object} event Event object
- * @returns {undefined}
- */
- onSelect(event, id) {
- if (indexOf(this.state.selected, id) === -1) {
- this.setState({
- selected: concat(this.state.selected, id),
- });
- } else {
- this.setState({
- selected: pull(this.state.selected, id),
- });
- }
- }
-
- /**
- * On select all handler
- * @method onSelectAll
- * @returns {undefined}
- */
- onSelectAll() {
- this.setState({
- selected: map(this.state.items, (item) => item['@id']),
- });
- }
-
- /**
- * On select none handler
- * @method onSelectNone
- * @returns {undefined}
- */
- onSelectNone() {
- this.setState({
- selected: [],
- });
- }
-
- /**
- * On select index
- * @method onSelectIndex
- * @param {object} event Event object.
- * @param {string} value Index value.
- * @returns {undefined}
- */
- onSelectIndex(event, { value }) {
- let newIndex = {
- ...this.state.index,
- selectedCount:
- this.state.index.selectedCount +
- (this.state.index.values[value].selected ? -1 : 1),
- values: mapValues(this.state.index.values, (indexValue, indexKey) => ({
- ...indexValue,
- selected:
- indexKey === value ? !indexValue.selected : indexValue.selected,
- })),
- };
- this.setState({
- index: newIndex,
- });
- this.props.updateColumnsContent(getBaseUrl(this.props.pathname), newIndex);
- }
-
- /**
- * On change filter
- * @method onChangeFilter
- * @param {object} event Event object.
- * @param {string} value Filter value.
- * @returns {undefined}
- */
- onChangeFilter(event, { value }) {
- const self = this;
- clearTimeout(self.filterTimeout);
- this.setState(
- {
- filter: value,
- },
- () => {
- self.filterTimeout = setTimeout(() => {
- self.fetchContents();
- }, 200);
- },
- );
- }
-
- /**
- * On change selected values (Filter)
- * @method onChangeSelected
- * @param {object} event Event object.
- * @param {string} value Filter value.
- * @returns {undefined}
- */
- onChangeSelected(event, { value }) {
- event.stopPropagation();
- const { items, selected } = this.state;
-
- const filteredItems = filter(selected, (selectedItem) =>
- find(items, (item) => item['@id'] === selectedItem)
- .title.toLowerCase()
- .includes(value.toLowerCase()),
- );
-
- this.setState({
- filteredItems,
- selectedMenuFilter: value,
- });
- }
-
- /**
- * On change page
- * @method onChangePage
- * @param {object} event Event object.
- * @param {string} value Page value.
- * @returns {undefined}
- */
- onChangePage(event, { value }) {
- this.setState(
- {
- currentPage: value,
- },
- () => this.fetchContents(),
- );
- }
-
- /**
- * On change page size
- * @method onChangePageSize
- * @param {object} event Event object.
- * @param {string} value Page size value.
- * @returns {undefined}
- */
- onChangePageSize(event, { value }) {
- this.setState(
- {
- pageSize: value,
- currentPage: 0,
- },
- () => this.fetchContents(),
- );
- }
-
- /**
- * On order index
- * @method onOrderIndex
- * @param {number} index Index
- * @param {number} delta Delta
- * @returns {undefined}
- */
- onOrderIndex(index, delta) {
- this.setState({
- index: {
- ...this.state.index,
- order: move(this.state.index.order, index, index + delta),
- },
- });
- this.props.updateColumnsContent(
- getBaseUrl(this.props.pathname),
- this.state.index,
- );
- }
-
- /**
- * On order item
- * @method onOrderItem
- * @param {string} id Item id
- * @param {number} itemIndex Item index
- * @param {number} delta Delta
- * @returns {undefined}
- */
- onOrderItem(id, itemIndex, delta, backend) {
- if (backend) {
- this.props.orderContent(
- getBaseUrl(this.props.pathname),
- id.replace(/^.*\//, ''),
- delta,
- );
- } else {
- this.setState({
- items: move(this.state.items, itemIndex, itemIndex + delta),
- });
- }
- }
-
- /**
- * On sort items
- * @method onSortItems
- * @param {object} event Event object
- * @param {string} value Item index
- * @returns {undefined}
- */
- onSortItems(event, { value }) {
- const values = value.split('|');
- this.setState({
- sort_on: values[0],
- sort_order: values[1],
- });
- this.props.sortContent(
- getBaseUrl(this.props.pathname),
- values[0],
- values[1],
- );
- }
-
- /**
- * On move to top
- * @method onMoveToTop
- * @param {object} event Event object
- * @param {string} value Item index
- * @returns {undefined}
- */
- onMoveToTop(event, { value }) {
- const id = this.state.items[value]['@id'];
- this.props
- .orderContent(
- getBaseUrl(this.props.pathname),
- id.replace(/^.*\//, ''),
- 'top',
- )
- .then(() => {
- this.setState(
- {
- currentPage: 0,
- },
- () => this.fetchContents(),
- );
- });
- }
-
- /**
- * On move to bottom
- * @method onMoveToBottom
- * @param {object} event Event object
- * @param {string} value Item index
- * @returns {undefined}
- */
- onMoveToBottom(event, { value }) {
- const id = this.state.items[value]['@id'];
- this.props
- .orderContent(
- getBaseUrl(this.props.pathname),
- id.replace(/^.*\//, ''),
- 'bottom',
- )
- .then(() => {
- this.setState(
- {
- currentPage: 0,
- },
- () => this.fetchContents(),
- );
- });
- }
-
- /**
- * On delete ok
- * @method onDeleteOk
- * @returns {undefined}
- */
- onDeleteOk() {
- this.props.deleteContent(this.state.itemsToDelete);
- this.setState({
- showDelete: false,
- itemsToDelete: [],
- selected: [],
- });
- }
-
- /**
- * On delete cancel
- * @method onDeleteCancel
- * @returns {undefined}
- */
- onDeleteCancel() {
- this.setState({
- showDelete: false,
- itemsToDelete: [],
- });
- }
-
- /**
- * On upload ok
- * @method onUploadOk
- * @returns {undefined}
- */
- onUploadOk() {
- this.fetchContents();
- this.setState({
- showUpload: false,
- });
- }
-
- /**
- * On upload cancel
- * @method onUploadCancel
- * @returns {undefined}
- */
- onUploadCancel() {
- this.setState({
- showUpload: false,
- });
- }
-
- /**
- * On rename ok
- * @method onRenameOk
- * @returns {undefined}
- */
- onRenameOk() {
- this.setState({
- showRename: false,
- selected: [],
- });
- }
-
- /**
- * On rename cancel
- * @method onRenameCancel
- * @returns {undefined}
- */
- onRenameCancel() {
- this.setState({
- showRename: false,
- });
- }
-
- /**
- * On tags ok
- * @method onTagsOk
- * @returns {undefined}
- */
- onTagsOk() {
- this.setState({
- showTags: false,
- selected: [],
- });
- }
-
- /**
- * On tags cancel
- * @method onTagsCancel
- * @returns {undefined}
- */
- onTagsCancel() {
- this.setState({
- showTags: false,
- });
- }
-
- /**
- * On properties ok
- * @method onPropertiesOk
- * @returns {undefined}
- */
- onPropertiesOk() {
- this.setState({
- showProperties: false,
- selected: [],
- });
- }
-
- /**
- * On properties cancel
- * @method onPropertiesCancel
- * @returns {undefined}
- */
- onPropertiesCancel() {
- this.setState({
- showProperties: false,
- });
- }
-
- /**
- * On workflow ok
- * @method onWorkflowOk
- * @returns {undefined}
- */
- onWorkflowOk() {
- this.fetchContents();
- this.setState({
- showWorkflow: false,
- selected: [],
- });
- this.props.toastify.toast.success(
- ,
- );
- }
-
- /**
- * On workflow cancel
- * @method onWorkflowCancel
- * @returns {undefined}
- */
- onWorkflowCancel() {
- this.setState({
- showWorkflow: false,
- });
- }
-
- /**
- * Get field by id
- * @method getFieldById
- * @param {string} id Id of object
- * @param {string} field Field of object
- * @returns {string} Field of object
- */
- getFieldById(id, field) {
- const item = find(this.state.items, { '@id': id });
- return item ? item[field] : '';
- }
-
- /**
- * Fetch contents handler
- * @method fetchContents
- * @param {string} pathname Pathname to fetch contents.
- * @returns {undefined}
- */
- fetchContents(pathname) {
- if (this.state.pageSize === this.props.intl.formatMessage(messages.all)) {
- //'All'
- this.props.searchContent(getBaseUrl(pathname || this.props.pathname), {
- 'path.depth': 1,
- sort_on: this.state.sort_on,
- sort_order: this.state.sort_order,
- metadata_fields: '_all',
- b_size: 100000000,
- show_inactive: true,
- ...(this.state.filter && { SearchableText: `${this.state.filter}*` }),
- });
- } else {
- this.props.searchContent(getBaseUrl(pathname || this.props.pathname), {
- 'path.depth': 1,
- sort_on: this.state.sort_on,
- sort_order: this.state.sort_order,
- metadata_fields: '_all',
- ...(this.state.filter && { SearchableText: `${this.state.filter}*` }),
- b_size: this.state.pageSize,
- b_start: this.state.currentPage * this.state.pageSize,
- show_inactive: true,
- });
- }
- }
-
- /**
- * Cut handler
- * @method cut
- * @param {Object} event Event object.
- * @param {string} value Value of the event.
- * @returns {undefined}
- */
- cut(event, { value }) {
- this.props.cut(value ? [value] : this.state.selected);
- this.onSelectNone();
- this.props.toastify.toast.success(
- ,
- );
- }
-
- /**
- * Copy handler
- * @method copy
- * @param {Object} event Event object.
- * @param {string} value Value of the event.
- * @returns {undefined}
- */
- copy(event, { value }) {
- this.props.copy(value ? [value] : this.state.selected);
- this.onSelectNone();
- this.props.toastify.toast.success(
- ,
- );
- }
-
- /**
- * Delete handler
- * @method delete
- * @param {Object} event Event object.
- * @param {string} value Value of the event.
- * @returns {undefined}
- */
- delete(event, { value }) {
- this.setState({
- showDelete: true,
- itemsToDelete: value ? [value] : this.state.selected,
- });
- }
-
- /**
- * Upload handler
- * @method upload
- * @returns {undefined}
- */
- upload() {
- this.setState({
- showUpload: true,
- });
- }
-
- /**
- * Rename handler
- * @method rename
- * @returns {undefined}
- */
- rename() {
- this.setState({
- showRename: true,
- });
- }
-
- /**
- * Tags handler
- * @method tags
- * @returns {undefined}
- */
- tags() {
- this.setState({
- showTags: true,
- });
- }
-
- /**
- * Properties handler
- * @method properties
- * @returns {undefined}
- */
- properties() {
- this.setState({
- showProperties: true,
- });
- }
-
- /**
- * Workflow handler
- * @method workflow
- * @returns {undefined}
- */
- workflow() {
- this.setState({
- showWorkflow: true,
- });
- }
-
- /**
- * Paste handler
- * @method paste
- * @returns {undefined}
- */
- paste() {
- if (this.props.action === 'copy') {
- this.props.copyContent(
- this.props.source,
- getBaseUrl(this.props.pathname),
- );
- }
- if (this.props.action === 'cut') {
- this.props.moveContent(
- this.props.source,
- getBaseUrl(this.props.pathname),
- );
- }
- }
-
- /**
- * Render method.
- * @method render
- * @returns {string} Markup for the component.
- */
- render() {
- const selected = this.state.selected.length > 0;
- const filteredItems = this.state.filteredItems || this.state.selected;
- const path = getBaseUrl(this.props.pathname);
- const folderContentsAction = find(this.props.objectActions, {
- id: 'folderContents',
- });
- const loading =
- (this.props.clipboardRequest?.loading &&
- !this.props.clipboardRequest?.error) ||
- (this.props.deleteRequest?.loading && !this.props.deleteRequest?.error) ||
- (this.props.updateRequest?.loading && !this.props.updateRequest?.error) ||
- (this.props.orderRequest?.loading && !this.props.orderRequest?.error) ||
- (this.props.searchRequest?.loading && !this.props.searchRequest?.error);
-
- const Container =
- config.getComponent({ name: 'Container' }).component || SemanticContainer;
-
- return this.props.token && this.props.objectActions?.length > 0 ? (
- <>
- {folderContentsAction ? (
-
-
-
-
- {this.props.intl.formatMessage(messages.loading)}
-
-
-
-
-
-
-
- {this.state.itemsToDelete.length > 1 ? (
- this.state.containedItemsToDelete > 0 ? (
- <>
-
- {this.state.containedItemsToDelete}
-
- ),
- variation: (
-
- {this.state.containedItemsToDelete ===
- 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
- {this.state.brokenReferences > 0 && (
- <>
-
-
- {this.state.brokenReferences}
-
- ),
- variation: (
-
- {this.state.brokenReferences === 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
- >
- )}
- >
- ) : (
- <>
- {this.state.brokenReferences > 0 && (
- <>
-
- {this.state.brokenReferences}
-
- ),
- variation: (
-
- {this.state.brokenReferences === 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
- >
- )}
- >
- )
- ) : this.state.containedItemsToDelete > 0 ? (
- <>
-
- {this.state.containedItemsToDelete}
-
- ),
- variation: (
-
- {this.state.containedItemsToDelete === 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
- {this.state.brokenReferences > 0 && (
- <>
-
- {this.state.brokenReferences}
- ),
- variation: (
-
- {this.state.brokenReferences === 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
-
-
-
- {this.state.breaches.map((breach) => (
- -
-
- {breach.source.title}
- {' '}
- refers to{' '}
- {breach.targets
- .map((target) => (
-
- {target.title}
-
- ))
- .reduce((result, item) => (
- <>
- {result}, {item}
- >
- ))}
-
- ))}
-
- {this.state.linksAndReferencesViewLink && (
-
-
-
- )}
-
- >
- )}
- >
- ) : this.state.brokenReferences > 0 ? (
- <>
- {this.state.brokenReferences}
- ),
- variation: (
-
- {this.state.brokenReferences === 1 ? (
-
- ) : (
-
- )}
-
- ),
- }}
- />
-
-
-
- {this.state.breaches.map((breach) => (
- -
-
- {breach.source.title}
- {' '}
- refers to{' '}
- {breach.targets
- .map((target) => (
-
- {target.title}
-
- ))
- .reduce((result, item) => (
- <>
- {result}, {item}
- >
- ))}
-
- ))}
-
- {this.state.linksAndReferencesViewLink && (
-
-
-
- )}
-
- >
- ) : null}
-
- }
- onCancel={this.onDeleteCancel}
- onConfirm={this.onDeleteOk}
- size="medium"
- />
-
- ({
- url: item,
- title: this.getFieldById(item, 'title'),
- id: this.getFieldById(item, 'id'),
- }))}
- />
- ({
- url: item,
- subjects: this.getFieldById(item, 'Subject'),
- }))}
- />
-
- {this.state.showWorkflow && (
-
- )}
-
-
-
-
-
-
- }
- className="right floating selectIndex"
- >
-
-
-
- {map(
- filter(
- this.state.index.order,
- (index) => index !== 'sortable_title',
- ),
- (index) => (
-
- {this.state.index.values[index].selected ? (
-
- ) : (
-
- )}
-
- {' '}
- {this.props.intl.formatMessage({
- id: this.state.index.values[index]
- .label,
- defaultMessage:
- this.state.index.values[index].label,
- })}
-
-
- ),
- )}
-
-
-
-
-
-
-
-
-
-
- }
- >
-
-
-
-
- 0
- ? '#007eb1'
- : '#826a6a'
- }
- className="dropdown-popup-trigger"
- size="24px"
- />
- }
- >
-
-
-
-
-
-
- {map(
- this.state.index.order,
- (index, order) =>
- this.state.index.values[index].selected && (
-
- ),
- )}
-
-
-
-
-
-
- {this.state.items.map((item, order) => (
- ({
- id: index,
- type: this.state.index.values[index].type,
- })),
- (index) =>
- this.state.index.values[index.id].selected,
- )}
- onCut={this.cut}
- onCopy={this.copy}
- onDelete={this.delete}
- onOrderItem={this.onOrderItem}
- onMoveToTop={this.onMoveToTop}
- onMoveToBottom={this.onMoveToBottom}
- />
- ))}
-
-
-
-
-
-
-
-
-
- {this.state.isClient && (
-
-
-
-
- }
- />
-
- )}
-
-
- ) : (
-
- )}
- >
- ) : (
-
- );
- }
-}
-
-let dndContext;
-
-const DragDropConnector = (props) => {
- const { DragDropContext } = props.reactDnd;
- const HTML5Backend = props.reactDndHtml5Backend.default;
-
- const DndConnectedContents = React.useMemo(() => {
- if (!dndContext) {
- dndContext = DragDropContext(HTML5Backend);
- }
- return dndContext(Contents);
- }, [DragDropContext, HTML5Backend]);
-
- return ;
-};
-
-export const __test__ = compose(
- injectIntl,
- injectLazyLibs(['toastify', 'reactDnd']),
- connect(
- (store, props) => {
- return {
- token: store.userSession.token,
- items: store.search.items,
- sort: store.content.update.sort,
- index: store.content.updatecolumns.idx,
- breadcrumbs: store.breadcrumbs.items,
- total: store.search.total,
- searchRequest: {
- loading: store.search.loading,
- loaded: store.search.loaded,
- },
- pathname: props.location.pathname,
- action: store.clipboard.action,
- source: store.clipboard.source,
- clipboardRequest: store.clipboard.request,
- deleteRequest: store.content.delete,
- updateRequest: store.content.update,
- objectActions: store.actions.actions.object,
- orderRequest: store.content.order,
- };
- },
- {
- searchContent,
- cut,
- copy,
- copyContent,
- deleteContent,
- listActions,
- moveContent,
- orderContent,
- sortContent,
- updateColumnsContent,
- linkIntegrityCheck,
- getContent,
- },
- ),
-)(Contents);
-
-export default compose(
- injectIntl,
- connect(
- (store, props) => {
- return {
- token: store.userSession.token,
- items: store.search.items,
- sort: store.content.update.sort,
- index: store.content.updatecolumns.idx,
- breadcrumbs: store.breadcrumbs.items,
- total: store.search.total,
- searchRequest: {
- loading: store.search.loading,
- loaded: store.search.loaded,
- },
- pathname: props.location.pathname,
- action: store.clipboard.action,
- source: store.clipboard.source,
- clipboardRequest: store.clipboard.request,
- deleteRequest: store.content.delete,
- updateRequest: store.content.update,
- objectActions: store.actions.actions.object,
- orderRequest: store.content.order,
- };
- },
- {
- searchContent,
- cut,
- copy,
- copyContent,
- deleteContent,
- listActions,
- moveContent,
- orderContent,
- sortContent,
- updateColumnsContent,
- linkIntegrityCheck,
- getContent,
- },
- ),
- asyncConnect([
- {
- key: 'actions',
- // Dispatch async/await to make the operation synchronous, otherwise it returns
- // before the promise is resolved
- promise: async ({ location, store: { dispatch } }) =>
- await dispatch(listActions(getBaseUrl(location.pathname))),
- },
- ]),
- injectLazyLibs(['toastify', 'reactDnd', 'reactDndHtml5Backend']),
-)(DragDropConnector);
+/**
+ * Contents component.
+ * @module components/manage/Contents/Contents
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import { Portal } from 'react-portal';
+import { Link } from 'react-router-dom';
+import {
+ Button,
+ Confirm,
+ Container as SemanticContainer,
+ Divider,
+ Dropdown,
+ Menu,
+ Input,
+ Segment,
+ Table,
+ Loader,
+ Dimmer,
+} from 'semantic-ui-react';
+import {
+ concat,
+ filter,
+ find,
+ indexOf,
+ keys,
+ map,
+ mapValues,
+ pull,
+} from 'lodash';
+import move from 'lodash-move';
+import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
+import { asyncConnect } from '@plone/volto/helpers';
+import { flattenToAppURL } from '@plone/volto/helpers';
+
+import {
+ searchContent,
+ cut,
+ copy,
+ copyContent,
+ deleteContent,
+ listActions,
+ moveContent,
+ orderContent,
+ sortContent,
+ updateColumnsContent,
+ linkIntegrityCheck,
+ getContent,
+} from '@plone/volto/actions';
+import Indexes, { defaultIndexes } from '@plone/volto/constants/Indexes';
+import {
+ ContentsBreadcrumbs,
+ ContentsIndexHeader,
+ ContentsItem,
+ ContentsRenameModal,
+ ContentsUploadModal,
+ ContentsWorkflowModal,
+ ContentsTagsModal,
+ ContentsPropertiesModal,
+ Pagination,
+ Popup,
+ Toolbar,
+ Toast,
+ Icon,
+ Unauthorized,
+} from '@plone/volto/components';
+
+import { Helmet, getBaseUrl } from '@plone/volto/helpers';
+import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
+import config from '@plone/volto/registry';
+
+import backSVG from '@plone/volto/icons/back.svg';
+import cutSVG from '@plone/volto/icons/cut.svg';
+import deleteSVG from '@plone/volto/icons/delete.svg';
+import copySVG from '@plone/volto/icons/copy.svg';
+import tagSVG from '@plone/volto/icons/tag.svg';
+import renameSVG from '@plone/volto/icons/rename.svg';
+import semaphoreSVG from '@plone/volto/icons/semaphore.svg';
+import uploadSVG from '@plone/volto/icons/upload.svg';
+import propertiesSVG from '@plone/volto/icons/properties.svg';
+import pasteSVG from '@plone/volto/icons/paste.svg';
+import zoomSVG from '@plone/volto/icons/zoom.svg';
+import checkboxUncheckedSVG from '@plone/volto/icons/checkbox-unchecked.svg';
+import checkboxCheckedSVG from '@plone/volto/icons/checkbox-checked.svg';
+import checkboxIndeterminateSVG from '@plone/volto/icons/checkbox-indeterminate.svg';
+import configurationSVG from '@plone/volto/icons/configuration-app.svg';
+import sortDownSVG from '@plone/volto/icons/sort-down.svg';
+import sortUpSVG from '@plone/volto/icons/sort-up.svg';
+import downKeySVG from '@plone/volto/icons/down-key.svg';
+import moreSVG from '@plone/volto/icons/more.svg';
+import clearSVG from '@plone/volto/icons/clear.svg';
+
+const messages = defineMessages({
+ back: {
+ id: 'Back',
+ defaultMessage: 'Back',
+ },
+ contents: {
+ id: 'Contents',
+ defaultMessage: 'Contents',
+ },
+ copy: {
+ id: 'Copy',
+ defaultMessage: 'Copy',
+ },
+ cut: {
+ id: 'Cut',
+ defaultMessage: 'Cut',
+ },
+ error: {
+ id: "You can't paste this content here",
+ defaultMessage: "You can't paste this content here",
+ },
+ delete: {
+ id: 'Delete',
+ defaultMessage: 'Delete',
+ },
+ deleteConfirmSingleItem: {
+ id: 'Delete this item?',
+ defaultMessage: 'Delete this item?',
+ },
+ deleteConfirmMultipleItems: {
+ id: 'Delete selected items?',
+ defaultMessage: 'Delete selected items?',
+ },
+ deleteError: {
+ id: 'The item could not be deleted.',
+ defaultMessage: 'The item could not be deleted.',
+ },
+ loading: {
+ id: 'loading',
+ defaultMessage: 'Loading',
+ },
+ home: {
+ id: 'Home',
+ defaultMessage: 'Home',
+ },
+ filter: {
+ id: 'Filter…',
+ defaultMessage: 'Filter…',
+ },
+ messageCopied: {
+ id: 'Item(s) copied.',
+ defaultMessage: 'Item(s) copied.',
+ },
+ messageCut: {
+ id: 'Item(s) cut.',
+ defaultMessage: 'Item(s) cut.',
+ },
+ messageUpdate: {
+ id: 'Item(s) has been updated.',
+ defaultMessage: 'Item(s) has been updated.',
+ },
+ messageReorder: {
+ id: 'Item succesfully moved.',
+ defaultMessage: 'Item successfully moved.',
+ },
+ messagePasted: {
+ id: 'Item(s) pasted.',
+ defaultMessage: 'Item(s) pasted.',
+ },
+ messageWorkflowUpdate: {
+ id: 'Item(s) state has been updated.',
+ defaultMessage: 'Item(s) state has been updated.',
+ },
+ paste: {
+ id: 'Paste',
+ defaultMessage: 'Paste',
+ },
+ properties: {
+ id: 'Properties',
+ defaultMessage: 'Properties',
+ },
+ rearrangeBy: {
+ id: 'Rearrange items by…',
+ defaultMessage: 'Rearrange items by…',
+ },
+ rename: {
+ id: 'Rename',
+ defaultMessage: 'Rename',
+ },
+ select: {
+ id: 'Select…',
+ defaultMessage: 'Select…',
+ },
+ selected: {
+ id: '{count} selected',
+ defaultMessage: '{count} selected',
+ },
+ selectColumns: {
+ id: 'Select columns to show',
+ defaultMessage: 'Select columns to show',
+ },
+ sort: {
+ id: 'sort',
+ defaultMessage: 'sort',
+ },
+ state: {
+ id: 'State',
+ defaultMessage: 'State',
+ },
+ tags: {
+ id: 'Tags',
+ defaultMessage: 'Tags',
+ },
+ upload: {
+ id: 'Upload',
+ defaultMessage: 'Upload',
+ },
+ success: {
+ id: 'Success',
+ defaultMessage: 'Success',
+ },
+ publicationDate: {
+ id: 'Publication date',
+ defaultMessage: 'Publication date',
+ },
+ createdOn: {
+ id: 'Created on',
+ defaultMessage: 'Created on',
+ },
+ expirationDate: {
+ id: 'Expiration date',
+ defaultMessage: 'Expiration date',
+ },
+ id: {
+ id: 'ID',
+ defaultMessage: 'ID',
+ },
+ uid: {
+ id: 'UID',
+ defaultMessage: 'UID',
+ },
+ reviewState: {
+ id: 'Review state',
+ defaultMessage: 'Review state',
+ },
+ folder: {
+ id: 'Folder',
+ defaultMessage: 'Folder',
+ },
+ excludedFromNavigation: {
+ id: 'Excluded from navigation',
+ defaultMessage: 'Excluded from navigation',
+ },
+ objectSize: {
+ id: 'Object Size',
+ defaultMessage: 'Object Size',
+ },
+ lastCommentedDate: {
+ id: 'Last comment date',
+ defaultMessage: 'Last comment date',
+ },
+ totalComments: {
+ id: 'Total comments',
+ defaultMessage: 'Total comments',
+ },
+ creator: {
+ id: 'Creator',
+ defaultMessage: 'Creator',
+ },
+ endDate: {
+ id: 'End Date',
+ defaultMessage: 'End Date',
+ },
+ startDate: {
+ id: 'Start Date',
+ defaultMessage: 'Start Date',
+ },
+ all: {
+ id: 'All',
+ defaultMessage: 'All',
+ },
+});
+
+/**
+ * Contents class.
+ * @class Contents
+ * @extends Component
+ */
+class Contents extends Component {
+ /**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+ static propTypes = {
+ action: PropTypes.string,
+ source: PropTypes.arrayOf(PropTypes.string),
+ searchContent: PropTypes.func.isRequired,
+ cut: PropTypes.func.isRequired,
+ copy: PropTypes.func.isRequired,
+ copyContent: PropTypes.func.isRequired,
+ deleteContent: PropTypes.func.isRequired,
+ moveContent: PropTypes.func.isRequired,
+ orderContent: PropTypes.func.isRequired,
+ sortContent: PropTypes.func.isRequired,
+ updateColumnsContent: PropTypes.func.isRequired,
+ linkIntegrityCheck: PropTypes.func.isRequired,
+ clipboardRequest: PropTypes.shape({
+ loading: PropTypes.bool,
+ loaded: PropTypes.bool,
+ }).isRequired,
+ deleteRequest: PropTypes.shape({
+ loading: PropTypes.bool,
+ loaded: PropTypes.bool,
+ }).isRequired,
+ updateRequest: PropTypes.shape({
+ loading: PropTypes.bool,
+ loaded: PropTypes.bool,
+ }).isRequired,
+ searchRequest: PropTypes.shape({
+ loading: PropTypes.bool,
+ loaded: PropTypes.bool,
+ }).isRequired,
+ items: PropTypes.arrayOf(
+ PropTypes.shape({
+ '@id': PropTypes.string,
+ '@type': PropTypes.string,
+ title: PropTypes.string,
+ description: PropTypes.string,
+ }),
+ ),
+ breadcrumbs: PropTypes.arrayOf(
+ PropTypes.shape({
+ title: PropTypes.string,
+ url: PropTypes.string,
+ }),
+ ).isRequired,
+ total: PropTypes.number.isRequired,
+ pathname: PropTypes.string.isRequired,
+ };
+
+ /**
+ * Default properties.
+ * @property {Object} defaultProps Default properties.
+ * @static
+ */
+ static defaultProps = {
+ items: [],
+ action: null,
+ source: null,
+ index: {
+ order: keys(Indexes),
+ values: mapValues(Indexes, (value, key) => ({
+ ...value,
+ selected: indexOf(defaultIndexes, key) !== -1,
+ })),
+ selectedCount: defaultIndexes.length + 1,
+ },
+ };
+
+ /**
+ * Constructor
+ * @method constructor
+ * @param {Object} props Component properties
+ * @constructs ContentsComponent
+ */
+ constructor(props) {
+ super(props);
+ this.onDeselect = this.onDeselect.bind(this);
+ this.onSelect = this.onSelect.bind(this);
+ this.onSelectAll = this.onSelectAll.bind(this);
+ this.onSelectIndex = this.onSelectIndex.bind(this);
+ this.onSelectNone = this.onSelectNone.bind(this);
+ this.onDeleteOk = this.onDeleteOk.bind(this);
+ this.onDeleteCancel = this.onDeleteCancel.bind(this);
+ this.onUploadOk = this.onUploadOk.bind(this);
+ this.onUploadCancel = this.onUploadCancel.bind(this);
+ this.onRenameOk = this.onRenameOk.bind(this);
+ this.onRenameCancel = this.onRenameCancel.bind(this);
+ this.onTagsOk = this.onTagsOk.bind(this);
+ this.onTagsCancel = this.onTagsCancel.bind(this);
+ this.onPropertiesOk = this.onPropertiesOk.bind(this);
+ this.onPropertiesCancel = this.onPropertiesCancel.bind(this);
+ this.onWorkflowOk = this.onWorkflowOk.bind(this);
+ this.onWorkflowCancel = this.onWorkflowCancel.bind(this);
+ this.onChangeFilter = this.onChangeFilter.bind(this);
+ this.onChangePage = this.onChangePage.bind(this);
+ this.onChangePageSize = this.onChangePageSize.bind(this);
+ this.onOrderIndex = this.onOrderIndex.bind(this);
+ this.onOrderItem = this.onOrderItem.bind(this);
+ this.onSortItems = this.onSortItems.bind(this);
+ this.onMoveToTop = this.onMoveToTop.bind(this);
+ this.onChangeSelected = this.onChangeSelected.bind(this);
+ this.onMoveToBottom = this.onMoveToBottom.bind(this);
+ this.cut = this.cut.bind(this);
+ this.copy = this.copy.bind(this);
+ this.delete = this.delete.bind(this);
+ this.upload = this.upload.bind(this);
+ this.rename = this.rename.bind(this);
+ this.tags = this.tags.bind(this);
+ this.properties = this.properties.bind(this);
+ this.workflow = this.workflow.bind(this);
+ this.paste = this.paste.bind(this);
+ this.fetchContents = this.fetchContents.bind(this);
+ this.orderTimeout = null;
+ this.deleteItemsToShowThreshold = 10;
+
+ this.state = {
+ selected: [],
+ showDelete: false,
+ showUpload: false,
+ showRename: false,
+ showTags: false,
+ showProperties: false,
+ showWorkflow: false,
+ itemsToDelete: [],
+ containedItemsToDelete: [],
+ brokenReferences: 0,
+ breaches: [],
+ showAllItemsToDelete: true,
+ items: this.props.items,
+ filter: '',
+ currentPage: 0,
+ pageSize: 50,
+ index: this.props.index || {
+ order: keys(Indexes),
+ values: mapValues(Indexes, (value, key) => ({
+ ...value,
+ selected: indexOf(defaultIndexes, key) !== -1,
+ })),
+ selectedCount: defaultIndexes.length + 1,
+ },
+ sort_on: this.props.sort?.on || 'getObjPositionInParent',
+ sort_order: this.props.sort?.order || 'ascending',
+ isClient: false,
+ linkIntegrityBreakages: [],
+ };
+ this.filterTimeout = null;
+ }
+
+ /**
+ * Component did mount
+ * @method componentDidMount
+ * @returns {undefined}
+ */
+ componentDidMount() {
+ this.fetchContents();
+ this.setState({ isClient: true });
+ }
+ async componentDidUpdate(_, prevState) {
+ if (
+ this.state.itemsToDelete !== prevState.itemsToDelete &&
+ this.state.itemsToDelete.length > 0
+ ) {
+ const linkintegrityInfo = await this.props.linkIntegrityCheck(
+ map(this.state.itemsToDelete, (item) => this.getFieldById(item, 'UID')),
+ );
+ const containedItems = linkintegrityInfo
+ .map((result) => result.items_total ?? 0)
+ .reduce((acc, value) => acc + value, 0);
+ const breaches = linkintegrityInfo.flatMap((result) =>
+ result.breaches.map((source) => ({
+ source: source,
+ target: result,
+ })),
+ );
+ const source_by_uid = breaches.reduce(
+ (acc, value) => acc.set(value.source.uid, value.source),
+ new Map(),
+ );
+ const by_source = breaches.reduce((acc, value) => {
+ if (acc.get(value.source.uid) === undefined) {
+ acc.set(value.source.uid, new Set());
+ }
+ acc.get(value.source.uid).add(value.target);
+ return acc;
+ }, new Map());
+
+ this.setState({
+ containedItemsToDelete: containedItems,
+ brokenReferences: by_source.size,
+ linksAndReferencesViewLink: linkintegrityInfo.length
+ ? linkintegrityInfo[0]['@id'] + '/links-to-item'
+ : null,
+ breaches: Array.from(by_source, (entry) => ({
+ source: source_by_uid.get(entry[0]),
+ targets: Array.from(entry[1]),
+ })),
+ showAllItemsToDelete:
+ this.state.itemsToDelete.length < this.deleteItemsToShowThreshold,
+ });
+ }
+ }
+
+ /**
+ * Component will receive props
+ * @method componentWillReceiveProps
+ * @param {Object} nextProps Next properties
+ * @returns {undefined}
+ */
+ UNSAFE_componentWillReceiveProps(nextProps) {
+ if (
+ (this.props.clipboardRequest.loading &&
+ nextProps.clipboardRequest.loaded) ||
+ (this.props.deleteRequest.loading && nextProps.deleteRequest.loaded) ||
+ (this.props.updateRequest.loading && nextProps.updateRequest.loaded)
+ ) {
+ this.fetchContents(nextProps.pathname);
+ }
+ if (this.props.updateRequest.loading && nextProps.updateRequest.loaded) {
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+ if (this.props.pathname !== nextProps.pathname) {
+ // Refetching content to sync the current object in the toolbar
+ this.props.getContent(getBaseUrl(nextProps.pathname));
+ this.setState(
+ {
+ currentPage: 0,
+ },
+ () =>
+ this.setState({ filter: '' }, () =>
+ this.fetchContents(nextProps.pathname),
+ ),
+ );
+ }
+ if (this.props.searchRequest.loading && nextProps.searchRequest.loaded) {
+ this.setState({
+ items: nextProps.items,
+ });
+ }
+ if (
+ this.props.clipboardRequest.loading &&
+ nextProps.clipboardRequest.error
+ ) {
+ this.props.toastify.toast.error(
+ ,
+ );
+ }
+
+ if (
+ this.props.clipboardRequest.loading &&
+ nextProps.clipboardRequest.loaded
+ ) {
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+
+ if (this.props.deleteRequest.loading && nextProps.deleteRequest.error) {
+ this.props.toastify.toast.error(
+ ,
+ );
+ }
+
+ if (this.props.orderRequest.loading && nextProps.orderRequest.loaded) {
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+ }
+
+ /**
+ * On deselect handler
+ * @method onDeselect
+ * @param {object} event Event object
+ * @param {string} value Value
+ * @returns {undefined}
+ */
+ onDeselect(event, { value }) {
+ this.setState({
+ selected: pull(this.state.selected, value),
+ });
+ }
+
+ /**
+ * On select handler
+ * @method onSelect
+ * @param {object} event Event object
+ * @returns {undefined}
+ */
+ onSelect(event, id) {
+ if (indexOf(this.state.selected, id) === -1) {
+ this.setState({
+ selected: concat(this.state.selected, id),
+ });
+ } else {
+ this.setState({
+ selected: pull(this.state.selected, id),
+ });
+ }
+ }
+
+ /**
+ * On select all handler
+ * @method onSelectAll
+ * @returns {undefined}
+ */
+ onSelectAll() {
+ this.setState({
+ selected: map(this.state.items, (item) => item['@id']),
+ });
+ }
+
+ /**
+ * On select none handler
+ * @method onSelectNone
+ * @returns {undefined}
+ */
+ onSelectNone() {
+ this.setState({
+ selected: [],
+ });
+ }
+
+ /**
+ * On select index
+ * @method onSelectIndex
+ * @param {object} event Event object.
+ * @param {string} value Index value.
+ * @returns {undefined}
+ */
+ onSelectIndex(event, { value }) {
+ let newIndex = {
+ ...this.state.index,
+ selectedCount:
+ this.state.index.selectedCount +
+ (this.state.index.values[value].selected ? -1 : 1),
+ values: mapValues(this.state.index.values, (indexValue, indexKey) => ({
+ ...indexValue,
+ selected:
+ indexKey === value ? !indexValue.selected : indexValue.selected,
+ })),
+ };
+ this.setState({
+ index: newIndex,
+ });
+ this.props.updateColumnsContent(getBaseUrl(this.props.pathname), newIndex);
+ }
+
+ /**
+ * On change filter
+ * @method onChangeFilter
+ * @param {object} event Event object.
+ * @param {string} value Filter value.
+ * @returns {undefined}
+ */
+ onChangeFilter(event, { value }) {
+ const self = this;
+ clearTimeout(self.filterTimeout);
+ this.setState(
+ {
+ filter: value,
+ },
+ () => {
+ self.filterTimeout = setTimeout(() => {
+ self.fetchContents();
+ }, 200);
+ },
+ );
+ }
+
+ /**
+ * On change selected values (Filter)
+ * @method onChangeSelected
+ * @param {object} event Event object.
+ * @param {string} value Filter value.
+ * @returns {undefined}
+ */
+ onChangeSelected(event, { value }) {
+ event.stopPropagation();
+ const { items, selected } = this.state;
+
+ const filteredItems = filter(selected, (selectedItem) =>
+ find(items, (item) => item['@id'] === selectedItem)
+ .title.toLowerCase()
+ .includes(value.toLowerCase()),
+ );
+
+ this.setState({
+ filteredItems,
+ selectedMenuFilter: value,
+ });
+ }
+
+ /**
+ * On change page
+ * @method onChangePage
+ * @param {object} event Event object.
+ * @param {string} value Page value.
+ * @returns {undefined}
+ */
+ onChangePage(event, { value }) {
+ this.setState(
+ {
+ currentPage: value,
+ },
+ () => this.fetchContents(),
+ );
+ }
+
+ /**
+ * On change page size
+ * @method onChangePageSize
+ * @param {object} event Event object.
+ * @param {string} value Page size value.
+ * @returns {undefined}
+ */
+ onChangePageSize(event, { value }) {
+ this.setState(
+ {
+ pageSize: value,
+ currentPage: 0,
+ },
+ () => this.fetchContents(),
+ );
+ }
+
+ /**
+ * On order index
+ * @method onOrderIndex
+ * @param {number} index Index
+ * @param {number} delta Delta
+ * @returns {undefined}
+ */
+ onOrderIndex(index, delta) {
+ this.setState({
+ index: {
+ ...this.state.index,
+ order: move(this.state.index.order, index, index + delta),
+ },
+ });
+ this.props.updateColumnsContent(
+ getBaseUrl(this.props.pathname),
+ this.state.index,
+ );
+ }
+
+ /**
+ * On order item
+ * @method onOrderItem
+ * @param {string} id Item id
+ * @param {number} itemIndex Item index
+ * @param {number} delta Delta
+ * @returns {undefined}
+ */
+ onOrderItem(id, itemIndex, delta, backend) {
+ if (backend) {
+ this.props.orderContent(
+ getBaseUrl(this.props.pathname),
+ id.replace(/^.*\//, ''),
+ delta,
+ );
+ } else {
+ this.setState({
+ items: move(this.state.items, itemIndex, itemIndex + delta),
+ });
+ }
+ }
+
+ /**
+ * On sort items
+ * @method onSortItems
+ * @param {object} event Event object
+ * @param {string} value Item index
+ * @returns {undefined}
+ */
+ onSortItems(event, { value }) {
+ const values = value.split('|');
+ this.setState({
+ sort_on: values[0],
+ sort_order: values[1],
+ });
+ this.props.sortContent(
+ getBaseUrl(this.props.pathname),
+ values[0],
+ values[1],
+ );
+ }
+
+ /**
+ * On move to top
+ * @method onMoveToTop
+ * @param {object} event Event object
+ * @param {string} value Item index
+ * @returns {undefined}
+ */
+ onMoveToTop(event, { value }) {
+ const id = this.state.items[value]['@id'];
+ this.props
+ .orderContent(
+ getBaseUrl(this.props.pathname),
+ id.replace(/^.*\//, ''),
+ 'top',
+ )
+ .then(() => {
+ this.setState(
+ {
+ currentPage: 0,
+ },
+ () => this.fetchContents(),
+ );
+ });
+ }
+
+ /**
+ * On move to bottom
+ * @method onMoveToBottom
+ * @param {object} event Event object
+ * @param {string} value Item index
+ * @returns {undefined}
+ */
+ onMoveToBottom(event, { value }) {
+ const id = this.state.items[value]['@id'];
+ this.props
+ .orderContent(
+ getBaseUrl(this.props.pathname),
+ id.replace(/^.*\//, ''),
+ 'bottom',
+ )
+ .then(() => {
+ this.setState(
+ {
+ currentPage: 0,
+ },
+ () => this.fetchContents(),
+ );
+ });
+ }
+
+ /**
+ * On delete ok
+ * @method onDeleteOk
+ * @returns {undefined}
+ */
+ onDeleteOk() {
+ this.props.deleteContent(this.state.itemsToDelete);
+ this.setState({
+ showDelete: false,
+ itemsToDelete: [],
+ selected: [],
+ });
+ }
+
+ /**
+ * On delete cancel
+ * @method onDeleteCancel
+ * @returns {undefined}
+ */
+ onDeleteCancel() {
+ this.setState({
+ showDelete: false,
+ itemsToDelete: [],
+ });
+ }
+
+ /**
+ * On upload ok
+ * @method onUploadOk
+ * @returns {undefined}
+ */
+ onUploadOk() {
+ this.fetchContents();
+ this.setState({
+ showUpload: false,
+ });
+ }
+
+ /**
+ * On upload cancel
+ * @method onUploadCancel
+ * @returns {undefined}
+ */
+ onUploadCancel() {
+ this.setState({
+ showUpload: false,
+ });
+ }
+
+ /**
+ * On rename ok
+ * @method onRenameOk
+ * @returns {undefined}
+ */
+ onRenameOk() {
+ this.setState({
+ showRename: false,
+ selected: [],
+ });
+ }
+
+ /**
+ * On rename cancel
+ * @method onRenameCancel
+ * @returns {undefined}
+ */
+ onRenameCancel() {
+ this.setState({
+ showRename: false,
+ });
+ }
+
+ /**
+ * On tags ok
+ * @method onTagsOk
+ * @returns {undefined}
+ */
+ onTagsOk() {
+ this.setState({
+ showTags: false,
+ selected: [],
+ });
+ }
+
+ /**
+ * On tags cancel
+ * @method onTagsCancel
+ * @returns {undefined}
+ */
+ onTagsCancel() {
+ this.setState({
+ showTags: false,
+ });
+ }
+
+ /**
+ * On properties ok
+ * @method onPropertiesOk
+ * @returns {undefined}
+ */
+ onPropertiesOk() {
+ this.setState({
+ showProperties: false,
+ selected: [],
+ });
+ }
+
+ /**
+ * On properties cancel
+ * @method onPropertiesCancel
+ * @returns {undefined}
+ */
+ onPropertiesCancel() {
+ this.setState({
+ showProperties: false,
+ });
+ }
+
+ /**
+ * On workflow ok
+ * @method onWorkflowOk
+ * @returns {undefined}
+ */
+ onWorkflowOk() {
+ this.fetchContents();
+ this.setState({
+ showWorkflow: false,
+ selected: [],
+ });
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+
+ /**
+ * On workflow cancel
+ * @method onWorkflowCancel
+ * @returns {undefined}
+ */
+ onWorkflowCancel() {
+ this.setState({
+ showWorkflow: false,
+ });
+ }
+
+ /**
+ * Get field by id
+ * @method getFieldById
+ * @param {string} id Id of object
+ * @param {string} field Field of object
+ * @returns {string} Field of object
+ */
+ getFieldById(id, field) {
+ const item = find(this.state.items, { '@id': id });
+ return item ? item[field] : '';
+ }
+
+ /**
+ * Fetch contents handler
+ * @method fetchContents
+ * @param {string} pathname Pathname to fetch contents.
+ * @returns {undefined}
+ */
+ fetchContents(pathname) {
+ if (this.state.pageSize === this.props.intl.formatMessage(messages.all)) {
+ //'All'
+ this.props.searchContent(getBaseUrl(pathname || this.props.pathname), {
+ 'path.depth': 1,
+ sort_on: this.state.sort_on,
+ sort_order: this.state.sort_order,
+ metadata_fields: '_all',
+ b_size: 100000000,
+ show_inactive: true,
+ ...(this.state.filter && { SearchableText: `${this.state.filter}*` }),
+ });
+ } else {
+ this.props.searchContent(getBaseUrl(pathname || this.props.pathname), {
+ 'path.depth': 1,
+ sort_on: this.state.sort_on,
+ sort_order: this.state.sort_order,
+ metadata_fields: '_all',
+ ...(this.state.filter && { SearchableText: `${this.state.filter}*` }),
+ b_size: this.state.pageSize,
+ b_start: this.state.currentPage * this.state.pageSize,
+ show_inactive: true,
+ });
+ }
+ }
+
+ /**
+ * Cut handler
+ * @method cut
+ * @param {Object} event Event object.
+ * @param {string} value Value of the event.
+ * @returns {undefined}
+ */
+ cut(event, { value }) {
+ this.props.cut(value ? [value] : this.state.selected);
+ this.onSelectNone();
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+
+ /**
+ * Copy handler
+ * @method copy
+ * @param {Object} event Event object.
+ * @param {string} value Value of the event.
+ * @returns {undefined}
+ */
+ copy(event, { value }) {
+ this.props.copy(value ? [value] : this.state.selected);
+ this.onSelectNone();
+ this.props.toastify.toast.success(
+ ,
+ );
+ }
+
+ /**
+ * Delete handler
+ * @method delete
+ * @param {Object} event Event object.
+ * @param {string} value Value of the event.
+ * @returns {undefined}
+ */
+ delete(event, { value }) {
+ this.setState({
+ showDelete: true,
+ itemsToDelete: value ? [value] : this.state.selected,
+ });
+ }
+
+ /**
+ * Upload handler
+ * @method upload
+ * @returns {undefined}
+ */
+ upload() {
+ this.setState({
+ showUpload: true,
+ });
+ }
+
+ /**
+ * Rename handler
+ * @method rename
+ * @returns {undefined}
+ */
+ rename() {
+ this.setState({
+ showRename: true,
+ });
+ }
+
+ /**
+ * Tags handler
+ * @method tags
+ * @returns {undefined}
+ */
+ tags() {
+ this.setState({
+ showTags: true,
+ });
+ }
+
+ /**
+ * Properties handler
+ * @method properties
+ * @returns {undefined}
+ */
+ properties() {
+ this.setState({
+ showProperties: true,
+ });
+ }
+
+ /**
+ * Workflow handler
+ * @method workflow
+ * @returns {undefined}
+ */
+ workflow() {
+ this.setState({
+ showWorkflow: true,
+ });
+ }
+
+ /**
+ * Paste handler
+ * @method paste
+ * @returns {undefined}
+ */
+ paste() {
+ if (this.props.action === 'copy') {
+ this.props.copyContent(
+ this.props.source,
+ getBaseUrl(this.props.pathname),
+ );
+ }
+ if (this.props.action === 'cut') {
+ this.props.moveContent(
+ this.props.source,
+ getBaseUrl(this.props.pathname),
+ );
+ }
+ }
+
+ /**
+ * Render method.
+ * @method render
+ * @returns {string} Markup for the component.
+ */
+ render() {
+ const selected = this.state.selected.length > 0;
+ const filteredItems = this.state.filteredItems || this.state.selected;
+ const path = getBaseUrl(this.props.pathname);
+ const folderContentsAction = find(this.props.objectActions, {
+ id: 'folderContents',
+ });
+ const loading =
+ (this.props.clipboardRequest?.loading &&
+ !this.props.clipboardRequest?.error) ||
+ (this.props.deleteRequest?.loading && !this.props.deleteRequest?.error) ||
+ (this.props.updateRequest?.loading && !this.props.updateRequest?.error) ||
+ (this.props.orderRequest?.loading && !this.props.orderRequest?.error) ||
+ (this.props.searchRequest?.loading && !this.props.searchRequest?.error);
+
+ const Container =
+ config.getComponent({ name: 'Container' }).component || SemanticContainer;
+
+ return this.props.token && this.props.objectActions?.length > 0 ? (
+ <>
+ {folderContentsAction ? (
+
+
+
+
+ {this.props.intl.formatMessage(messages.loading)}
+
+
+
+
+
+
+
+ {this.state.itemsToDelete.length > 1 ? (
+ this.state.containedItemsToDelete > 0 ? (
+ <>
+
+ {this.state.containedItemsToDelete}
+
+ ),
+ variation: (
+
+ {this.state.containedItemsToDelete ===
+ 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+ {this.state.brokenReferences > 0 && (
+ <>
+
+
+ {this.state.brokenReferences}
+
+ ),
+ variation: (
+
+ {this.state.brokenReferences === 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+ >
+ )}
+ >
+ ) : (
+ <>
+ {this.state.brokenReferences > 0 && (
+ <>
+
+ {this.state.brokenReferences}
+
+ ),
+ variation: (
+
+ {this.state.brokenReferences === 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+ >
+ )}
+ >
+ )
+ ) : this.state.containedItemsToDelete > 0 ? (
+ <>
+
+ {this.state.containedItemsToDelete}
+
+ ),
+ variation: (
+
+ {this.state.containedItemsToDelete === 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+ {this.state.brokenReferences > 0 && (
+ <>
+
+ {this.state.brokenReferences}
+ ),
+ variation: (
+
+ {this.state.brokenReferences === 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+
+
+
+ {this.state.breaches.map((breach) => (
+ -
+
+ {breach.source.title}
+ {' '}
+ refers to{' '}
+ {breach.targets
+ .map((target) => (
+
+ {target.title}
+
+ ))
+ .reduce((result, item) => (
+ <>
+ {result}, {item}
+ >
+ ))}
+
+ ))}
+
+ {this.state.linksAndReferencesViewLink && (
+
+
+
+ )}
+
+ >
+ )}
+ >
+ ) : this.state.brokenReferences > 0 ? (
+ <>
+ {this.state.brokenReferences}
+ ),
+ variation: (
+
+ {this.state.brokenReferences === 1 ? (
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+
+
+
+ {this.state.breaches.map((breach) => (
+ -
+
+ {breach.source.title}
+ {' '}
+ refers to{' '}
+ {breach.targets
+ .map((target) => (
+
+ {target.title}
+
+ ))
+ .reduce((result, item) => (
+ <>
+ {result}, {item}
+ >
+ ))}
+
+ ))}
+
+ {this.state.linksAndReferencesViewLink && (
+
+
+
+ )}
+
+ >
+ ) : null}
+
+ }
+ onCancel={this.onDeleteCancel}
+ onConfirm={this.onDeleteOk}
+ size="medium"
+ />
+
+ ({
+ url: item,
+ title: this.getFieldById(item, 'title'),
+ id: this.getFieldById(item, 'id'),
+ }))}
+ />
+ ({
+ url: item,
+ subjects: this.getFieldById(item, 'Subject'),
+ }))}
+ />
+
+ {this.state.showWorkflow && (
+
+ )}
+
+
+
+
+
+
+ }
+ className="right floating selectIndex"
+ >
+
+
+
+ {map(
+ filter(
+ this.state.index.order,
+ (index) => index !== 'sortable_title',
+ ),
+ (index) => (
+
+ {this.state.index.values[index].selected ? (
+
+ ) : (
+
+ )}
+
+ {' '}
+ {this.props.intl.formatMessage({
+ id: this.state.index.values[index]
+ .label,
+ defaultMessage:
+ this.state.index.values[index].label,
+ })}
+
+
+ ),
+ )}
+
+
+
+
+
+
+
+
+
+
+ }
+ >
+
+
+
+
+ 0
+ ? '#007eb1'
+ : '#826a6a'
+ }
+ className="dropdown-popup-trigger"
+ size="24px"
+ />
+ }
+ >
+
+
+
+
+
+
+ {map(
+ this.state.index.order,
+ (index, order) =>
+ this.state.index.values[index].selected && (
+
+ ),
+ )}
+
+
+
+
+
+
+ {this.state.items.map((item, order) => (
+ ({
+ id: index,
+ type: this.state.index.values[index].type,
+ })),
+ (index) =>
+ this.state.index.values[index.id].selected,
+ )}
+ onCut={this.cut}
+ onCopy={this.copy}
+ onDelete={this.delete}
+ onOrderItem={this.onOrderItem}
+ onMoveToTop={this.onMoveToTop}
+ onMoveToBottom={this.onMoveToBottom}
+ />
+ ))}
+
+
+
+
+
+
+
+
+
+ {this.state.isClient && (
+
+
+
+
+ }
+ />
+
+ )}
+
+
+ ) : (
+
+ )}
+ >
+ ) : (
+
+ );
+ }
+}
+
+let dndContext;
+
+const DragDropConnector = (props) => {
+ const { DragDropContext } = props.reactDnd;
+ const HTML5Backend = props.reactDndHtml5Backend.default;
+
+ const DndConnectedContents = React.useMemo(() => {
+ if (!dndContext) {
+ dndContext = DragDropContext(HTML5Backend);
+ }
+ return dndContext(Contents);
+ }, [DragDropContext, HTML5Backend]);
+
+ return ;
+};
+
+export const __test__ = compose(
+ injectIntl,
+ injectLazyLibs(['toastify', 'reactDnd']),
+ connect(
+ (store, props) => {
+ return {
+ token: store.userSession.token,
+ items: store.search.items,
+ sort: store.content.update.sort,
+ index: store.content.updatecolumns.idx,
+ breadcrumbs: store.breadcrumbs.items,
+ total: store.search.total,
+ searchRequest: {
+ loading: store.search.loading,
+ loaded: store.search.loaded,
+ },
+ pathname: props.location.pathname,
+ action: store.clipboard.action,
+ source: store.clipboard.source,
+ clipboardRequest: store.clipboard.request,
+ deleteRequest: store.content.delete,
+ updateRequest: store.content.update,
+ objectActions: store.actions.actions.object,
+ orderRequest: store.content.order,
+ };
+ },
+ {
+ searchContent,
+ cut,
+ copy,
+ copyContent,
+ deleteContent,
+ listActions,
+ moveContent,
+ orderContent,
+ sortContent,
+ updateColumnsContent,
+ linkIntegrityCheck,
+ getContent,
+ },
+ ),
+)(Contents);
+
+export default compose(
+ injectIntl,
+ connect(
+ (store, props) => {
+ return {
+ token: store.userSession.token,
+ items: store.search.items,
+ sort: store.content.update.sort,
+ index: store.content.updatecolumns.idx,
+ breadcrumbs: store.breadcrumbs.items,
+ total: store.search.total,
+ searchRequest: {
+ loading: store.search.loading,
+ loaded: store.search.loaded,
+ },
+ pathname: props.location.pathname,
+ action: store.clipboard.action,
+ source: store.clipboard.source,
+ clipboardRequest: store.clipboard.request,
+ deleteRequest: store.content.delete,
+ updateRequest: store.content.update,
+ objectActions: store.actions.actions.object,
+ orderRequest: store.content.order,
+ };
+ },
+ {
+ searchContent,
+ cut,
+ copy,
+ copyContent,
+ deleteContent,
+ listActions,
+ moveContent,
+ orderContent,
+ sortContent,
+ updateColumnsContent,
+ linkIntegrityCheck,
+ getContent,
+ },
+ ),
+ asyncConnect([
+ {
+ key: 'actions',
+ // Dispatch async/await to make the operation synchronous, otherwise it returns
+ // before the promise is resolved
+ promise: async ({ location, store: { dispatch } }) =>
+ await dispatch(listActions(getBaseUrl(location.pathname))),
+ },
+ ]),
+ injectLazyLibs(['toastify', 'reactDnd', 'reactDndHtml5Backend']),
+)(DragDropConnector);
diff --git a/src/components/manage/Contents/__snapshots__/Contents.test.jsx.snap b/src/components/manage/Contents/__snapshots__/Contents.test.jsx.snap
index 968280ce12..a348d4c3db 100644
--- a/src/components/manage/Contents/__snapshots__/Contents.test.jsx.snap
+++ b/src/components/manage/Contents/__snapshots__/Contents.test.jsx.snap
@@ -2,6 +2,7 @@
exports[`Contents renders a folder contents view component 1`] = `