Use eng statuses and show other layers

dev
Platon Yasev 3 years ago
parent 85f94a5070
commit e86255756a

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
dist/index.html vendored

@ -1,16 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta charset="UTF-8"/>
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
<link href="/favicon.ico" rel="icon"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>PostNet by Spatial</title>
<script type="module" crossorigin src="/assets/index.24e33a70.js"></script>
<link rel="stylesheet" href="/assets/index.9d2c87bd.css">
<script crossorigin src="/assets/index.297e7fbd.js" type="module"></script>
<link href="/assets/index.ca3dcc1b.css" rel="stylesheet">
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,32 @@
import { Layer } from "react-map-gl";
import { cancelledPointLayer } from "./layers-config";
import { useLayersVisibility } from "../../stores/useLayersVisibility";
import { STATUSES } from "../../config";
import { useRegionFilterExpression } from "./useRegionFilterExpression";
import { LAYER_IDS } from "./constants";
const statusExpression = ["==", ["get", "status"], STATUSES.cancelled];
export const CancelledPoints = () => {
const { isVisible } = useLayersVisibility();
const regionFilterExpression = useRegionFilterExpression();
const filter = regionFilterExpression
? ["all", statusExpression, regionFilterExpression]
: statusExpression;
return (
<>
<Layer
{...cancelledPointLayer}
id={LAYER_IDS.cancelled}
source={"points"}
source-layer={"public.service_placementpoint"}
layout={{
visibility: isVisible[LAYER_IDS.cancelled] ? "visible" : "none",
}}
filter={filter}
/>
</>
);
};

@ -3,6 +3,8 @@ import { Layer, Source } from "react-map-gl";
import { aoLayer, rayonLayer, selectedRegionLayer } from "./layers-config";
import { useFilters } from "../../stores/useFilters";
import { BASE_URL } from "../../api";
import { PVZ } from "./PVZ";
import { OtherPostamates } from "./OtherPostamates";
export const Layers = () => {
const {
@ -50,6 +52,14 @@ export const Layers = () => {
)}
<Points prediction={prediction} />
<Source
id="rivals"
type="vector"
tiles={[`${BASE_URL}/martin/public.service_rivals/{z}/{x}/{y}.pbf`]}
>
<PVZ />
<OtherPostamates />
</Source>
</>
);
};

@ -0,0 +1,22 @@
import { Layer } from "react-map-gl";
import { otherPostamatesLayer } from "./layers-config";
import { useLayersVisibility } from "../../stores/useLayersVisibility";
import { LAYER_IDS } from "./constants";
export const OtherPostamates = () => {
const { isVisible } = useLayersVisibility();
return (
<>
<Layer
{...otherPostamatesLayer}
id={LAYER_IDS.other}
source={"rivals"}
source-layer={"public.service_rivals"}
layout={{
visibility: isVisible[LAYER_IDS.other] ? "visible" : "none",
}}
/>
</>
);
};

@ -0,0 +1,22 @@
import { Layer } from "react-map-gl";
import { pvzPointLayer } from "./layers-config";
import { useLayersVisibility } from "../../stores/useLayersVisibility";
import { LAYER_IDS } from "./constants";
export const PVZ = () => {
const { isVisible } = useLayersVisibility();
return (
<>
<Layer
{...pvzPointLayer}
id={LAYER_IDS.pvz}
source={"rivals"}
source-layer={"public.service_rivals"}
layout={{
visibility: isVisible[LAYER_IDS.pvz] ? "visible" : "none",
}}
/>
</>
);
};

