Add delete behavior

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-14 13:55:40 +02:00
parent 787d4e5a41
commit 81bdbab104
11 changed files with 247 additions and 530 deletions

View File

@ -13,12 +13,7 @@ const reducers = {
})),
'content-manager_listView': jest.fn(() => ({
data: [],
didDeleteData: false,
entriesToDelete: [],
isLoading: true,
showModalConfirmButtonLoading: false,
showWarningDelete: false,
showWarningDeleteAll: false,
contentType: {},
initialDisplayedHeaders: [],
displayedHeaders: [],

View File

@ -0,0 +1,77 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { Dialog, DialogBody, DialogFooter } from '@strapi/parts/Dialog';
import { Stack } from '@strapi/parts/Stack';
import { Row } from '@strapi/parts/Row';
import { Text } from '@strapi/parts/Text';
import { Button } from '@strapi/parts/Button';
import AlertWarningIcon from '@strapi/icons/AlertWarningIcon';
import DeleteIcon from '@strapi/icons/DeleteIcon';
import InjectionZoneList from '../../InjectionZoneList';
const ConfirmDialogDelete = ({ isConfirmButtonLoading, isOpen, onToggleDialog, onConfirm }) => {
const { formatMessage } = useIntl();
return (
<Dialog
onClose={onToggleDialog}
title={formatMessage({
id: 'app.components.ConfirmDialog.title',
defaultMessage: 'Confirmation',
})}
labelledBy="confirmation"
describedBy="confirm-description"
isOpen={isOpen}
>
<DialogBody icon={<AlertWarningIcon />}>
<Stack size={2}>
<Row justifyContent="center">
<Text id="confirm-description">
{formatMessage({
id: 'components.popUpWarning.message',
defaultMessage: 'Are you sure you want to delete this?',
})}
</Text>
</Row>
<Row>
<InjectionZoneList area="contentManager.listView.deleteModalAdditionalInfos" />
</Row>
</Stack>
</DialogBody>
<DialogFooter
startAction={
<Button onClick={onToggleDialog} variant="tertiary">
{formatMessage({
id: 'app.components.Button.cancel',
defaultMessage: 'Cancel',
})}
</Button>
}
endAction={
<Button
onClick={onConfirm}
variant="danger-light"
startIcon={<DeleteIcon />}
id="confirm-delete"
loading={isConfirmButtonLoading}
>
{formatMessage({
id: 'app.components.Button.confirm',
defaultMessage: 'Confirm',
})}
</Button>
}
/>
</Dialog>
);
};
ConfirmDialogDelete.propTypes = {
isConfirmButtonLoading: PropTypes.bool.isRequired,
isOpen: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onToggleDialog: PropTypes.func.isRequired,
};
export default ConfirmDialogDelete;

View File

@ -0,0 +1,78 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { Dialog, DialogBody, DialogFooter } from '@strapi/parts/Dialog';
import { Stack } from '@strapi/parts/Stack';
import { Row } from '@strapi/parts/Row';
import { Text } from '@strapi/parts/Text';
import { Button } from '@strapi/parts/Button';
import AlertWarningIcon from '@strapi/icons/AlertWarningIcon';
import DeleteIcon from '@strapi/icons/DeleteIcon';
import InjectionZoneList from '../../InjectionZoneList';
import { getTrad } from '../../../utils';
const ConfirmDialogDeleteAll = ({ isConfirmButtonLoading, isOpen, onToggleDialog, onConfirm }) => {
const { formatMessage } = useIntl();
return (
<Dialog
onClose={onToggleDialog}
title={formatMessage({
id: 'app.components.ConfirmDialog.title',
defaultMessage: 'Confirmation',
})}
labelledBy="confirmation"
describedBy="confirm-description"
isOpen={isOpen}
>
<DialogBody icon={<AlertWarningIcon />}>
<Stack size={2}>
<Row justifyContent="center">
<Text id="confirm-description">
{formatMessage({
id: getTrad('popUpWarning.bodyMessage.contentType.delete.all'),
defaultMessage: 'Are you sure you want to delete these entries?',
})}
</Text>
</Row>
<Row>
<InjectionZoneList area="contentManager.listView.deleteModalAdditionalInfos" />
</Row>
</Stack>
</DialogBody>
<DialogFooter
startAction={
<Button onClick={onToggleDialog} variant="tertiary">
{formatMessage({
id: 'app.components.Button.cancel',
defaultMessage: 'Cancel',
})}
</Button>
}
endAction={
<Button
onClick={onConfirm}
variant="danger-light"
startIcon={<DeleteIcon />}
id="confirm-delete"
loading={isConfirmButtonLoading}
>
{formatMessage({
id: 'app.components.Button.confirm',
defaultMessage: 'Confirm',
})}
</Button>
}
/>
</Dialog>
);
};
ConfirmDialogDeleteAll.propTypes = {
isConfirmButtonLoading: PropTypes.bool.isRequired,
isOpen: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onToggleDialog: PropTypes.func.isRequired,
};
export default ConfirmDialogDeleteAll;

View File

@ -7,6 +7,8 @@ import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
import { getTrad } from '../../utils';
import State from '../State';
import TableRows from './TableRows';
import ConfirmDialogDeleteAll from './ConfirmDialogDeleteAll';
import ConfirmDialogDelete from './ConfirmDialogDelete';
const DynamicTable = ({
canCreate,
@ -14,6 +16,8 @@ const DynamicTable = ({
contentTypeName,
isBulkable,
isLoading,
onConfirmDelete,
onConfirmDeleteAll,
layout,
rows,
}) => {
@ -55,9 +59,12 @@ const DynamicTable = ({
return (
<Table
components={{ ConfirmDialogDelete, ConfirmDialogDeleteAll }}
contentType={contentTypeName}
isLoading={isLoading}
headers={tableHeaders}
onConfirmDelete={onConfirmDelete}
onConfirmDeleteAll={onConfirmDeleteAll}
rows={rows}
withBulkActions
withMainAction={canDelete && isBulkable}
@ -94,6 +101,8 @@ DynamicTable.propTypes = {
settings: PropTypes.object.isRequired,
}).isRequired,
}).isRequired,
onConfirmDelete: PropTypes.func.isRequired,
onConfirmDeleteAll: PropTypes.func.isRequired,
rows: PropTypes.array.isRequired,
};

View File

@ -1,29 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Box } from '@strapi/parts/Box';
import { useInjectionZone } from '../../../shared/hooks';
const List = styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
`;
const ListItem = styled.li`
font-size: ${p => p.theme.main.sizes.fonts.md};
&:before {
background: ${p => p.theme.main.colors.grey};
width: 4px;
height: 4px;
content: '';
position: absolute;
border-radius: 50%;
margin-left: -${p => p.theme.main.sizes.margins.sm};
margin-top: 8px;
}
`;
const InjectionZoneList = ({ area, ...props }) => {
const compos = useInjectionZone(area);
@ -31,22 +10,23 @@ const InjectionZoneList = ({ area, ...props }) => {
return null;
}
// TODO
return (
<List>
<ul>
{compos.map(compo => {
const component = compo.Component(props);
if (component) {
return (
<ListItem key={compo.name}>
<Box key={compo.name} padding={3} style={{ textAlign: 'center' }}>
<compo.Component {...props} />
</ListItem>
</Box>
);
}
return null;
})}
</List>
</ul>
);
};

View File

@ -1,18 +1,10 @@
import {
GET_DATA,
GET_DATA_SUCCEEDED,
ON_CHANGE_BULK,
ON_CHANGE_BULK_SELECT_ALL,
ON_CHANGE_LIST_HEADERS,
ON_RESET_LIST_HEADERS,
ON_DELETE_DATA_ERROR,
ON_DELETE_DATA_SUCCEEDED,
ON_DELETE_SEVERAL_DATA_SUCCEEDED,
RESET_PROPS,
SET_LIST_LAYOUT,
SET_MODAL_LOADING_STATE,
TOGGLE_MODAL_DELETE,
TOGGLE_MODAL_DELETE_ALL,
} from './constants';
export const getData = () => ({ type: GET_DATA });
@ -23,61 +15,12 @@ export const getDataSucceeded = (pagination, data) => ({
data,
});
export function onChangeBulk({ target: { name } }) {
return {
type: ON_CHANGE_BULK,
name,
};
}
export function onChangeBulkSelectall() {
return {
type: ON_CHANGE_BULK_SELECT_ALL,
};
}
export function onDeleteDataError() {
return {
type: ON_DELETE_DATA_ERROR,
};
}
export function onDeleteDataSucceeded() {
return {
type: ON_DELETE_DATA_SUCCEEDED,
};
}
export function onDeleteSeveralDataSucceeded() {
return {
type: ON_DELETE_SEVERAL_DATA_SUCCEEDED,
};
}
export const onResetListHeaders = () => ({ type: ON_RESET_LIST_HEADERS });
export function resetProps() {
return { type: RESET_PROPS };
}
export function setModalLoadingState() {
return {
type: SET_MODAL_LOADING_STATE,
};
}
export function toggleModalDeleteAll() {
return {
type: TOGGLE_MODAL_DELETE_ALL,
};
}
export function toggleModalDelete() {
return {
type: TOGGLE_MODAL_DELETE,
};
}
export const setLayout = contentType => {
const { layouts } = contentType;

View File

@ -1,16 +1,6 @@
export const GET_DATA = 'ContentManager/ListView/GET_DATA';
export const GET_DATA_SUCCEEDED = 'ContentManager/ListView/GET_DATA_SUCCEEDED';
export const ON_CHANGE_BULK = 'ContentManager/ListView/ON_CHANGE_BULK';
export const ON_CHANGE_BULK_SELECT_ALL = 'ContentManager/ListView/ON_CHANGE_BULK_SELECT_ALL';
export const ON_DELETE_DATA_SUCCEEDED = 'ContentManager/ListView/ON_DELETE_DATA_SUCCEEDED';
export const ON_DELETE_DATA_ERROR = 'ContentManager/ListView/ON_DELETE_DATA_ERROR';
export const ON_DELETE_SEVERAL_DATA_SUCCEEDED =
'ContentManager/ListView/ON_DELETE_SEVERAL_DATA_SUCCEEDED';
export const RESET_PROPS = 'ContentManager/ListView/RESET_PROPS';
export const TOGGLE_MODAL_DELETE_ALL = 'ContentManager/ListView/TOGGLE_MODAL_DELETE_ALL';
export const TOGGLE_MODAL_DELETE = 'ContentManager/ListView/TOGGLE_MODAL_DELETE';
export const SET_MODAL_LOADING_STATE = 'ContentManager/ListView/SET_MODAL_LOADING_STATE';
export const ON_CHANGE_LIST_HEADERS = 'ContentManager/ListView/ON_CHANGE_LIST_HEADERS ';
export const ON_RESET_LIST_HEADERS = 'ContentManager/ListView/ON_RESET_LIST_HEADERS ';
export const SET_LIST_LAYOUT = 'ContentManager/ListView/SET_LIST_LAYOUT ';

View File

@ -2,6 +2,7 @@ import React, { memo, useCallback, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux';
import isEmpty from 'lodash/isEmpty';
// import { get, isEmpty } from 'lodash';
import get from 'lodash/get';
// import isEmpty from 'lodash/isEmpty'
@ -42,21 +43,7 @@ import {
// import FieldPicker from './FieldPicker';
// import Filter from './Filter';
import PaginationFooter from './PaginationFooter';
import {
getData,
getDataSucceeded,
onChangeBulk,
onChangeBulkSelectall,
onDeleteDataError,
onDeleteDataSucceeded,
onDeleteSeveralDataSucceeded,
setModalLoadingState,
toggleModalDelete,
toggleModalDeleteAll,
setLayout,
onChangeListHeaders,
onResetListHeaders,
} from './actions';
import { getData, getDataSucceeded, onChangeListHeaders, onResetListHeaders } from './actions';
import makeSelectListView from './selectors';
import {
// getAllAllowedHeaders,
@ -72,20 +59,8 @@ function ListView({
canCreate,
canDelete,
canRead,
// canUpdate,
// didDeleteData,
// entriesToDelete,
// onChangeBulk,
// onChangeBulkSelectall,
// onDeleteDataError,
// onDeleteDataSucceeded,
// onDeleteSeveralDataSucceeded,
// setModalLoadingState,
// showWarningDelete,
// showModalConfirmButtonLoading,
// showWarningDeleteAll,
// toggleModalDelete,
// toggleModalDeleteAll,
data,
getData,
getDataSucceeded,
@ -114,7 +89,6 @@ function ListView({
useFocusWhenNavigate();
// const [{ query }, setQuery] = useQueryParams();
const [{ query }] = useQueryParams();
const params = buildQueryString(query);
@ -136,6 +110,7 @@ function ListView({
// const sort = query.sort;
// const _q = query._q || '';
// FIXME
// Using a ref to avoid requests being fired multiple times on slug on change
// We need it because the hook as mulitple dependencies so it may run before the permissions have checked
const requestUrlRef = useRef('');
@ -169,7 +144,6 @@ function ListView({
}
const resStatus = get(err, 'response.status', null);
console.log(err);
if (resStatus === 403) {
await fetchPermissionsRef.current();
@ -212,80 +186,67 @@ function ListView({
// [displayedHeaders, onChangeListHeaders, toggleNotification]
// );
// const handleConfirmDeleteAllData = useCallback(async () => {
// try {
// setModalLoadingState();
const handleConfirmDeleteAllData = useCallback(
async ids => {
try {
await axiosInstance.post(getRequestUrl(`collection-types/${slug}/actions/bulkDelete`), {
ids,
});
// await axiosInstance.post(getRequestUrl(`collection-types/${slug}/actions/bulkDelete`), {
// ids: entriesToDelete,
// });
const requestUrl = getRequestUrl(`collection-types/${slug}${params}`);
fetchData(requestUrl);
trackUsageRef.current('didBulkDeleteEntries');
} catch (err) {
toggleNotification({
type: 'warning',
message: { id: getTrad('error.record.delete') },
});
}
},
[fetchData, params, slug, toggleNotification]
);
// onDeleteSeveralDataSucceeded();
// trackUsageRef.current('didBulkDeleteEntries');
// } catch (err) {
// toggleNotification({
// type: 'warning',
// message: { id: getTrad('error.record.delete') },
// });
// }
// }, [
// entriesToDelete,
// onDeleteSeveralDataSucceeded,
// slug,
// setModalLoadingState,
// toggleNotification,
// ]);
const handleConfirmDeleteData = useCallback(
async idToDelete => {
try {
let trackerProperty = {};
// const handleConfirmDeleteData = useCallback(async () => {
// try {
// let trackerProperty = {};
if (hasDraftAndPublish) {
const dataToDelete = data.find(obj => obj.id.toString() === idToDelete.toString());
const isDraftEntry = isEmpty(dataToDelete.published_at);
const status = isDraftEntry ? 'draft' : 'published';
// if (hasDraftAndPublish) {
// const dataToDelete = data.find(obj => obj.id.toString() === idToDelete.toString());
// const isDraftEntry = isEmpty(dataToDelete.published_at);
// const status = isDraftEntry ? 'draft' : 'published';
trackerProperty = { status };
}
// trackerProperty = { status };
// }
trackUsageRef.current('willDeleteEntry', trackerProperty);
// trackUsageRef.current('willDeleteEntry', trackerProperty);
// setModalLoadingState();
await axiosInstance.delete(getRequestUrl(`collection-types/${slug}/${idToDelete}`));
// await axiosInstance.delete(getRequestUrl(`collection-types/${slug}/${idToDelete}`));
const requestUrl = getRequestUrl(`collection-types/${slug}${params}`);
fetchData(requestUrl);
// toggleNotification({
// type: 'success',
// message: { id: getTrad('success.record.delete') },
// });
toggleNotification({
type: 'success',
message: { id: getTrad('success.record.delete') },
});
// // Close the modal and refetch data
// onDeleteDataSucceeded();
// trackUsageRef.current('didDeleteEntry', trackerProperty);
// } catch (err) {
// const errorMessage = get(
// err,
// 'response.payload.message',
// formatMessage({ id: getTrad('error.record.delete') })
// );
trackUsageRef.current('didDeleteEntry', trackerProperty);
} catch (err) {
const errorMessage = get(
err,
'response.payload.message',
formatMessage({ id: getTrad('error.record.delete') })
);
// toggleNotification({
// type: 'warning',
// message: errorMessage,
// });
// // Close the modal
// onDeleteDataError();
// }
// }, [
// toggleNotification,
// hasDraftAndPublish,
// setModalLoadingState,
// slug,
// idToDelete,
// onDeleteDataSucceeded,
// data,
// formatMessage,
// onDeleteDataError,
// ]);
toggleNotification({
type: 'warning',
message: errorMessage,
});
}
},
[hasDraftAndPublish, slug, params, fetchData, toggleNotification, data, formatMessage]
);
useEffect(() => {
const CancelToken = axios.CancelToken;
@ -306,19 +267,6 @@ function ListView({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [canRead, getData, slug, params, getDataSucceeded, fetchData]);
// const handleClickDelete = id => {
// setIdToDelete(id);
// toggleModalDelete();
// };
// const handleModalClose = useCallback(() => {
// if (didDeleteData) {
// const requestUrl = getRequestUrl(`collection-types/${slug}${params}`);
// fetchData(requestUrl);
// }
// }, [fetchData, didDeleteData, slug, params]);
// const toggleFilterPickerState = useCallback(() => {
// setFilterPickerState(prevState => {
// if (!prevState) {
@ -329,11 +277,6 @@ function ListView({
// });
// }, []);
// const handleToggleModalDeleteAll = e => {
// trackUsageRef.current('willBulkDeleteEntries');
// toggleModalDeleteAll(e);
// };
const defaultHeaderLayoutTitle = formatMessage({
id: getTrad('header.name'),
defaultMessage: 'Content',
@ -399,6 +342,8 @@ function ListView({
canCreate={canCreate}
canDelete={canDelete}
contentTypeName={headerLayoutTitle}
onConfirmDeleteAll={handleConfirmDeleteAllData}
onConfirmDelete={handleConfirmDeleteData}
isBulkable={isBulkable}
isLoading={isLoading}
// FIXME: remove the layout props drilling
@ -557,18 +502,11 @@ function ListView({
// );
}
// ListView.defaultProps = {
// permissions: [],
// };
ListView.propTypes = {
canCreate: PropTypes.bool.isRequired,
canDelete: PropTypes.bool.isRequired,
canRead: PropTypes.bool.isRequired,
// canUpdate: PropTypes.bool.isRequired,
data: PropTypes.array.isRequired,
// didDeleteData: PropTypes.bool.isRequired,
// entriesToDelete: PropTypes.array.isRequired,
layout: PropTypes.exact({
components: PropTypes.object.isRequired,
contentType: PropTypes.shape({
@ -586,31 +524,12 @@ ListView.propTypes = {
isLoading: PropTypes.bool.isRequired,
getData: PropTypes.func.isRequired,
getDataSucceeded: PropTypes.func.isRequired,
// onChangeBulk: PropTypes.func.isRequired,
// onChangeBulkSelectall: PropTypes.func.isRequired,
// onChangeListHeaders: PropTypes.func.isRequired,
// onDeleteDataError: PropTypes.func.isRequired,
// onDeleteDataSucceeded: PropTypes.func.isRequired,
// onDeleteSeveralDataSucceeded: PropTypes.func.isRequired,
// onResetListHeaders: PropTypes.func.isRequired,
pagination: PropTypes.shape({ total: PropTypes.number.isRequired, pageCount: PropTypes.number })
.isRequired,
// setModalLoadingState: PropTypes.func.isRequired,
// showModalConfirmButtonLoading: PropTypes.bool.isRequired,
// showWarningDelete: PropTypes.bool.isRequired,
// showWarningDeleteAll: PropTypes.bool.isRequired,
slug: PropTypes.string.isRequired,
// toggleModalDelete: PropTypes.func.isRequired,
// toggleModalDeleteAll: PropTypes.func.isRequired,
// setLayout: PropTypes.func.isRequired,
// permissions: PropTypes.arrayOf(
// PropTypes.shape({
// action: PropTypes.string.isRequired,
// subject: PropTypes.string.isRequired,
// properties: PropTypes.object,
// conditions: PropTypes.arrayOf(PropTypes.string),
// })
// ),
};
const mapStateToProps = makeSelectListView();
@ -620,17 +539,8 @@ export function mapDispatchToProps(dispatch) {
{
getData,
getDataSucceeded,
onChangeBulk,
onChangeBulkSelectall,
onChangeListHeaders,
onDeleteDataError,
onDeleteDataSucceeded,
onDeleteSeveralDataSucceeded,
onResetListHeaders,
setModalLoadingState,
toggleModalDelete,
toggleModalDeleteAll,
setLayout,
},
dispatch
);

View File

@ -8,27 +8,14 @@ import {
GET_DATA,
GET_DATA_SUCCEEDED,
RESET_PROPS,
ON_CHANGE_BULK,
ON_CHANGE_BULK_SELECT_ALL,
ON_DELETE_DATA_ERROR,
ON_DELETE_DATA_SUCCEEDED,
ON_DELETE_SEVERAL_DATA_SUCCEEDED,
TOGGLE_MODAL_DELETE,
TOGGLE_MODAL_DELETE_ALL,
ON_CHANGE_LIST_HEADERS,
ON_RESET_LIST_HEADERS,
SET_LIST_LAYOUT,
SET_MODAL_LOADING_STATE,
} from './constants';
export const initialState = {
data: [],
didDeleteData: false,
entriesToDelete: [],
isLoading: true,
showModalConfirmButtonLoading: false,
showWarningDelete: false,
showWarningDeleteAll: false,
contentType: {},
initialDisplayedHeaders: [],
displayedHeaders: [],
@ -56,30 +43,6 @@ const listViewReducer = (state = initialState, action) =>
drafState.isLoading = false;
break;
}
case ON_CHANGE_BULK: {
const hasElement = state.entriesToDelete.some(el => el === action.name);
if (hasElement) {
drafState.entriesToDelete = drafState.entriesToDelete.filter(el => el !== action.name);
break;
}
drafState.entriesToDelete.push(action.name);
break;
}
case ON_CHANGE_BULK_SELECT_ALL: {
if (state.entriesToDelete.length > 0) {
drafState.entriesToDelete = [];
break;
}
drafState.data.forEach(value => {
drafState.entriesToDelete.push(value.id.toString());
});
break;
}
case ON_CHANGE_LIST_HEADERS: {
const {
@ -115,21 +78,6 @@ const listViewReducer = (state = initialState, action) =>
break;
}
case ON_DELETE_DATA_SUCCEEDED: {
drafState.didDeleteData = true;
drafState.showWarningDelete = false;
break;
}
case ON_DELETE_DATA_ERROR: {
drafState.didDeleteData = false;
drafState.showWarningDelete = false;
break;
}
case ON_DELETE_SEVERAL_DATA_SUCCEEDED: {
drafState.didDeleteData = true;
drafState.showWarningDeleteAll = false;
break;
}
case ON_RESET_LIST_HEADERS: {
drafState.displayedHeaders = state.initialDisplayedHeaders;
break;
@ -137,34 +85,6 @@ const listViewReducer = (state = initialState, action) =>
case RESET_PROPS: {
return initialState;
}
case SET_MODAL_LOADING_STATE: {
drafState.showModalConfirmButtonLoading = true;
break;
}
case TOGGLE_MODAL_DELETE: {
drafState.showModalConfirmButtonLoading = false;
// Only change this value when the modal is opening
if (!state.showWarningDelete) {
drafState.didDeleteData = false;
}
drafState.entriesToDelete = [];
drafState.showWarningDelete = !state.showWarningDelete;
break;
}
case TOGGLE_MODAL_DELETE_ALL: {
drafState.showModalConfirmButtonLoading = false;
// Only change this value when the modal is closing
if (!state.showWarningDeleteAll) {
drafState.didDeleteData = false;
}
drafState.showWarningDeleteAll = !state.showWarningDeleteAll;
break;
}
case SET_LIST_LAYOUT: {
const { contentType, displayedHeaders } = action;

View File

@ -1,15 +1,5 @@
import produce from 'immer';
import {
getData,
getDataSucceeded,
onChangeBulk,
onChangeBulkSelectall,
onDeleteDataSucceeded,
onDeleteSeveralDataSucceeded,
setModalLoadingState,
toggleModalDelete,
toggleModalDeleteAll,
} from '../actions';
import { getData, getDataSucceeded } from '../actions';
import reducer from '../reducer';
@ -19,12 +9,7 @@ describe('CONTENT MANAGER | CONTAINERS | ListView | reducer', () => {
beforeEach(() => {
state = {
data: [],
didDeleteData: false,
entriesToDelete: [],
isLoading: true,
showModalConfirmButtonLoading: false,
showWarningDelete: false,
showWarningDeleteAll: false,
contentType: {},
initialDisplayedHeaders: [],
displayedHeaders: [],
@ -50,12 +35,7 @@ describe('CONTENT MANAGER | CONTAINERS | ListView | reducer', () => {
const expected = produce(state, draft => {
draft.data = [];
draft.didDeleteData = false;
draft.entriesToDelete = [];
draft.isLoading = true;
draft.showModalConfirmButtonLoading = false;
draft.showWarningDelete = false;
draft.showWarningDeleteAll = false;
draft.contentType = 'test';
draft.initialDisplayedHeaders = ['test'];
draft.displayedHeaders = ['test'];
@ -74,179 +54,4 @@ describe('CONTENT MANAGER | CONTAINERS | ListView | reducer', () => {
expect(reducer(state, getDataSucceeded({ count: 1 }, ['test']))).toEqual(expected);
});
describe('ON_CHANGE_BULK', () => {
it('should add the data to the entriesToDelete if it is not already selected', () => {
const target = {
name: '13',
};
state.entriesToDelete = ['1'];
const expected = produce(state, draft => {
draft.entriesToDelete = ['1', '13'];
});
expect(reducer(state, onChangeBulk({ target }))).toEqual(expected);
});
it('should remove the data to the entriesToDelete if it is already selected', () => {
const target = {
name: '13',
};
state.entriesToDelete = ['1', '13', '14'];
const expected = produce(state, draft => {
draft.entriesToDelete = ['1', '14'];
});
expect(reducer(state, onChangeBulk({ target }))).toEqual(expected);
});
});
describe('ON_CHANGE_BULK_SELECT_ALL', () => {
it('should remove all the selected elements if the entriesToDelete array is not empty', () => {
state.entriesToDelete = ['1', '13', '14'];
const expected = produce(state, draft => {
draft.entriesToDelete = [];
});
expect(reducer(state, onChangeBulkSelectall())).toEqual(expected);
});
it('should all all the elements if the entriesToDelete array is empty', () => {
state.entriesToDelete = [];
state.data = [{ id: 1 }, { id: '2' }, { id: '3' }];
const expected = produce(state, draft => {
draft.entriesToDelete = ['1', '2', '3'];
});
expect(reducer(state, onChangeBulkSelectall())).toEqual(expected);
});
});
describe('ON_DELETE_DATA_SUCCEEDED', () => {
it('should toggle the modal and set the didDeleteData to true', () => {
state.showWarningDelete = true;
const expected = produce(state, draft => {
draft.showWarningDelete = false;
draft.didDeleteData = true;
});
expect(reducer(state, onDeleteDataSucceeded())).toEqual(expected);
});
});
describe('ON_DELETE_DATA_SEVERAL_DATA_SUCCEEDED', () => {
it('should toggle the modal and set the didDeleteData to true', () => {
state.showWarningDeleteAll = true;
const expected = produce(state, draft => {
draft.showWarningDeleteAll = false;
draft.didDeleteData = true;
});
expect(reducer(state, onDeleteSeveralDataSucceeded())).toEqual(expected);
});
});
describe('SET_MODAL_LOADING_STATE', () => {
it('should set the showModalConfirmButtonLoading to true', () => {
state.showModalConfirmButtonLoading = false;
const expected = produce(state, draft => {
draft.showModalConfirmButtonLoading = true;
});
expect(reducer(state, setModalLoadingState())).toEqual(expected);
});
});
describe('TOGGLE_MODAL_DELETE', () => {
it('should set the showModalConfirmButtonLoading to false', () => {
state.showModalConfirmButtonLoading = true;
const expected = produce(state, draft => {
draft.showModalConfirmButtonLoading = false;
draft.showWarningDelete = true;
});
expect(reducer(state, toggleModalDelete())).toEqual(expected);
});
it('should set the didDeleteData to false if showWarningDelete is false', () => {
state.showWarningDelete = false;
state.didDeleteData = true;
const expected = produce(state, draft => {
draft.didDeleteData = false;
draft.showWarningDelete = true;
});
expect(reducer(state, toggleModalDelete())).toEqual(expected);
});
it('should not change the didDeleteData to false if showWarningDelete is truthy', () => {
state.showWarningDelete = true;
state.didDeleteData = true;
const expected = produce(state, draft => {
draft.didDeleteData = true;
draft.showWarningDelete = false;
});
expect(reducer(state, toggleModalDelete())).toEqual(expected);
});
it('should set the entriesToDelete to an empty array', () => {
state.showWarningDelete = false;
state.entriesToDelete = ['1'];
const expected = produce(state, draft => {
draft.showWarningDelete = true;
draft.entriesToDelete = [];
});
expect(reducer(state, toggleModalDelete())).toEqual(expected);
});
});
describe('TOGGLE_MODAL_DELETE_ALL', () => {
it('should set the showModalConfirmButtonLoading to false', () => {
state.showModalConfirmButtonLoading = true;
const expected = produce(state, draft => {
draft.showModalConfirmButtonLoading = false;
draft.showWarningDeleteAll = true;
});
expect(reducer(state, toggleModalDeleteAll())).toEqual(expected);
});
it('should set the didDeleteData to false if showWarningDeleteAll is falsy', () => {
state.showWarningDeleteAll = false;
state.didDeleteData = true;
const expected = produce(state, draft => {
draft.didDeleteData = false;
draft.showWarningDeleteAll = true;
});
expect(reducer(state, toggleModalDeleteAll())).toEqual(expected);
});
it('should not change the didDeleteData to false if showWarningDeleteAll is truthy', () => {
state.showWarningDeleteAll = true;
state.didDeleteData = true;
const expected = produce(state, draft => {
draft.didDeleteData = true;
draft.showWarningDeleteAll = false;
});
expect(reducer(state, toggleModalDeleteAll())).toEqual(expected);
});
});
});

View File

@ -1,24 +1,34 @@
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import React from 'react';
import { useIntl } from 'react-intl';
import { Text } from '@strapi/parts/Text';
import { getTrad } from '../../utils';
import useHasI18n from '../../hooks/useHasI18n';
const DeleteModalAdditionalInfos = () => {
const hasI18nEnabled = useHasI18n();
const { formatMessage } = useIntl();
if (!hasI18nEnabled) {
return null;
}
return (
<span>
<FormattedMessage
id={getTrad('Settings.list.actions.deleteAdditionalInfos')}
values={{
em: chunks => <em>{chunks}</em>,
}}
/>
</span>
<Text textColor="danger500">
{formatMessage(
{
id: getTrad('Settings.list.actions.deleteAdditionalInfos'),
defaultMessage:
'This will delete the active locale versions <em>(from Internationalization)</em>',
},
{
em: chunks => (
<Text textColor="danger500" bold>
{chunks}
</Text>
),
}
)}
</Text>
);
};