mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
Add qs for search management
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
5792cfeea8
commit
586781e12e
@ -70,6 +70,7 @@
|
||||
"p-map": "4.0.0",
|
||||
"passport-local": "1.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"qs": "6.9.4",
|
||||
"react": "^16.13.1",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"react-dnd": "^10.0.2",
|
||||
|
||||
@ -18,6 +18,7 @@ const alias = [
|
||||
'immutable',
|
||||
'invariant',
|
||||
'moment',
|
||||
'qs',
|
||||
'react',
|
||||
'react-copy-to-clipboard',
|
||||
'react-dnd',
|
||||
|
||||
@ -45,13 +45,16 @@ class Search extends React.Component {
|
||||
this.triggerChange('');
|
||||
};
|
||||
|
||||
triggerChange = value =>
|
||||
this.props.changeParams({
|
||||
target: {
|
||||
name: '_q',
|
||||
value,
|
||||
triggerChange = value => {
|
||||
const method = value ? 'push' : 'remove';
|
||||
|
||||
this.props.changeParams(
|
||||
{
|
||||
_q: value,
|
||||
},
|
||||
});
|
||||
method
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { model } = this.props;
|
||||
|
||||
@ -1,21 +1,23 @@
|
||||
import React, { memo } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { GlobalPagination, InputSelect, useGlobalContext } from 'strapi-helper-plugin';
|
||||
import useListView from '../../hooks/useListView';
|
||||
|
||||
import { FooterWrapper, SelectWrapper, Label } from './components';
|
||||
|
||||
function Footer() {
|
||||
function Footer({ count, onChange, params }) {
|
||||
const { emitEvent } = useGlobalContext();
|
||||
const { count, onChangeSearch, _limit, _page } = useListView();
|
||||
const _limit = parseInt(params.pageSize, 10);
|
||||
const _page = parseInt(params.page, 10);
|
||||
|
||||
const handleChangePage = ({ target: { value } }) => {
|
||||
onChangeSearch({ target: { name: '_page', value } });
|
||||
onChange({ page: value });
|
||||
};
|
||||
|
||||
const handleChangeLimit = ({ target: { value } }) => {
|
||||
emitEvent('willChangeNumberOfEntriesPerPage');
|
||||
|
||||
onChangeSearch({ target: { name: '_limit', value } });
|
||||
onChange({ pageSize: value });
|
||||
};
|
||||
|
||||
return (
|
||||
@ -49,4 +51,10 @@ function Footer() {
|
||||
);
|
||||
}
|
||||
|
||||
Footer.propTypes = {
|
||||
count: PropTypes.number.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
params: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Footer);
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
} from 'strapi-helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
import pluginPermissions from '../../permissions';
|
||||
import { useQueryParams } from '../../hooks';
|
||||
import { generatePermissionsObject, getRequestUrl, getTrad } from '../../utils';
|
||||
|
||||
import DisplayedFieldsDropdown from '../../components/DisplayedFieldsDropdown';
|
||||
@ -88,13 +89,34 @@ function ListView({
|
||||
onResetListHeaders,
|
||||
setLayout,
|
||||
}) {
|
||||
const {
|
||||
contentType: {
|
||||
attributes,
|
||||
settings: {
|
||||
defaultSortBy,
|
||||
defaultSortOrder,
|
||||
bulkable: isBulkable,
|
||||
filterable: isFilterable,
|
||||
searchable: isSearchable,
|
||||
pageSize: defaultPageSize,
|
||||
// mainField,
|
||||
},
|
||||
},
|
||||
} = layout;
|
||||
|
||||
const { emitEvent } = useGlobalContext();
|
||||
const viewPermissions = useMemo(() => generatePermissionsObject(slug), [slug]);
|
||||
const {
|
||||
isLoading: isLoadingForPermissions,
|
||||
allowedActions: { canCreate, canRead, canUpdate, canDelete },
|
||||
} = useUserPermissions(viewPermissions);
|
||||
const query = useQuery();
|
||||
// const query = useQuery();
|
||||
const defaultSort = `${defaultSortBy}:${defaultSortOrder}`;
|
||||
const [{ query, rawQuery }, setQuery] = useQueryParams({
|
||||
page: 1,
|
||||
pageSize: defaultPageSize,
|
||||
_sort: defaultSort,
|
||||
});
|
||||
const { pathname, search } = useLocation();
|
||||
const { push } = useHistory;
|
||||
|
||||
@ -105,88 +127,41 @@ function ListView({
|
||||
const [idToDelete, setIdToDelete] = useState(null);
|
||||
|
||||
const contentType = layout.contentType;
|
||||
const {
|
||||
contentType: {
|
||||
attributes,
|
||||
settings: {
|
||||
defaultSortBy,
|
||||
defaultSortOrder,
|
||||
bulkable: isBulkable,
|
||||
filterable: isFilterable,
|
||||
searchable: isSearchable,
|
||||
pageSize,
|
||||
// mainField,
|
||||
},
|
||||
},
|
||||
} = layout;
|
||||
|
||||
const hasDraftAndPublish = contentType.options.draftAndPublish;
|
||||
const defaultSort = `${defaultSortBy}:${defaultSortOrder}`;
|
||||
|
||||
const allAllowedHeaders = getAllAllowedHeaders(attributes);
|
||||
|
||||
const filters = useMemo(() => {
|
||||
const currentSearch = new URLSearchParams(search);
|
||||
const filters = query._where || [];
|
||||
|
||||
// Delete all params that are not related to the filters
|
||||
const paramsToDelete = ['_limit', '_page', '_sort', '_q'];
|
||||
const _limit = parseInt(query.pageSize, 10);
|
||||
const _page = parseInt(query.page, 10);
|
||||
const _sort = query._sort;
|
||||
const _q = query._q || '';
|
||||
|
||||
for (let i = 0; i < paramsToDelete.length; i++) {
|
||||
currentSearch.delete(paramsToDelete[i]);
|
||||
}
|
||||
|
||||
return generateFiltersFromSearch(currentSearch.toString());
|
||||
}, [search]);
|
||||
|
||||
// TODO
|
||||
const _limit = pageSize;
|
||||
// const _limit = useMemo(() => {
|
||||
// return parseInt(query.get('_limit') || pageSize, 10);
|
||||
// }, [pageSize, query]);
|
||||
// TODO
|
||||
const _q = query.get('_q') || '';
|
||||
// TODO
|
||||
const _page = parseInt(query.get('_page') || 1, 10);
|
||||
|
||||
// TODO
|
||||
const _sort = query.get('_sort') || defaultSort;
|
||||
const label = contentType.info.label;
|
||||
|
||||
const _start = useMemo(() => {
|
||||
return (_page - 1) * parseInt(_limit, 10);
|
||||
}, [_limit, _page]);
|
||||
const searchToSendForRequest = rawQuery;
|
||||
// const searchToSendForRequest = useMemo(() => {
|
||||
// const currentSearch = new URLSearchParams(search);
|
||||
|
||||
const searchToSendForRequest = useMemo(() => {
|
||||
const currentSearch = new URLSearchParams(search);
|
||||
// currentSearch.set('_limit', _limit);
|
||||
// currentSearch.set('_sort', _sort);
|
||||
// currentSearch.set('_start', _start);
|
||||
// currentSearch.delete('_page');
|
||||
|
||||
currentSearch.set('_limit', _limit);
|
||||
currentSearch.set('_sort', _sort);
|
||||
currentSearch.set('_start', _start);
|
||||
currentSearch.delete('_page');
|
||||
// return currentSearch.toString();
|
||||
// }, [_limit, _sort, _start, search]);
|
||||
|
||||
return currentSearch.toString();
|
||||
}, [_limit, _sort, _start, search]);
|
||||
|
||||
const getDataActionRef = useRef(getData);
|
||||
// const getDataActionRef = useRef(getData);
|
||||
const getDataSucceededRef = useRef(getDataSucceeded);
|
||||
|
||||
const shouldSendRequest = useMemo(() => {
|
||||
return !isLoadingForPermissions && canRead;
|
||||
}, [canRead, isLoadingForPermissions]);
|
||||
|
||||
const fetchData = async (search = searchToSendForRequest) => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
// getDataActionRef.current();
|
||||
// const [{ count }, data] = await Promise.all([
|
||||
// request(getRequestUrl(`explorer/${slug}/count?${search}`), {
|
||||
// method: 'GET',
|
||||
// }),
|
||||
// request(getRequestUrl(`explorer/${slug}?${search}`), {
|
||||
// method: 'GET',
|
||||
// }),
|
||||
// ]);
|
||||
|
||||
// const c = await request(getRequestUrl(`collection-types/${slug}?${search}`));
|
||||
// console.log({ c });
|
||||
const data = [
|
||||
{
|
||||
id: 16,
|
||||
@ -231,8 +206,6 @@ function ListView({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// TODO
|
||||
console.log('up');
|
||||
setLayout(layout);
|
||||
}, [layout, setLayout]);
|
||||
|
||||
@ -354,23 +327,23 @@ function ListView({
|
||||
[displayedHeaders, onChangeListHeaders]
|
||||
);
|
||||
|
||||
const handleChangeFilters = ({ target: { value } }) => {
|
||||
const newSearch = new URLSearchParams();
|
||||
// const handleChangeFilters = ({ target: { value } }) => {
|
||||
// const newSearch = new URLSearchParams();
|
||||
|
||||
// Set the default params
|
||||
newSearch.set('_limit', _limit);
|
||||
newSearch.set('_sort', _sort);
|
||||
newSearch.set('_page', 1);
|
||||
// // Set the default params
|
||||
// newSearch.set('_limit', _limit);
|
||||
// newSearch.set('_sort', _sort);
|
||||
// newSearch.set('_page', 1);
|
||||
|
||||
value.forEach(({ filter, name, value: filterValue }) => {
|
||||
const filterType = filter === '=' ? '' : filter;
|
||||
const filterName = `${name}${filterType}`;
|
||||
// value.forEach(({ filter, name, value: filterValue }) => {
|
||||
// const filterType = filter === '=' ? '' : filter;
|
||||
// const filterName = `${name}${filterType}`;
|
||||
|
||||
newSearch.append(filterName, filterValue);
|
||||
});
|
||||
// newSearch.append(filterName, filterValue);
|
||||
// });
|
||||
|
||||
push({ search: newSearch.toString() });
|
||||
};
|
||||
// push({ search: newSearch.toString() });
|
||||
// };
|
||||
|
||||
const handleChangeSearch = async ({ target: { name, value } }) => {
|
||||
const currentSearch = new URLSearchParams(searchToSendForRequest);
|
||||
@ -403,7 +376,7 @@ function ListView({
|
||||
const handleSubmit = (filters = []) => {
|
||||
emitEvent('didFilterEntries');
|
||||
toggleFilterPickerState();
|
||||
handleChangeFilters({ target: { name: 'filters', value: filters } });
|
||||
// handleChangeFilters({ target: { name: 'filters', value: filters } });
|
||||
};
|
||||
|
||||
const toggleFilterPickerState = () => {
|
||||
@ -421,7 +394,7 @@ function ListView({
|
||||
onClick: () => {
|
||||
toggleFilterPickerState();
|
||||
// Delete all filters
|
||||
handleChangeFilters({ target: { name: 'filters', value: [] } });
|
||||
// handleChangeFilters({ target: { name: 'filters', value: [] } });
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -496,7 +469,9 @@ function ListView({
|
||||
<>
|
||||
<ListViewProvider
|
||||
data={data}
|
||||
// TO remove
|
||||
count={count}
|
||||
//
|
||||
entriesToDelete={entriesToDelete}
|
||||
emitEvent={emitEvent}
|
||||
label={label}
|
||||
@ -508,8 +483,10 @@ function ListView({
|
||||
schema={{}}
|
||||
slug={slug}
|
||||
toggleModalDeleteAll={toggleModalDeleteAll}
|
||||
// TODO TO REMOVE ?
|
||||
_limit={_limit}
|
||||
_page={_page}
|
||||
//
|
||||
filters={filters}
|
||||
_q={_q}
|
||||
_sort={_sort}
|
||||
@ -526,7 +503,7 @@ function ListView({
|
||||
<Container className="container-fluid">
|
||||
{!isFilterPickerOpen && <Header {...headerProps} isLoading={isLoading && canRead} />}
|
||||
{isSearchable && canRead && (
|
||||
<Search changeParams={handleChangeSearch} initValue={_q} model={label} value={_q} />
|
||||
<Search changeParams={setQuery} initValue={_q} model={label} value={_q} />
|
||||
)}
|
||||
{canRead && (
|
||||
<Wrapper>
|
||||
@ -542,7 +519,7 @@ function ListView({
|
||||
{filters.map((filter, key) => (
|
||||
<Filter
|
||||
{...filter}
|
||||
changeParams={handleChangeFilters}
|
||||
// changeParams={handleChangeFilters}
|
||||
filters={filters}
|
||||
index={key}
|
||||
schema={{}}
|
||||
@ -580,7 +557,7 @@ function ListView({
|
||||
onChangeParams={handleChangeSearch}
|
||||
showLoader={isLoading}
|
||||
/>
|
||||
<Footer />
|
||||
<Footer count={count} params={query} onChange={setQuery} />
|
||||
</div>
|
||||
</div>
|
||||
</Wrapper>
|
||||
|
||||
@ -3,4 +3,5 @@ export { default as useFetchContentTypeLayout } from './useFetchContentTypeLayou
|
||||
export { default as useDataManager } from './useDataManager';
|
||||
export { default as useLayoutDnd } from './useLayoutDnd';
|
||||
export { default as useListView } from './useListView';
|
||||
export { default as useQueryParams } from './useQueryParams';
|
||||
export { default as useWysiwyg } from './useWysiwyg';
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { parse, stringify } from 'qs';
|
||||
|
||||
const useQueryParams = initialParams => {
|
||||
const { search } = useLocation();
|
||||
const { push } = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
if (!search && initialParams) {
|
||||
const newSearch = stringify(initialParams);
|
||||
|
||||
push({ search: newSearch });
|
||||
}
|
||||
}, [initialParams, push, search]);
|
||||
|
||||
const query = useMemo(() => {
|
||||
const searchQuery = search.substring(1);
|
||||
|
||||
if (!search) {
|
||||
return initialParams;
|
||||
}
|
||||
|
||||
return parse(searchQuery);
|
||||
}, [initialParams, search]);
|
||||
|
||||
const setQuery = useCallback(
|
||||
(nextParams, method = 'push') => {
|
||||
let nextQuery = { ...query };
|
||||
|
||||
if (method === 'remove') {
|
||||
Object.keys(nextParams).forEach(key => {
|
||||
delete nextQuery[key];
|
||||
});
|
||||
} else {
|
||||
nextQuery = { ...query, ...nextParams };
|
||||
}
|
||||
|
||||
push({ search: stringify(nextQuery, { encode: false }) });
|
||||
},
|
||||
[push, query]
|
||||
);
|
||||
|
||||
return [{ query, rawQuery: search }, setQuery];
|
||||
};
|
||||
|
||||
export default useQueryParams;
|
||||
@ -15097,7 +15097,7 @@ qs@6.7.0:
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
|
||||
|
||||
qs@^6.4.0, qs@^6.5.2, qs@^6.9.3, qs@^6.9.4:
|
||||
qs@6.9.4, qs@^6.4.0, qs@^6.5.2, qs@^6.9.3, qs@^6.9.4:
|
||||
version "6.9.4"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687"
|
||||
integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user