@ -5,6 +5,7 @@ import { InitialPoints } from "./InitialPoints";
import { ApprovePoints } from "./ApprovePoints";
import { WorkingPoints } from "./WorkingPoints";
import { FilteredWorkingPoints } from "./FilteredWorkingPoints";
import { CancelledPoints } from "./CancelledPoints";
export const Points = () => {
const { updateCounter } = useUpdateLayerCounter();
@ -23,6 +24,7 @@ export const Points = () => {
<ApprovePoints />
<WorkingPoints />
<FilteredWorkingPoints />
<CancelledPoints />
</Source>
</>
);

@ -7,4 +7,6 @@ export const LAYER_IDS = {
filteredWorking: "filtered-working-points",
cancelled: "cancelled-points",
atd: "atd",
pvz: "pvz",
other: "other",
};

@ -1,11 +1,13 @@
const POINT_SIZE = 5;
const UNMATCH_POINT_SIZE = 3;
export const INITIAL_COLOR = "#CC2222";
export const INITIAL_COLOR = "#001cd2";
export const CANCELLED_COLOR = "#CC2222";
export const APPROVE_COLOR = "#ff7d00";
export const WORKING_COLOR = "#006e01";
export const UNMATCHED_COLOR = "#b4b4b4";
export const PVZ_COLOR = "#da11b2";
export const OTHER_POSTAMATES_COLOR = "#26a2a2";
const DEFAULT_POINT_CONFIG = {
type: "circle",
@ -35,6 +37,8 @@ export const unmatchInitialPointLayer = getPointConfig(
export const approvePointLayer = getPointConfig(APPROVE_COLOR);
export const workingPointLayer = getPointConfig(WORKING_COLOR);
export const cancelledPointLayer = getPointConfig(CANCELLED_COLOR);
export const pvzPointLayer = getPointConfig(PVZ_COLOR);
export const otherPostamatesLayer = getPointConfig(OTHER_POSTAMATES_COLOR);
const regionColor = "#676767";

@ -1,36 +1,58 @@
import { Title } from "../../components/Title";
import { useLayersVisibility } from "../../stores/useLayersVisibility";
import { useMode } from "../../stores/useMode";
import Checkbox from "antd/es/checkbox/Checkbox";
import { MODES } from "../../config";
import { LAYER_IDS } from "../Layers/constants";
export const LayersVisibility = () => {
const { toggleVisibility, isVisible } = useLayersVisibility();
const { mode } = useMode();
return (
<div>
<Title text={"Слои"} className={"mb-1"} />
<div className={"space-y-1 flex flex-col"}>
{/*{mode === MODES.INITIAL && (*/}
{/* <Checkbox*/}
{/* onChange={() => toggleVisibility(LAYER_IDS.initial)}*/}
{/* checked={isVisible[LAYER_IDS.initial]}*/}
{/* >*/}
{/* Локации к рассмотрению*/}
{/* </Checkbox>*/}
{/*)}*/}
{/*{mode === MODES.WORKING && (*/}
{/* <>*/}
{/* <Checkbox*/}
{/* className={"!ml-0"}*/}
{/* onChange={() => toggleVisibility(LAYER_IDS.working)}*/}
{/* checked={isVisible[LAYER_IDS.working]}*/}
{/* >*/}
{/* Работает*/}
{/* </Checkbox>*/}
{/* </>*/}
{/*)}*/}
</div>
<div className={"space-y-1 flex flex-col"}>
{mode === MODES.INITIAL && (
<>
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.working)}
checked={isVisible[LAYER_IDS.working]}
>
Работающие постаматы
</Checkbox>
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.cancelled)}
checked={isVisible[LAYER_IDS.cancelled]}
>
Отмененные локации
</Checkbox>
</>
)}
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.pvz)}
checked={isVisible[LAYER_IDS.pvz]}
>
ПВЗ
</Checkbox>
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.other)}
checked={isVisible[LAYER_IDS.other]}
>
Постаматы прочих сетей
</Checkbox>
{/*{mode === MODES.WORKING && (*/}
{/* <>*/}
{/* <Checkbox*/}
{/* className={"!ml-0"}*/}
{/* onChange={() => toggleVisibility(LAYER_IDS.working)}*/}
{/* checked={isVisible[LAYER_IDS.working]}*/}
{/* >*/}
{/* Работает*/}
{/* </Checkbox>*/}
{/* </>*/}
{/*)}*/}
</div>
);
};

