From 9b3290f514d03ca6891c5d0bbef6b322fbb102f2 Mon Sep 17 00:00:00 2001 From: Anton Vlasov Date: Sun, 6 Aug 2023 18:12:12 +0000 Subject: [PATCH] order columns --- package.json | 1 + src/Map/Popup/Popup.jsx | 14 ++--- src/hooks/useLocalStorage.js | 25 ++++++++ src/modules/Table/HeaderWrapper.jsx | 3 + src/modules/Table/OnApprovalTable/Header.jsx | 2 + .../Table/OnApprovalTable/OnApprovalTable.jsx | 3 +- .../Table/PendingTable/PendingTable.jsx | 4 +- src/modules/Table/TableSettings.jsx | 63 +++++++++++++++++++ .../Table/WorkingTable/WorkingTable.jsx | 4 +- src/modules/Table/WorkingTable/useColumns.jsx | 16 ++++- src/modules/Table/useColumns.jsx | 16 ++++- 11 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 src/hooks/useLocalStorage.js create mode 100644 src/modules/Table/TableSettings.jsx diff --git a/package.json b/package.json index 0e7c2d0..4135160 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "maplibre-gl": "^2.4.0", "nanostores": "^0.7.3", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-icons": "^4.8.0", "react-map-gl": "^7.0.19", diff --git a/src/Map/Popup/Popup.jsx b/src/Map/Popup/Popup.jsx index f33619f..58b8abe 100644 --- a/src/Map/Popup/Popup.jsx +++ b/src/Map/Popup/Popup.jsx @@ -19,21 +19,21 @@ const SingleFeaturePopup = ({ feature }) => { const isWorkingPoint = feature.properties.status === STATUSES.working; if (isRivals) { - return ; + return ; } if (mode === MODES.ON_APPROVAL && !isPendingPoint) { - return ; + return ; } if (mode === MODES.WORKING && isWorkingPoint) { - return ; + return ; } if (mode === MODES.PENDING && isPendingPoint) - return ; + return ; - return ; + return ; }; const MultipleFeaturesPopup = ({ features }) => { @@ -89,10 +89,10 @@ const YandexPanoramaLink = ({ lat, lng }) => { export const MapPopup = ({ features, lat, lng, onClose }) => { const getContent = () => { if (features.length === 1) { - return ; + return ; } - return ; + return ; }; return ( diff --git a/src/hooks/useLocalStorage.js b/src/hooks/useLocalStorage.js new file mode 100644 index 0000000..01f6d35 --- /dev/null +++ b/src/hooks/useLocalStorage.js @@ -0,0 +1,25 @@ +import { useState, useEffect } from "react"; + +const useLocalStorage = (key, defaultValue) => { + const [value, setValue] = useState(() => { + let currentValue; + + try { + currentValue = JSON.parse( + localStorage.getItem(key) || String(defaultValue) + ); + } catch (error) { + currentValue = defaultValue; + } + + return currentValue; + }); + + useEffect(() => { + localStorage.setItem(key, JSON.stringify(value)); + }, [value, key]); + + return [value, setValue]; +}; + +export default useLocalStorage; \ No newline at end of file diff --git a/src/modules/Table/HeaderWrapper.jsx b/src/modules/Table/HeaderWrapper.jsx index de1a562..f068fc7 100644 --- a/src/modules/Table/HeaderWrapper.jsx +++ b/src/modules/Table/HeaderWrapper.jsx @@ -3,6 +3,7 @@ import { Button, Tooltip } from "antd"; import { useTable } from "../../stores/useTable"; import { FullscreenExitOutlined, FullscreenOutlined } from "@ant-design/icons"; import { useEffect, useState } from "react"; +import { TableSettings } from "./TableSettings"; const ToggleFullScreenButton = () => { const { @@ -51,6 +52,7 @@ export const HeaderWrapper = ({ rightColumn, exportProvider, classes, + orderColumns }) => { return (
@@ -61,6 +63,7 @@ export const HeaderWrapper = ({
{rightColumn}
+ {exportProvider && }
diff --git a/src/modules/Table/OnApprovalTable/Header.jsx b/src/modules/Table/OnApprovalTable/Header.jsx index 7513e82..206bf11 100644 --- a/src/modules/Table/OnApprovalTable/Header.jsx +++ b/src/modules/Table/OnApprovalTable/Header.jsx @@ -10,6 +10,7 @@ export const Header = ({ selectedIds, onClearSelected, onOpenMakeWorkingModal, + orderColumns }) => { const [status, setStatus] = useState(STATUSES.pending); @@ -42,6 +43,7 @@ export const Header = ({ leftColumn: "flex items-center gap-x-4", rightColumn: "flex item-center gap-x-4", }} + orderColumns={orderColumns} exportProvider={useExportOnApprovalData} /> ); diff --git a/src/modules/Table/OnApprovalTable/OnApprovalTable.jsx b/src/modules/Table/OnApprovalTable/OnApprovalTable.jsx index c7bd27b..fe676b0 100644 --- a/src/modules/Table/OnApprovalTable/OnApprovalTable.jsx +++ b/src/modules/Table/OnApprovalTable/OnApprovalTable.jsx @@ -31,7 +31,7 @@ export const OnApprovalTable = ({ fullWidth }) => { } = useOnApprovalPointsFilters(); const [isMakeWorkingModalOpened, setIsMakeWorkingModalOpened] = useState(false); - const columns = useColumns(extraCols); + const { columns, defaultColumns, order, setOrder } = useColumns(extraCols, 'onApprovalTableOrder'); const { isVisible } = useLayersVisibility(); const clearSelected = () => setSelectedIds([]); @@ -94,6 +94,7 @@ export const OnApprovalTable = ({ fullWidth }) => { selectedIds={selectedIds} onClearSelected={clearSelected} onOpenMakeWorkingModal={() => setIsMakeWorkingModalOpened(true)} + orderColumns={{ defaultColumns, order, setOrder }} /> } rowSelection={canEdit ? rowSelection : undefined} diff --git a/src/modules/Table/PendingTable/PendingTable.jsx b/src/modules/Table/PendingTable/PendingTable.jsx index db74dd6..05cc3df 100644 --- a/src/modules/Table/PendingTable/PendingTable.jsx +++ b/src/modules/Table/PendingTable/PendingTable.jsx @@ -15,7 +15,7 @@ export const PendingTable = ({ fullWidth }) => { const { clickedPointConfig, setClickedPointConfig } = useClickedPointConfig(); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(PAGE_SIZE); - const columns = useColumns(); + const {columns, defaultColumns, order, setOrder} = useColumns([], 'pendingTableOrder'); const { setPopup } = usePopup(); const { data, isClickedPointLoading, isDataLoading } = usePendingTableData( @@ -79,7 +79,7 @@ export const PendingTable = ({ fullWidth }) => { isClickedPointLoading={isClickedPointLoading} columns={columns} fullWidth={fullWidth} - header={} + header={} loading={isDataLoading} /> ); diff --git a/src/modules/Table/TableSettings.jsx b/src/modules/Table/TableSettings.jsx new file mode 100644 index 0000000..c05e299 --- /dev/null +++ b/src/modules/Table/TableSettings.jsx @@ -0,0 +1,63 @@ +import {useState} from "react"; +import {Button, Dropdown} from "antd"; +import {SettingOutlined} from "@ant-design/icons"; +import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd"; + +export const TableSettings = ({orderColumns}) => { + const [columnsList, setColumnsList] = useState(orderColumns.order) + + const handleDrop = (droppedItem) => { + // Ignore drop outside droppable container + if (!droppedItem.destination) return; + var updatedList = [...columnsList]; + // Remove dragged item + const [reorderedItem] = updatedList.splice(droppedItem.source.index, 1); + // Add dropped item + updatedList.splice(droppedItem.destination.index, 0, reorderedItem); + // Update State + setColumnsList(updatedList); + orderColumns.setOrder(updatedList); + }; + + const columnsListRender = () => { + return ( +
e.stopPropagation()} className='z-10 bg-white-background rounded-xl p-3 space-y-3'> + + + {(provided) => ( +
+ {columnsList.map((item, index) => { + return ( + + {(provided) => ( +
+

+ { orderColumns.defaultColumns[item].title } +

+
+ )} +
+ ); + })} + {provided.placeholder} +
+ )} +
+
+
+ ) + } + + return ( + columnsListRender()} + > + + + ); +}; diff --git a/src/modules/Table/WorkingTable/WorkingTable.jsx b/src/modules/Table/WorkingTable/WorkingTable.jsx index 89b5f8b..636200c 100644 --- a/src/modules/Table/WorkingTable/WorkingTable.jsx +++ b/src/modules/Table/WorkingTable/WorkingTable.jsx @@ -16,7 +16,7 @@ export const WorkingTable = ({ fullWidth }) => { const { filters: { region, deltaTraffic, factTraffic, age }, } = useWorkingPointsFilters(); - const columns = useColumns(); + const {columns, defaultColumns, order, setOrder} = useColumns('workingTableOrder'); const { data, isInitialLoading } = useQuery( ["working-points", page, region, deltaTraffic, factTraffic, age], @@ -51,7 +51,7 @@ export const WorkingTable = ({ fullWidth }) => { isClickedPointLoading={isClickedPointLoading} columns={columns} fullWidth={fullWidth} - header={} + header={} loading={isInitialLoading} /> ); diff --git a/src/modules/Table/WorkingTable/useColumns.jsx b/src/modules/Table/WorkingTable/useColumns.jsx index d988161..7994494 100644 --- a/src/modules/Table/WorkingTable/useColumns.jsx +++ b/src/modules/Table/WorkingTable/useColumns.jsx @@ -5,14 +5,18 @@ 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"; -export const useColumns = () => { +const DEFAULT_LENGTH = 11; +export const useColumns = ({ key }) => { const { data: regions } = useGetRegions(); const { tableState: { fullScreen }, } = useTable(); - return useMemo(() => { + const [order, setOrder] = useLocalStorage(key, [...Array(DEFAULT_LENGTH).keys()]) + + const defaultColumns = useMemo(() => { return [ { title: fullScreen ? ( @@ -118,4 +122,12 @@ export const useColumns = () => { }, ]; }, [regions?.normalized, fullScreen]); + + const columns = useMemo(() => { + return order.map((item) => { + return defaultColumns[item]; + }) + }, [defaultColumns, order, fullScreen]); + + return {columns, defaultColumns, order, setOrder}; }; diff --git a/src/modules/Table/useColumns.jsx b/src/modules/Table/useColumns.jsx index e5a3614..2ada99c 100644 --- a/src/modules/Table/useColumns.jsx +++ b/src/modules/Table/useColumns.jsx @@ -6,14 +6,18 @@ import { Button, Popover } from "antd"; import { AddressSearch } from "../../Map/AddressSearch.jsx"; import { SearchOutlined } from "@ant-design/icons"; import { useTable } from "../../stores/useTable.js"; +import useLocalStorage from "../../hooks/useLocalStorage.js"; -export const useColumns = (fields = []) => { +const DEFAULT_LENGTH = 7; +export const useColumns = (fields = [], key) => { const { data: regions } = useGetRegions(); const { tableState: { fullScreen }, } = useTable(); - return useMemo(() => { + const [order, setOrder] = useLocalStorage(key, [...Array(DEFAULT_LENGTH + fields.length).keys()]) + + const defaultColumns = useMemo(() => { return [ { title: fullScreen ? ( @@ -90,4 +94,12 @@ export const useColumns = (fields = []) => { ...fields, ]; }, [regions?.normalized, fields, fullScreen]); + + const columns = useMemo(() => { + return order.map((item) => { + return defaultColumns[item]; + }) + }, [defaultColumns, order, fullScreen]); + + return {columns, defaultColumns, order, setOrder}; };