mirror of
https://github.com/strapi/strapi.git
synced 2025-09-20 14:00:48 +00:00
merge commit
This commit is contained in:
commit
c1b61fa2a7
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { get } from 'lodash';
|
||||
import get from 'lodash/get';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Row } from '@strapi/parts/Row';
|
||||
import { Grid, GridItem } from '@strapi/parts/Grid';
|
||||
@ -99,7 +99,7 @@ const Settings = ({ modifiedData, onChange, sortOptions }) => {
|
||||
defaultMessage:
|
||||
'Note: You can override this value in the Collection Type settings page.',
|
||||
})}
|
||||
onChange={e => onChange({ target: { name: 'settings.pageSize', value: e } })}
|
||||
onChange={value => onChange({ target: { name: 'settings.pageSize', value } })}
|
||||
name="settings.pageSize"
|
||||
value={get(modifiedData, 'settings.pageSize', '')}
|
||||
>
|
||||
@ -116,7 +116,7 @@ const Settings = ({ modifiedData, onChange, sortOptions }) => {
|
||||
id: 'content-manager.form.Input.defaultSort',
|
||||
defaultMessage: 'Default sort attribute',
|
||||
})}
|
||||
onChange={e => onChange({ target: { name: 'settings.defaultSortBy', value: e } })}
|
||||
onChange={value => onChange({ target: { name: 'settings.defaultSortBy', value } })}
|
||||
name="settings.defaultSortBy"
|
||||
value={get(modifiedData, 'settings.defaultSortBy', '')}
|
||||
>
|
||||
@ -133,7 +133,7 @@ const Settings = ({ modifiedData, onChange, sortOptions }) => {
|
||||
id: 'content-manager.form.Input.sort.order',
|
||||
defaultMessage: 'Default sort order',
|
||||
})}
|
||||
onChange={e => onChange({ target: { name: 'settings.defaultSortOrder', value: e } })}
|
||||
onChange={value => onChange({ target: { name: 'settings.defaultSortOrder', value } })}
|
||||
name="settings.defaultSortOrder"
|
||||
value={get(modifiedData, 'settings.defaultSortOrder', '')}
|
||||
>
|
||||
|
@ -2,7 +2,10 @@ import React, { memo, useContext, useMemo, useReducer, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { useMutation } from 'react-query';
|
||||
import { isEqual, upperFirst, pick, get } from 'lodash';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import pick from 'lodash/pick';
|
||||
import get from 'lodash/get';
|
||||
import { stringify } from 'qs';
|
||||
import { useNotification, useTracking, ConfirmDialog } from '@strapi/helper-plugin';
|
||||
import { useIntl } from 'react-intl';
|
||||
@ -27,6 +30,7 @@ import Settings from './components/Settings';
|
||||
import DraggableCard from './components/DraggableCard';
|
||||
import init from './init';
|
||||
import reducer, { initialState } from './reducer';
|
||||
import { EXCLUDED_SORT_OPTIONS } from './utils/excludedSortOptions';
|
||||
|
||||
const Flex = styled(Box)`
|
||||
flex: ${({ size }) => size};
|
||||
@ -41,7 +45,7 @@ const SelectContainer = styled(Flex)`
|
||||
max-width: ${200 / 16}rem;
|
||||
`;
|
||||
|
||||
const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
const ListSettingsView = ({ layout, slug }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { trackUsage } = useTracking();
|
||||
const pluginsQueryParams = usePluginsQueryParams();
|
||||
@ -74,14 +78,44 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
return get(modifiedData, ['layouts', 'list'], []);
|
||||
}, [modifiedData]);
|
||||
|
||||
const excludedSortOptions = ['media', 'richtext', 'dynamiczone', 'relation', 'component', 'json'];
|
||||
const sortOptions = Object.entries(attributes).reduce((acc, cur) => {
|
||||
const [name, { type }] = cur;
|
||||
|
||||
if (!EXCLUDED_SORT_OPTIONS.includes(type)) {
|
||||
acc.push(name);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// const handleClickEditLabel = labelToEdit => {
|
||||
// dispatch({
|
||||
// type: 'SET_LABEL_TO_EDIT',
|
||||
// labelToEdit,
|
||||
// });
|
||||
// toggleModalForm();
|
||||
// };
|
||||
|
||||
// const handleClosed = () => {
|
||||
// dispatch({
|
||||
// type: 'UNSET_LABEL_TO_EDIT',
|
||||
// });
|
||||
// };
|
||||
|
||||
const handleChange = ({ target: { name, value } }) => {
|
||||
dispatch({
|
||||
type: 'ON_CHANGE',
|
||||
keys: name,
|
||||
value: name === 'settings.pageSize' ? parseInt(value, 10) : value,
|
||||
});
|
||||
};
|
||||
|
||||
const goBackUrl = () => {
|
||||
const {
|
||||
settings: { pageSize, defaultSortBy, defaultSortOrder },
|
||||
kind,
|
||||
uid,
|
||||
} = modifiedData;
|
||||
} = initialData;
|
||||
const sort = `${defaultSortBy}:${defaultSortOrder}`;
|
||||
const goBackSearch = `${stringify(
|
||||
{
|
||||
@ -95,15 +129,6 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
return `/content-manager/${kind}/${uid}?${goBackSearch}`;
|
||||
};
|
||||
|
||||
const handleChange = ({ target: { name, value } }) => {
|
||||
dispatch({
|
||||
type: 'ON_CHANGE',
|
||||
keys: name,
|
||||
value: name === 'settings.pageSize' ? parseInt(value, 10) : value,
|
||||
});
|
||||
console.log('here');
|
||||
};
|
||||
|
||||
const handleConfirm = async () => {
|
||||
const body = pick(modifiedData, ['layouts', 'settings', 'metadatas']);
|
||||
submitMutation.mutateAsync(body);
|
||||
@ -138,23 +163,8 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
trackUsage('willSaveContentTypeLayout');
|
||||
};
|
||||
|
||||
const sortOptions = Object.entries(attributes).reduce((acc, cur) => {
|
||||
const [name, { type }] = cur;
|
||||
|
||||
if (!excludedSortOptions.includes(type)) {
|
||||
acc.push(name);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const submitMutation = useMutation(body => putCMSettingsLV(body, slug), {
|
||||
onSuccess: async ({ data: { data } }) => {
|
||||
updateLayout(data);
|
||||
|
||||
dispatch({
|
||||
type: 'SUBMIT_SUCCEEDED',
|
||||
});
|
||||
onSuccess: async () => {
|
||||
trackUsage('didEditListSettings');
|
||||
refetchData();
|
||||
},
|
||||
@ -164,7 +174,6 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
message: { id: 'notification.error' },
|
||||
});
|
||||
},
|
||||
refetchActive: true,
|
||||
});
|
||||
const { isLoading: isSubmittingForm } = submitMutation;
|
||||
|
||||
@ -257,7 +266,7 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
<form onSubmit={handleSubmit}>
|
||||
<HeaderLayout
|
||||
navigationAction={
|
||||
<Link startIcon={<BackIcon />} to={goBackUrl}>
|
||||
<Link startIcon={<BackIcon />} to={goBackUrl} id="go-back">
|
||||
{formatMessage({ id: 'app.components.go-back', defaultMessage: 'Go back' })}
|
||||
</Link>
|
||||
}
|
||||
@ -330,7 +339,12 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
</Stack>
|
||||
</ScrollableContainer>
|
||||
<SelectContainer size="auto" paddingBottom={4}>
|
||||
<Select onChange={e => handleAddField(e)} value="" placeholder="Add a field">
|
||||
<Select
|
||||
disabled={listRemainingFields.length <= 0}
|
||||
onChange={e => handleAddField(e)}
|
||||
value=""
|
||||
placeholder="Add a field"
|
||||
>
|
||||
{listRemainingFields.map(field => (
|
||||
<Option value={field} key={field}>
|
||||
{field}
|
||||
@ -479,13 +493,23 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
ListSettingsView.propTypes = {
|
||||
layout: PropTypes.shape({
|
||||
uid: PropTypes.string.isRequired,
|
||||
settings: PropTypes.object.isRequired,
|
||||
settings: PropTypes.shape({
|
||||
bulkable: PropTypes.bool,
|
||||
defaultSortBy: PropTypes.string,
|
||||
defaultSortOrder: PropTypes.string,
|
||||
filterable: PropTypes.bool,
|
||||
pageSize: PropTypes.number,
|
||||
searchable: PropTypes.bool,
|
||||
}).isRequired,
|
||||
metadatas: PropTypes.object.isRequired,
|
||||
options: PropTypes.object.isRequired,
|
||||
attributes: PropTypes.object.isRequired,
|
||||
attributes: PropTypes.objectOf(
|
||||
PropTypes.shape({
|
||||
type: PropTypes.string,
|
||||
})
|
||||
).isRequired,
|
||||
}).isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
updateLayout: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(ListSettingsView);
|
||||
|
@ -78,10 +78,6 @@ const reducer = (state = initialState, action) =>
|
||||
// set(draftState, [...fieldMetadataPath, 'sortable'], state.labelForm.sortable);
|
||||
// break;
|
||||
// }
|
||||
case 'SUBMIT_SUCCEEDED': {
|
||||
draftState.initialData = state.modifiedData;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return draftState;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { render, waitFor, screen } from '@testing-library/react';
|
||||
import { render, waitFor, screen, fireEvent } from '@testing-library/react';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
@ -49,10 +49,7 @@ const layout = {
|
||||
options: {},
|
||||
};
|
||||
|
||||
const history = createMemoryHistory();
|
||||
history.push('/content-manager');
|
||||
|
||||
const App = (
|
||||
const makeApp = history => (
|
||||
<Router history={history}>
|
||||
<ModelsContext.Provider value={{ refetchData: jest.fn() }}>
|
||||
<QueryClientProvider client={client}>
|
||||
@ -72,7 +69,10 @@ const App = (
|
||||
|
||||
describe('ADMIN | CM | LV | Configure the view', () => {
|
||||
it('renders and matches the snapshot', async () => {
|
||||
const { container } = render(App);
|
||||
const history = createMemoryHistory();
|
||||
history.push('/content-manager');
|
||||
|
||||
const { container } = render(makeApp(history));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Configure the view - Michka')).toBeInTheDocument();
|
||||
});
|
||||
@ -797,6 +797,7 @@ describe('ADMIN | CM | LV | Configure the view', () => {
|
||||
<a
|
||||
class="c6"
|
||||
href="/content-manager/undefined/api::restaurant.restaurant?page=1&sort=undefined:undefined"
|
||||
id="go-back"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
@ -1323,4 +1324,22 @@ describe('ADMIN | CM | LV | Configure the view', () => {
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
it('should keep plugins query params when arriving on the page and going back', async () => {
|
||||
const history = createMemoryHistory();
|
||||
history.push(
|
||||
'/content-manager/collectionType/api::category.category/configurations/list?plugins[i18n][locale]=fr'
|
||||
);
|
||||
|
||||
const { container } = render(makeApp(history));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Configure the view - Michka')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(history.location.search).toEqual('?plugins[i18n][locale]=fr');
|
||||
fireEvent.click(container.querySelector('#go-back'));
|
||||
expect(history.location.search).toEqual(
|
||||
'?page=1&sort=undefined:undefined&plugins[i18n][locale]=fr'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,8 @@
|
||||
export const EXCLUDED_SORT_OPTIONS = [
|
||||
'media',
|
||||
'richtext',
|
||||
'dynamiczone',
|
||||
'relation',
|
||||
'component',
|
||||
'json',
|
||||
];
|
@ -81,6 +81,7 @@ function ListView({
|
||||
|
||||
const [{ query }] = useQueryParams();
|
||||
const params = buildQueryString(query);
|
||||
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
||||
|
||||
const { pathname } = useLocation();
|
||||
const { push } = useHistory();
|
||||
@ -136,8 +137,6 @@ function ListView({
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('iii');
|
||||
|
||||
console.error(err);
|
||||
toggleNotification({
|
||||
type: 'warning',
|
||||
@ -256,7 +255,7 @@ function ListView({
|
||||
trackUsageRef.current('willCreateEntry', trackerProperty);
|
||||
push({
|
||||
pathname: `${pathname}/create`,
|
||||
search: query.plugins ? stringify({ plugins: query.plugins }, { encode: false }) : '',
|
||||
search: query.plugins ? pluginsQueryParams : '',
|
||||
});
|
||||
}}
|
||||
startIcon={<Add />}
|
||||
@ -282,7 +281,8 @@ function ListView({
|
||||
<FieldPicker layout={layout} />
|
||||
<CheckPermissions permissions={cmPermissions.collectionTypesConfigurations}>
|
||||
<IconButtonCustom
|
||||
onClick={() => push(`${slug}/configurations/list`)}
|
||||
onClick={() =>
|
||||
push({ pathname: `${slug}/configurations/list`, search: pluginsQueryParams })}
|
||||
icon={<Settings />}
|
||||
label={formatMessage({
|
||||
id: 'app.links.configure-view',
|
||||
|
Loading…
x
Reference in New Issue
Block a user