feat: add loader for saving route and description for stations
This commit is contained in:
@@ -1,4 +1,12 @@
|
|||||||
import { Button, Stack, TextField, Typography, Slider } from "@mui/material";
|
import {
|
||||||
|
Button,
|
||||||
|
Stack,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
Slider,
|
||||||
|
CircularProgress,
|
||||||
|
Box,
|
||||||
|
} from "@mui/material";
|
||||||
import { useMapData } from "./MapDataContext";
|
import { useMapData } from "./MapDataContext";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTransform } from "./TransformContext";
|
import { useTransform } from "./TransformContext";
|
||||||
@@ -28,6 +36,7 @@ export function RightSidebar() {
|
|||||||
const [isUserEditing, setIsUserEditing] = useState<boolean>(false);
|
const [isUserEditing, setIsUserEditing] = useState<boolean>(false);
|
||||||
const [iconSize, setIconSize] = useState<number>(100);
|
const [iconSize, setIconSize] = useState<number>(100);
|
||||||
const [fontSize, setFontSize] = useState<number>(100);
|
const [fontSize, setFontSize] = useState<number>(100);
|
||||||
|
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (originalRouteData) {
|
if (originalRouteData) {
|
||||||
@@ -150,11 +159,19 @@ export function RightSidebar() {
|
|||||||
newMinScale = 10;
|
newMinScale = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newMinScale > 300) {
|
||||||
|
newMinScale = 297;
|
||||||
|
}
|
||||||
|
|
||||||
setMinScale(newMinScale);
|
setMinScale(newMinScale);
|
||||||
|
|
||||||
if (maxScale - newMinScale < 2) {
|
if (maxScale - newMinScale < 2) {
|
||||||
let newMaxScale = newMinScale + 2;
|
let newMaxScale = newMinScale + 2;
|
||||||
|
|
||||||
|
if (newMaxScale > 300) {
|
||||||
|
newMaxScale = 300;
|
||||||
|
}
|
||||||
|
|
||||||
if (newMaxScale < 3) {
|
if (newMaxScale < 3) {
|
||||||
newMaxScale = 3;
|
newMaxScale = 3;
|
||||||
setMinScale(1);
|
setMinScale(1);
|
||||||
@@ -443,18 +460,35 @@ export function RightSidebar() {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
sx={{ mt: 2 }}
|
sx={{ mt: 2, position: "relative" }}
|
||||||
|
disabled={isSaving}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
await saveChanges();
|
await saveChanges();
|
||||||
toast.success("Изменения сохранены");
|
toast.success("Изменения сохранены");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
toast.error("Ошибка при сохранении изменений");
|
toast.error("Ошибка при сохранении изменений");
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Сохранить изменения
|
{isSaving ? (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress size={20} sx={{ color: "inherit" }} />
|
||||||
|
<span>Сохранение...</span>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
"Сохранить изменения"
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -1382,13 +1382,78 @@ export const WebGLRouteMapPrototype = observer(() => {
|
|||||||
skipNextAutoFitRef.current = false;
|
skipNextAutoFitRef.current = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetTransform();
|
|
||||||
|
const currentTransform = transformRef.current ?? lastTransformRef.current;
|
||||||
|
if (!currentTransform) {
|
||||||
|
resetTransform();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
if (!canvas || canvas.width === 0 || canvas.height === 0) {
|
||||||
|
resetTransform();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const preservedScale = currentTransform.scale;
|
||||||
|
|
||||||
|
const centerX = canvas.width / 2;
|
||||||
|
const centerY = canvas.height / 2;
|
||||||
|
|
||||||
|
const worldCenterX =
|
||||||
|
(centerX - currentTransform.translation.x) / preservedScale;
|
||||||
|
const worldCenterY =
|
||||||
|
(centerY - currentTransform.translation.y) / preservedScale;
|
||||||
|
|
||||||
|
const centerLat =
|
||||||
|
routeData?.center_latitude ?? originalRouteData?.center_latitude;
|
||||||
|
const centerLon =
|
||||||
|
routeData?.center_longitude ?? originalRouteData?.center_longitude;
|
||||||
|
|
||||||
|
if (Number.isFinite(centerLat) && Number.isFinite(centerLon)) {
|
||||||
|
const local = coordinatesToLocal(
|
||||||
|
centerLat as number,
|
||||||
|
centerLon as number
|
||||||
|
);
|
||||||
|
const baseX = local.x * UP_SCALE;
|
||||||
|
const baseY = local.y * UP_SCALE;
|
||||||
|
const cos = Math.cos(rotationAngle);
|
||||||
|
const sin = Math.sin(rotationAngle);
|
||||||
|
const rotatedX = baseX * cos - baseY * sin;
|
||||||
|
const rotatedY = baseX * sin + baseY * cos;
|
||||||
|
|
||||||
|
const updatedTransform: Transform = {
|
||||||
|
scale: preservedScale,
|
||||||
|
translation: {
|
||||||
|
x: centerX - rotatedX * preservedScale,
|
||||||
|
y: centerY - rotatedY * preservedScale,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
transformRef.current = updatedTransform;
|
||||||
|
lastTransformRef.current = updatedTransform;
|
||||||
|
setTransformState(updatedTransform);
|
||||||
|
drawSceneRef.current();
|
||||||
|
} else {
|
||||||
|
const updatedTransform: Transform = {
|
||||||
|
scale: preservedScale,
|
||||||
|
translation: {
|
||||||
|
x: centerX - worldCenterX * preservedScale,
|
||||||
|
y: centerY - worldCenterY * preservedScale,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
transformRef.current = updatedTransform;
|
||||||
|
lastTransformRef.current = updatedTransform;
|
||||||
|
setTransformState(updatedTransform);
|
||||||
|
drawSceneRef.current();
|
||||||
|
}
|
||||||
}, [
|
}, [
|
||||||
routeVertices,
|
|
||||||
stationVertices,
|
|
||||||
canvasSize.width,
|
|
||||||
canvasSize.height,
|
|
||||||
rotationAngle,
|
rotationAngle,
|
||||||
|
routeData?.center_latitude,
|
||||||
|
routeData?.center_longitude,
|
||||||
|
originalRouteData?.center_latitude,
|
||||||
|
originalRouteData?.center_longitude,
|
||||||
resetTransform,
|
resetTransform,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,10 @@ export const InformationTab = observer(
|
|||||||
{sight.common.id !== 0 && (
|
{sight.common.id !== 0 && (
|
||||||
<LinkedStations
|
<LinkedStations
|
||||||
parentId={sight.common.id}
|
parentId={sight.common.id}
|
||||||
fields={[{ label: "Название", data: "name" }]}
|
fields={[
|
||||||
|
{ label: "Название", data: "name" },
|
||||||
|
{ label: "Описание", data: "description" },
|
||||||
|
]}
|
||||||
type="edit"
|
type="edit"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user