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