show/hide columns + table sort

dev
Anton Vlasov 3 years ago committed by Timofey Malinin
parent 55ccc8e71a
commit 3a8ab0c632

@ -36,7 +36,7 @@ export const getPoints = async (params, region) => {
const resultParams = enrichParamsWithRegionFilter(params, region);
const { data } = await api.get(
`/api/placement_points?${resultParams.toString()}`
`/api/placement_points/?${resultParams.toString()}`
);
return data;

@ -19,6 +19,8 @@ const extraCols = [
key: "postamat_id",
width: "70px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
];
@ -31,13 +33,19 @@ export const OnApprovalTable = ({ fullWidth }) => {
} = useOnApprovalPointsFilters();
const [isMakeWorkingModalOpened, setIsMakeWorkingModalOpened] =
useState(false);
const { columns, defaultColumns, order, setOrder } = useColumns(extraCols, 'onApprovalTableOrder');
const { columns, orderColumns, sort, setSort } = useColumns(extraCols, 'onApprovalTableOrder');
const { isVisible } = useLayersVisibility();
const onSort = (sortDirection, key) => {
if (sortDirection === `ascend`) setSort(key);
if (sortDirection === `descend`) setSort(`-${key}`);
if (!sortDirection) setSort(null);
}
const clearSelected = () => setSelectedIds([]);
const { data, isInitialLoading } = useQuery(
["on-approval-points", page, region, isVisible],
const { data, isInitialLoading, isFetching } = useQuery(
["on-approval-points", page, region, isVisible, sort],
async () => {
const statuses = [];
@ -60,6 +68,7 @@ export const OnApprovalTable = ({ fullWidth }) => {
statuses.length > 0
? statuses
: [STATUSES.onApproval, STATUSES.working, STATUSES.cancelled],
ordering: sort,
});
if (statuses.length === 0) {
@ -94,7 +103,7 @@ export const OnApprovalTable = ({ fullWidth }) => {
selectedIds={selectedIds}
onClearSelected={clearSelected}
onOpenMakeWorkingModal={() => setIsMakeWorkingModalOpened(true)}
orderColumns={{ defaultColumns, order, setOrder }}
orderColumns={orderColumns}
/>
}
rowSelection={canEdit ? rowSelection : undefined}
@ -105,7 +114,10 @@ export const OnApprovalTable = ({ fullWidth }) => {
isClickedPointLoading={isClickedPointLoading}
columns={columns}
fullWidth={fullWidth}
loading={isInitialLoading}
onChange={(val, filter, sorter) => {
onSort(sorter.order, sorter.columnKey);
}}
loading={isInitialLoading || isFetching}
/>
{isMakeWorkingModalOpened && (
<MakeWorkingModal

@ -10,19 +10,27 @@ import { useColumns } from "../useColumns.jsx";
import { PAGE_SIZE } from "../constants.js";
import { usePopup } from "../../../stores/usePopup.js";
const tableKey = 'pendingTable';
export const PendingTable = ({ fullWidth }) => {
const { selection, include, exclude } = usePointSelection();
const { clickedPointConfig, setClickedPointConfig } = useClickedPointConfig();
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(PAGE_SIZE);
const {columns, defaultColumns, order, setOrder} = useColumns([], 'pendingTableOrder');
const {columns, orderColumns, sort, setSort} = useColumns([], tableKey);
const { setPopup } = usePopup();
const onSort = (sortDirection, key) => {
if (sortDirection === `ascend`) setSort(key);
if (sortDirection === `descend`) setSort(`-${key}`);
if (!sortDirection) setSort(null);
}
const { data, isClickedPointLoading, isDataLoading } = usePendingTableData(
page,
() => setPage(1),
pageSize,
setPageSize
setPageSize,
sort
);
const resetPageSize = () => setPageSize(PAGE_SIZE);
@ -79,7 +87,10 @@ export const PendingTable = ({ fullWidth }) => {
isClickedPointLoading={isClickedPointLoading}
columns={columns}
fullWidth={fullWidth}
header={<HeaderWrapper exportProvider={useExportPendingData} orderColumns={{defaultColumns, order, setOrder}} />}
onChange={(val, filter, sorter) => {
onSort(sorter.order, sorter.columnKey);
}}
header={<HeaderWrapper exportProvider={useExportPendingData} orderColumns={orderColumns} />}
loading={isDataLoading}
/>
);

@ -4,12 +4,12 @@ import { useMergeTableData } from "../useMergeTableData";
import { STATUSES } from "../../../config";
import { usePendingPointsFilters } from "../../../stores/usePendingPointsFilters";
export const usePendingTableData = (page, resetPage, pageSize, setPageSize) => {
export const usePendingTableData = (page, resetPage, pageSize, setPageSize, sort) => {
const { filters } = usePendingPointsFilters();
const { prediction, categories, region } = filters;
const { data, isInitialLoading } = useQuery(
["table", page, filters],
const { data, isInitialLoading, isFetching } = useQuery(
["table", page, filters, sort],
async () => {
const params = new URLSearchParams({
page,
@ -17,6 +17,7 @@ export const usePendingTableData = (page, resetPage, pageSize, setPageSize) => {
"prediction_current[]": prediction,
"status[]": [STATUSES.pending],
"categories[]": categories,
ordering: sort,
});
return await getPoints(params, region);
@ -40,6 +41,6 @@ export const usePendingTableData = (page, resetPage, pageSize, setPageSize) => {
data: mergedData,
pageSize,
isClickedPointLoading,
isDataLoading: isInitialLoading,
isDataLoading: isInitialLoading || isFetching,
};
};

@ -22,6 +22,7 @@ export const Table = React.memo(
header,
fullWidth,
loading,
onChange
}) => {
const { clickedPointConfig, setClickedPointConfig } =
useClickedPointConfig();
@ -68,6 +69,7 @@ export const Table = React.memo(
}}
dataSource={data?.results}
columns={columns}
onChange={onChange}
rowKey="id"
scroll={SCROLL}
sticky={true}

@ -1,5 +1,5 @@
import {useState} from "react";
import {Button, Dropdown} from "antd";
import {Button, Checkbox, Dropdown} from "antd";
import {SettingOutlined} from "@ant-design/icons";
import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
@ -19,6 +19,15 @@ export const TableSettings = ({orderColumns}) => {
orderColumns.setOrder(updatedList);
};
const hideColumn = (columnIndex) => {
const updatedList = columnsList.map((item, index) => {
if (columnIndex === index) return {...item, show: !item.show};
return item;
});
setColumnsList(updatedList);
orderColumns.setOrder(updatedList);
}
const columnsListRender = () => {
return (
<div onClick={(e) => e.stopPropagation()} className='z-10 bg-white-background rounded-xl p-3 space-y-3'>
@ -27,12 +36,14 @@ export const TableSettings = ({orderColumns}) => {
{(provided) => (
<div className="flex flex-col" {...provided.droppableProps} ref={provided.innerRef}>
{columnsList.map((item, index) => {
const num = item.position;
return (
<Draggable key={`list-${item}`} draggableId={`list-${item}`} index={index}>
<Draggable key={`list-${num}`} draggableId={`list-${num}`} index={index}>
{(provided) => (
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
<div className="flex flex-row gap-2" ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
<Checkbox onChange={() => hideColumn(index)} checked={item.show} />
<p>
{ orderColumns.defaultColumns[item].title }
{ orderColumns.defaultColumns[num].name || orderColumns.defaultColumns[num].title }
</p>
</div>
)}

@ -10,16 +10,23 @@ import { useExportWorkingData } from "./useExportWorkingData";
import { useWorkingPointsFilters } from "../../../stores/useWorkingPointsFilters";
import { useColumns } from "./useColumns.jsx";
const tableKey = 'workingTable'
export const WorkingTable = ({ fullWidth }) => {
const [pageSize, setPageSize] = useState(PAGE_SIZE);
const [page, setPage] = useState(1);
const {
filters: { region, deltaTraffic, factTraffic, age },
} = useWorkingPointsFilters();
const {columns, defaultColumns, order, setOrder} = useColumns('workingTableOrder');
const {columns, orderColumns, sort, setSort} = useColumns(tableKey);
const { data, isInitialLoading } = useQuery(
["working-points", page, region, deltaTraffic, factTraffic, age],
const onSort = (sortDirection, key) => {
if (sortDirection === `ascend`) setSort(key);
if (sortDirection === `descend`) setSort(`-${key}`);
if (!sortDirection) setSort(null);
}
const { data, isInitialLoading, isFetching } = useQuery(
["working-points", page, region, deltaTraffic, factTraffic, age, sort],
async () => {
const params = new URLSearchParams({
page,
@ -28,6 +35,7 @@ export const WorkingTable = ({ fullWidth }) => {
"delta_current[]": deltaTraffic,
"fact[]": factTraffic,
"age_day[]": age,
ordering: sort
});
return await getPoints(params, region);
@ -51,8 +59,11 @@ export const WorkingTable = ({ fullWidth }) => {
isClickedPointLoading={isClickedPointLoading}
columns={columns}
fullWidth={fullWidth}
header={<HeaderWrapper exportProvider={useExportWorkingData} orderColumns={{defaultColumns, order, setOrder}} />}
loading={isInitialLoading}
onChange={(val, filter, sorter) => {
onSort(sorter.order, sorter.columnKey);
}}
header={<HeaderWrapper exportProvider={useExportWorkingData} orderColumns={orderColumns} />}
loading={isInitialLoading || isFetching}
/>
);
};

@ -1,20 +1,27 @@
import { useGetRegions } from "../../../components/RegionSelect.jsx";
import { useMemo } from "react";
import { getRegionNameById } from "../../../Map/Popup/mode-popup/config.js";
import { SearchOutlined } from "@ant-design/icons";
import { Button, Popover } from "antd";
import { AddressSearch } from "../../../Map/AddressSearch.jsx";
import { useTable } from "../../../stores/useTable.js";
import {useGetRegions} from "../../../components/RegionSelect.jsx";
import {useMemo} from "react";
import {getRegionNameById} from "../../../Map/Popup/mode-popup/config.js";
import {SearchOutlined} from "@ant-design/icons";
import {Button, Popover} from "antd";
import {AddressSearch} from "../../../Map/AddressSearch.jsx";
import {useTable} from "../../../stores/useTable.js";
import useLocalStorage from "../../../hooks/useLocalStorage.js";
const DEFAULT_LENGTH = 11;
export const useColumns = ({ key }) => {
const { data: regions } = useGetRegions();
export const useColumns = (key) => {
const {data: regions} = useGetRegions();
const {
tableState: { fullScreen },
tableState: {fullScreen},
} = useTable();
const [order, setOrder] = useLocalStorage(key, [...Array(DEFAULT_LENGTH).keys()])
const [order, setOrder] = useLocalStorage(`${key}Order`, [...Array(DEFAULT_LENGTH).keys()].map((position) => {
return {
position,
show: true,
}
}));
const [sort, setSort] = useLocalStorage(`${key}Sort`, null);
const defaultColumns = useMemo(() => {
return [
@ -23,20 +30,23 @@ export const useColumns = ({ key }) => {
<div className="flex items-center justify-between">
<span>Адрес</span>
<Popover
content={<AddressSearch autoFocus={true} />}
content={<AddressSearch autoFocus={true}/>}
trigger="click"
placement={"right"}
>
<Button>
<SearchOutlined />
<SearchOutlined/>
</Button>
</Popover>
</div>
) : (
"Адрес"
),
name: "Адрес",
dataIndex: "address",
key: "address",
sorter: true,
showSorterTooltip: false,
width: 200,
},
{
@ -45,6 +55,8 @@ export const useColumns = ({ key }) => {
key: "area",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
render: (_, record) => {
return getRegionNameById(record.area, regions?.normalized);
},
@ -58,6 +70,8 @@ export const useColumns = ({ key }) => {
render: (_, record) => {
return getRegionNameById(record.district, regions?.normalized);
},
sorter: true,
showSorterTooltip: false,
},
{
title: "Название",
@ -65,6 +79,8 @@ export const useColumns = ({ key }) => {
key: "name",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Категория",
@ -72,6 +88,8 @@ export const useColumns = ({ key }) => {
key: "category",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "План",
@ -79,6 +97,8 @@ export const useColumns = ({ key }) => {
key: "plan_current",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Факт",
@ -86,6 +106,8 @@ export const useColumns = ({ key }) => {
key: "fact",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Расхождение с прогнозом",
@ -93,6 +115,8 @@ export const useColumns = ({ key }) => {
key: "delta_current",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Зрелость",
@ -100,12 +124,16 @@ export const useColumns = ({ key }) => {
key: "age_day",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Дата начала работы",
dataIndex: "start_date",
key: "start_date",
width: "120px",
sorter: true,
showSorterTooltip: false,
render: (value) => {
if (!value) return "Нет данных";
@ -119,15 +147,31 @@ export const useColumns = ({ key }) => {
key: "postamat_id",
width: "70px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
];
}, [regions?.normalized, fullScreen]);
const columns = useMemo(() => {
return order.map((item) => {
return defaultColumns[item];
})
return order.flatMap((item) => !item.show ? [] : defaultColumns[item.position])
.map((column) => {
if (sort && sort.includes(column.key)) return {
...column,
defaultSortOrder: sort.includes('-') ? 'descend' : 'ascend',
};
return column;
});
}, [defaultColumns, order, fullScreen]);
return {columns, defaultColumns, order, setOrder};
return {
columns,
orderColumns: {
defaultColumns,
order,
setOrder,
},
sort,
setSort
};
};

@ -15,7 +15,14 @@ export const useColumns = (fields = [], key) => {
tableState: { fullScreen },
} = useTable();
const [order, setOrder] = useLocalStorage(key, [...Array(DEFAULT_LENGTH + fields.length).keys()])
const [order, setOrder] = useLocalStorage(`${key}Order`, [...Array(DEFAULT_LENGTH).keys()].map((position) => {
return {
position,
show: true,
}
}));
const [sort, setSort] = useLocalStorage(`${key}Sort`, null);
const defaultColumns = useMemo(() => {
return [
@ -36,9 +43,12 @@ export const useColumns = (fields = [], key) => {
) : (
"Адрес"
),
name: "Адрес",
dataIndex: "address",
key: "address",
width: 200,
sorter: true,
showSorterTooltip: false,
},
{
title: "Район",
@ -46,6 +56,8 @@ export const useColumns = (fields = [], key) => {
key: "area",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
render: (_, record) => {
return getRegionNameById(record.area, regions?.normalized);
},
@ -56,6 +68,8 @@ export const useColumns = (fields = [], key) => {
key: "district",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
render: (_, record) => {
return getRegionNameById(record.district, regions?.normalized);
},
@ -66,6 +80,8 @@ export const useColumns = (fields = [], key) => {
key: "name",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Категория",
@ -73,6 +89,8 @@ export const useColumns = (fields = [], key) => {
key: "category",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
{
title: "Статус",
@ -80,6 +98,8 @@ export const useColumns = (fields = [], key) => {
key: "status",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
render: (_, record) => {
return STATUS_LABEL_MAPPER[record.status];
},
@ -90,16 +110,32 @@ export const useColumns = (fields = [], key) => {
key: "prediction_current",
width: "120px",
ellipsis: true,
sorter: true,
showSorterTooltip: false,
},
...fields,
];
}, [regions?.normalized, fields, fullScreen]);
const columns = useMemo(() => {
return order.map((item) => {
return defaultColumns[item];
})
return order.flatMap((item) => !item.show ? [] : defaultColumns[item.position])
.map((column) => {
if (sort && sort.includes(column.key)) return {
...column,
defaultSortOrder: sort.includes('-') ? 'descend' : 'ascend',
};
return column;
});
}, [defaultColumns, order, fullScreen]);
return {columns, defaultColumns, order, setOrder};
return {
columns,
orderColumns: {
defaultColumns,
order,
setOrder,
},
sort,
setSort
};
};

Loading…
Cancel
Save