@ -1,6 +1,13 @@
import { useMode } from "../stores/useMode";
import { MODES } from "../config";
import { APPROVE_COLOR, WORKING_COLOR } from "./Layers/layers-config";
import {
APPROVE_COLOR,
CANCELLED_COLOR,
INITIAL_COLOR,
OTHER_POSTAMATES_COLOR,
PVZ_COLOR,
WORKING_COLOR,
} from "./Layers/layers-config";
import { Title } from "../components/Title";
const LegendPointItem = ({ color, name }) => {
@ -18,28 +25,43 @@ const LegendPointItem = ({ color, name }) => {
export function Legend() {
const { mode } = useMode();
const getContent = () => {
if (mode === MODES.APPROVE_WORKING) {
return (
<>
<Title text={"Статус локации"} className={"text-center"} />
<div className="space-y-2">
<LegendPointItem
name="Согласование-установка"
color={APPROVE_COLOR}
/>
<LegendPointItem name="Работает" color={WORKING_COLOR} />
return (
<div className="absolute bottom-[20px] left-[20px] text-xs text-grey z-10 bg-white-background rounded-xl p-3 space-y-3">
{mode !== MODES.WORKING && (
<div>
<Title text={"Статус локации"} className="text-center" />
<div className="space-y-1">
{mode === MODES.INITIAL && (
<>
<LegendPointItem name="К рассмотрению" color={INITIAL_COLOR} />
<LegendPointItem name="Работает" color={WORKING_COLOR} />
<LegendPointItem name="Отменен" color={CANCELLED_COLOR} />
</>
)}
{mode === MODES.APPROVE_WORKING && (
<>
<LegendPointItem
name="Согласование-установка"
color={APPROVE_COLOR}
/>
<LegendPointItem name="Работает" color={WORKING_COLOR} />
<LegendPointItem name="Отменен" color={CANCELLED_COLOR} />
</>
)}
</div>
</>
);
}
return null;
};
</div>
)}
return (
<div className="absolute bottom-[20px] left-[20px] text-xs text-grey z-10 bg-white-background rounded-xl p-3">
{getContent()}
<div>
<Title text={"Прочее"} className="text-center" />
<div className="space-y-1">
<LegendPointItem name="ПВЗ" color={PVZ_COLOR} />
<LegendPointItem
name="Постаматы прочих сетей"
color={OTHER_POSTAMATES_COLOR}
/>
</div>
</div>
</div>
);
}

@ -140,6 +140,8 @@ export const MapComponent = () => {
LAYER_IDS["initial-unmatch"],
LAYER_IDS.approve,
LAYER_IDS.working,
LAYER_IDS.cancelled,
LAYER_IDS.pvz,
]}
onClick={handleClick}
onMouseEnter={handleMouseEnter}

@ -7,9 +7,19 @@ import { PopupWrapper } from "./PopupWrapper";
import { InitialPointPopup } from "./mode-popup/InitialPointPopup";
import { ApproveWorkingPointPopup } from "./mode-popup/ApproveWorkingPointPopup";
import { WorkingPointPopup } from "./mode-popup/WorkingPointPopup";
import { FeatureProperties } from "./mode-popup/FeatureProperties";
const SingleFeaturePopup = ({ feature }) => {
const { mode } = useMode();
const isRivals =
feature.layer.id === LAYER_IDS.pvz || feature.layer.id === LAYER_IDS.other;
const isInitialLayer =
feature.layer.id === LAYER_IDS["initial-match"] ||
feature.layer.id === LAYER_IDS["initial-unmatch"];
if (isRivals) {
return <FeatureProperties feature={feature} />;
}
if (mode === MODES.APPROVE_WORKING) {
return <ApproveWorkingPointPopup feature={feature} />;
@ -19,7 +29,10 @@ const SingleFeaturePopup = ({ feature }) => {
return <WorkingPointPopup feature={feature} />;
}
return <InitialPointPopup feature={feature} />;
if (mode === MODES.INITIAL && isInitialLayer)
return <InitialPointPopup feature={feature} />;
return <FeatureProperties feature={feature} />;
};
const MultipleFeaturesPopup = ({ features, onSelect }) => {

@ -2,9 +2,9 @@ import { useClickedPointConfig } from "../../../stores/useClickedPointConfig";
import { useEffect, useState } from "react";
import { FeatureProperties } from "./FeatureProperties";
import { Title } from "../../../components/Title";
import { StatusSelect } from "../../../modules/Table/ApproveAndWorkingTable/ApproveAndWorkingTable";
import { useQueryClient } from "@tanstack/react-query";
import { useUpdateStatus } from "../../../hooks/useUpdateStatus";
import { StatusSelect } from "../../../components/StatusSelect";
export const ApproveWorkingPointPopup = ({ feature }) => {
const featureId = feature.properties.id;

@ -17,18 +17,19 @@ export const FeatureProperties = ({ feature, dynamicStatus }) => {
return (
<div>
{finalConfig.map(({ field, name }) => {
{finalConfig.map(({ field, name, render }) => {
const value =
dynamicStatus && field === "status"
? dynamicStatus
: feature.properties[field];
const renderedValue = render ? render(value) : value;
return (
<Row className={twMerge("p-1")} key={field}>
<Col className={"font-semibold"} span={12}>
{name}
</Col>
<Col span={12}>{value}</Col>
<Col span={12}>{renderedValue}</Col>
</Row>
);
})}

@ -8,5 +8,5 @@ export const WorkingPointPopup = ({ feature }) => {
useEffect(() => setClickedPointConfig(featureId, false), [feature]);
return <FeatureProperties feature={feature} dynamicStatus={status} />;
return <FeatureProperties feature={feature} />;
};

@ -1,3 +1,5 @@
import { STATUS_LABEL_MAPPER } from "../../../config";
export const popupConfig = [
{
name: "Id",
@ -26,6 +28,7 @@ export const popupConfig = [
{
name: "Статус",
field: "status",
render: (value) => STATUS_LABEL_MAPPER[value],
},
{
name: "Прогнозный трафик",
@ -61,6 +64,7 @@ export const residentialPointConfig = [
{
name: "Статус",
field: "status",
render: (value) => STATUS_LABEL_MAPPER[value],
},
{
name: "Прогнозный трафик",

@ -0,0 +1,31 @@
import { Select } from "antd";
import { STATUS_LABEL_MAPPER, STATUSES } from "../config";
const statusOptions = [
{ label: STATUS_LABEL_MAPPER[STATUSES.initial], value: STATUSES.initial },
{ label: STATUS_LABEL_MAPPER[STATUSES.approve], value: STATUSES.approve },
{ label: STATUS_LABEL_MAPPER[STATUSES.working], value: STATUSES.working },
{ label: STATUS_LABEL_MAPPER[STATUSES.cancelled], value: STATUSES.cancelled },
];
export const StatusSelect = ({ value, onChange, disabled }) => {
const handleClick = (e) => e.stopPropagation();
const handleChange = (value) => {
onChange(value);
};
return (
<Select
style={{
width: 250,
}}
value={value}
onChange={handleChange}
options={statusOptions}
disabled={disabled}
placeholder="Выберите статус"
onClick={handleClick}
/>
);
};

@ -1,10 +1,17 @@
import { LAYER_IDS } from "./Map/Layers/constants";
export const STATUSES = {
initial: "К рассмотрению",
approve: "Согласование-установка",
working: "Работает",
cancelled: "Отменено",
initial: "Pending",
approve: "Installation",
working: "Working",
cancelled: "Cancelled",
};
export const STATUS_LABEL_MAPPER = {
[STATUSES.initial]: "К рассмотрению",
[STATUSES.approve]: "Согласование-установка",
[STATUSES.working]: "Работает",
[STATUSES.cancelled]: "Отменен",
};
export const CATEGORIES = {
@ -33,7 +40,11 @@ export const MODE_TO_STATUS_MAPPER = {
};
export const MODE_TO_LAYER_VISIBILITY_MAPPER = {
[MODES.INITIAL]: [LAYER_IDS.initial],
[MODES.APPROVE_WORKING]: [LAYER_IDS.approve, LAYER_IDS.working],
[MODES.INITIAL]: [LAYER_IDS.initial, LAYER_IDS.working, LAYER_IDS.cancelled],
[MODES.APPROVE_WORKING]: [
LAYER_IDS.approve,
LAYER_IDS.working,
LAYER_IDS.cancelled,
],
[MODES.WORKING]: [LAYER_IDS.filteredWorking],
};

@ -49,6 +49,13 @@ export const Sidebar = forwardRef(({ isCollapsed }, ref) => {
>
Работает
</Checkbox>
<Checkbox
className={"!ml-0"}
onChange={() => toggleVisibility(LAYER_IDS.cancelled)}
checked={isVisible[LAYER_IDS.cancelled]}
>
Отменен
</Checkbox>
</div>
</div>
)}

@ -6,40 +6,13 @@ import { useCallback, useState } from "react";
import { PAGE_SIZE } from "../constants";
import { STATUSES } from "../../../config";
import { useMergeTableData } from "../useMergeTableData";
import { Button, Select } from "antd";
import { Button } from "antd";
import { useUpdateStatus } from "../../../hooks/useUpdateStatus";
import { HeaderWrapper } from "../HeaderWrapper";
import { useExportApproveAndWorkingData } from "./useExportApproveAndWorkingData";
import { useFilters } from "../../../stores/useFilters";
import { usePopup } from "../../../stores/usePopup";
const statusOptions = [
{ label: STATUSES.approve, value: STATUSES.approve },
{ label: STATUSES.working, value: STATUSES.working },
{ label: STATUSES.initial, value: STATUSES.initial },
];
export const StatusSelect = ({ value, onChange, disabled }) => {
const handleClick = (e) => e.stopPropagation();
const handleChange = (value) => {
onChange(value);
};
return (
<Select
style={{
width: 250,
}}
value={value}
onChange={handleChange}
options={statusOptions}
disabled={disabled}
placeholder="Выберите статус"
onClick={handleClick}
/>
);
};
import { StatusSelect } from "../../../components/StatusSelect";
const ChangeStatusButton = ({ selectedIds, selectedStatus }) => {
const queryClient = useQueryClient();
@ -71,7 +44,7 @@ const ChangeStatusButton = ({ selectedIds, selectedStatus }) => {
};
const Header = ({ selectedIds, onClearSelected }) => {
const [status, setStatus] = useState(STATUSES.approve);
const [status, setStatus] = useState(STATUSES.initial);
const handleClear = (e) => {
e.stopPropagation();
@ -121,7 +94,7 @@ export const ApproveAndWorkingTable = ({ fullWidth }) => {
const params = new URLSearchParams({
page,
page_size: pageSize,
"status[]": [STATUSES.approve, STATUSES.working],
"status[]": [STATUSES.approve, STATUSES.working, STATUSES.cancelled],
});
return await getPoints(params, region);

@ -1,3 +1,5 @@
import { STATUS_LABEL_MAPPER } from "../../../config";
export const columns = [
{
title: "Адрес",
@ -39,6 +41,9 @@ export const columns = [
key: "status",
width: "120px",
ellipsis: true,
render: (_, record) => {
return STATUS_LABEL_MAPPER[record.status];
},
},
{
title: "Прогнозный трафик",

@ -8,8 +8,12 @@ const INITIAL_STATE = {
[LAYER_IDS.working]: false,
[LAYER_IDS.filteredWorking]: false,
[LAYER_IDS.cancelled]: false,
[LAYER_IDS.pvz]: true,
[LAYER_IDS.other]: true,
};
const STATIC_LAYERS = [LAYER_IDS.pvz, LAYER_IDS.other];
const store = (set) => ({
isVisible: INITIAL_STATE,
@ -24,7 +28,7 @@ const store = (set) => ({
state.isVisible[layerId] = true;
});
const invisibleLayersIds = Object.keys(state.isVisible).filter(
(l) => !visibleLayerIds.includes(l)
(l) => !visibleLayerIds.includes(l) && !STATIC_LAYERS.includes(l)
);
invisibleLayersIds.forEach((layerId) => {
state.isVisible[layerId] = false;

Loading…
Cancel
Save