From c13d4047769a6b7918b25b20c72cc7c4d70673eb Mon Sep 17 00:00:00 2001 From: Platon Yasev Date: Sun, 26 Feb 2023 23:57:37 +0300 Subject: [PATCH] Disable filters after manual edits --- src/Map/Points.jsx | 18 +++++-- src/Map/Popup.jsx | 4 ++ src/modules/Sidebar/ObjectTypesSelect.jsx | 7 ++- src/modules/Sidebar/PredictionSlider.jsx | 3 ++ src/modules/Sidebar/Sidebar.jsx | 16 ++++++ src/modules/Table/Table.jsx | 63 ++++++++++++----------- src/stores/usePointSelection.js | 15 ++++++ 7 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/Map/Points.jsx b/src/Map/Points.jsx index 95b199f..7437f34 100644 --- a/src/Map/Points.jsx +++ b/src/Map/Points.jsx @@ -8,7 +8,7 @@ import { usePointSelection } from "../stores/usePointSelection"; export const Points = () => { const { isVisible } = useLayersVisibility(); const { filters } = useFilters(); - const { prediction, status } = filters; + const { prediction, status, categories } = filters; const { selection } = usePointSelection(); const includedArr = [...selection.included]; const excludedArr = [...selection.excluded]; @@ -20,18 +20,30 @@ export const Points = () => { ["<=", ["get", "prediction_current"], prediction[1]], ]; const statusExpression = ["in", ["get", "status"], ["literal", status]]; + const categoryExpression = + categories.length > 0 + ? ["in", ["get", "category"], ["literal", categories]] + : true; const matchFilterExpression = [ "all", statusExpression, ["!", excludedExpression], - ["any", ["all", ...predictionExpression], includedExpression], + [ + "any", + ["all", ...predictionExpression, categoryExpression], + includedExpression, + ], ]; const unmatchFilterExpression = [ "all", statusExpression, - ["any", excludedExpression, ["!", ["all", ...predictionExpression]]], + [ + "any", + excludedExpression, + ["!", ["all", ...predictionExpression, categoryExpression]], + ], ]; return ( diff --git a/src/Map/Popup.jsx b/src/Map/Popup.jsx index c84a0c8..4fff60f 100644 --- a/src/Map/Popup.jsx +++ b/src/Map/Popup.jsx @@ -5,6 +5,10 @@ import { usePointSelection } from "../stores/usePointSelection"; import { useState } from "react"; const popupConfig = [ + { + field: "id", + name: "id", + }, { field: "name", name: "Название", diff --git a/src/modules/Sidebar/ObjectTypesSelect.jsx b/src/modules/Sidebar/ObjectTypesSelect.jsx index 7e25595..2e48c51 100644 --- a/src/modules/Sidebar/ObjectTypesSelect.jsx +++ b/src/modules/Sidebar/ObjectTypesSelect.jsx @@ -2,6 +2,7 @@ import { Button } from "antd"; import { twMerge } from "tailwind-merge"; import { Title } from "../../components/Title"; import { useFilters } from "../../stores/useFilters"; +import { useHasManualEdits } from "../../stores/usePointSelection"; //kiosk - городские киоски // mfc - многофункциональные центры предоставления государственных и муниципальных услуг @@ -19,7 +20,7 @@ const types = [ "Дом культуры/Клуб", ]; -const SelectItem = ({ name, isActive, onClick }) => { +const SelectItem = ({ name, isActive, onClick, disabled }) => { return ( @@ -37,6 +39,7 @@ const SelectItem = ({ name, isActive, onClick }) => { export const ObjectTypesSelect = () => { const { filters, setCategories } = useFilters(); + const hasManualEdits = useHasManualEdits(); const handleClick = (category) => setCategories(category); @@ -51,6 +54,7 @@ export const ObjectTypesSelect = () => { type="text" className="text-grey text-xs p-0 hover:bg-transparent active:bg-transparent focus:bg-transparent h-fit" onClick={clear} + disabled={hasManualEdits} > сбросить @@ -64,6 +68,7 @@ export const ObjectTypesSelect = () => { name={type} isActive={filters.categories.includes(type)} onClick={() => handleClick(type)} + disabled={hasManualEdits} /> ))} diff --git a/src/modules/Sidebar/PredictionSlider.jsx b/src/modules/Sidebar/PredictionSlider.jsx index 5961b16..f5da42d 100644 --- a/src/modules/Sidebar/PredictionSlider.jsx +++ b/src/modules/Sidebar/PredictionSlider.jsx @@ -3,9 +3,11 @@ import { useFilters } from "../../stores/useFilters"; import { useQuery } from "@tanstack/react-query"; import { api } from "../../api"; import { useEffect } from "react"; +import { useHasManualEdits } from "../../stores/usePointSelection"; export const PredictionSlider = () => { const { filters, setPrediction } = useFilters(); + const hasManualEdits = useHasManualEdits(); const { data } = useQuery(["max-min"], async () => { const { data } = await api.get(`/api/placement_points/filters`); @@ -33,6 +35,7 @@ export const PredictionSlider = () => { min={200} max={299} range + disabled={hasManualEdits} /> ); }; diff --git a/src/modules/Sidebar/Sidebar.jsx b/src/modules/Sidebar/Sidebar.jsx index 66cd18f..59820b9 100644 --- a/src/modules/Sidebar/Sidebar.jsx +++ b/src/modules/Sidebar/Sidebar.jsx @@ -6,6 +6,10 @@ import { LayersVisibility } from "./LayersVisibility"; import { useState } from "react"; import { api } from "../../api"; import { useFilters } from "../../stores/useFilters"; +import { + useHasManualEdits, + usePointSelection, +} from "../../stores/usePointSelection"; function download(filename, data) { const downloadLink = window.document.createElement("a"); @@ -38,6 +42,8 @@ export const Sidebar = () => { } = useFilters(); const [isExporting, setIsExporting] = useState(false); + const hasManualEdits = useHasManualEdits(); + const { reset: resetSelection } = usePointSelection(); const handleExport = async () => { setIsExporting(true); @@ -97,6 +103,16 @@ export const Sidebar = () => { + {hasManualEdits ? ( + + ) : null} diff --git a/src/modules/Table/Table.jsx b/src/modules/Table/Table.jsx index 2340e50..4a8264d 100644 --- a/src/modules/Table/Table.jsx +++ b/src/modules/Table/Table.jsx @@ -32,39 +32,39 @@ const columns = [ }, { title: "Прогноз", - dataIndex: "prediction_first", - key: "prediction_first", - width: "120px", - ellipsis: true, - }, - { - title: "Зрелость", - dataIndex: "age", - key: "age", - width: "120px", - ellipsis: true, - }, - { - title: "План", - dataIndex: "plan", - key: "plan", - width: "120px", - ellipsis: true, - }, - { - title: "Факт", - dataIndex: "fact", - key: "fact", - width: "120px", - ellipsis: true, - }, - { - title: "Дельта", - dataIndex: "delta", - key: "delta", + dataIndex: "prediction_current", + key: "prediction_current", width: "120px", ellipsis: true, }, + // { + // title: "Зрелость", + // dataIndex: "age", + // key: "age", + // width: "120px", + // ellipsis: true, + // }, + // { + // title: "План", + // dataIndex: "plan", + // key: "plan", + // width: "120px", + // ellipsis: true, + // }, + // { + // title: "Факт", + // dataIndex: "fact", + // key: "fact", + // width: "120px", + // ellipsis: true, + // }, + // { + // title: "Дельта", + // dataIndex: "delta", + // key: "delta", + // width: "120px", + // ellipsis: true, + // }, { title: "АО", dataIndex: "okrug", @@ -89,7 +89,7 @@ export const Table = React.memo(({ height = 200 }) => { const [page, setPage] = useState(1); const { filters } = useFilters(); - const { prediction, status } = filters; + const { prediction, status, categories } = filters; const { include, selection, exclude } = usePointSelection(); const { data } = useQuery( @@ -100,6 +100,7 @@ export const Table = React.memo(({ height = 200 }) => { page_size: PAGE_SIZE, "prediction_current[]": prediction, "status[]": status, + "categories[]": categories, "included[]": [...selection.included], "excluded[]": [...selection.excluded], }); diff --git a/src/stores/usePointSelection.js b/src/stores/usePointSelection.js index bb28dac..b5db9ef 100644 --- a/src/stores/usePointSelection.js +++ b/src/stores/usePointSelection.js @@ -1,5 +1,6 @@ import { create } from "zustand"; import { immer } from "zustand/middleware/immer"; +import { useMemo } from "react"; const INITIAL = { included: new Set([]), @@ -29,6 +30,20 @@ const store = (set) => ({ } }); }, + + reset: () => + set((state) => { + state.selection.included.clear(); + state.selection.excluded.clear(); + }), }); export const usePointSelection = create(immer(store)); + +export const useHasManualEdits = () => { + const { selection } = usePointSelection(); + return useMemo( + () => selection.included.size || selection.excluded.size, + [selection] + ); +};