fix: Fix webp + delete ctrl z + filter by city
This commit is contained in:
@@ -595,10 +595,6 @@ interface MapServiceConfig {
|
|||||||
zoom: number;
|
zoom: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HistoryState {
|
|
||||||
state: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type FeatureType = "station" | "route" | "sight";
|
type FeatureType = "station" | "route" | "sight";
|
||||||
|
|
||||||
class MapService {
|
class MapService {
|
||||||
@@ -620,9 +616,6 @@ class MapService {
|
|||||||
private modifyInteraction: Modify;
|
private modifyInteraction: Modify;
|
||||||
private selectInteraction: Select;
|
private selectInteraction: Select;
|
||||||
private hoveredFeatureId: string | number | null;
|
private hoveredFeatureId: string | number | null;
|
||||||
private history: HistoryState[];
|
|
||||||
private historyIndex: number;
|
|
||||||
private beforeActionState: string | null = null;
|
|
||||||
private boundHandlePointerMove: (
|
private boundHandlePointerMove: (
|
||||||
event: MapBrowserEvent<PointerEvent>
|
event: MapBrowserEvent<PointerEvent>
|
||||||
) => void;
|
) => void;
|
||||||
@@ -674,8 +667,6 @@ class MapService {
|
|||||||
this.currentDrawingFeatureType = null;
|
this.currentDrawingFeatureType = null;
|
||||||
this.currentInteraction = null;
|
this.currentInteraction = null;
|
||||||
this.hoveredFeatureId = null;
|
this.hoveredFeatureId = null;
|
||||||
this.history = [];
|
|
||||||
this.historyIndex = -1;
|
|
||||||
this.clusterStyleCache = {};
|
this.clusterStyleCache = {};
|
||||||
|
|
||||||
this.setLoading = setLoading;
|
this.setLoading = setLoading;
|
||||||
@@ -1037,21 +1028,10 @@ class MapService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
this.modifyInteraction.on("modifystart", () => {
|
|
||||||
if (!this.beforeActionState) {
|
|
||||||
this.beforeActionState = this.getCurrentStateAsGeoJSON();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.modifyInteraction.on("modifyend", (event) => {
|
this.modifyInteraction.on("modifyend", (event) => {
|
||||||
if (this.beforeActionState) {
|
|
||||||
this.addStateToHistory(this.beforeActionState);
|
|
||||||
}
|
|
||||||
event.features.getArray().forEach((feature) => {
|
event.features.getArray().forEach((feature) => {
|
||||||
this.saveModifiedFeature(feature as Feature<Geometry>);
|
this.saveModifiedFeature(feature as Feature<Geometry>);
|
||||||
});
|
});
|
||||||
this.beforeActionState = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.map) {
|
if (this.map) {
|
||||||
@@ -1100,11 +1080,6 @@ class MapService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const beforeState = this.getCurrentStateAsGeoJSON();
|
|
||||||
if (beforeState) {
|
|
||||||
this.addStateToHistory(beforeState);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newCoordinates = coordinates.filter(
|
const newCoordinates = coordinates.filter(
|
||||||
(_, index) => index !== closestIndex
|
(_, index) => index !== closestIndex
|
||||||
);
|
);
|
||||||
@@ -1330,197 +1305,6 @@ class MapService {
|
|||||||
this.lineSource.addFeatures(lineFeatures);
|
this.lineSource.addFeatures(lineFeatures);
|
||||||
|
|
||||||
this.updateFeaturesInReact();
|
this.updateFeaturesInReact();
|
||||||
const initialState = this.getCurrentStateAsGeoJSON();
|
|
||||||
if (initialState) {
|
|
||||||
this.addStateToHistory(initialState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private addStateToHistory(stateToSave: string): void {
|
|
||||||
this.history = this.history.slice(0, this.historyIndex + 1);
|
|
||||||
this.history.push({ state: stateToSave });
|
|
||||||
this.historyIndex = this.history.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getCurrentStateAsGeoJSON(): string | null {
|
|
||||||
if (!this.map) return null;
|
|
||||||
const geoJSONFormat = new GeoJSON();
|
|
||||||
const allFeatures = [
|
|
||||||
...this.pointSource.getFeatures(),
|
|
||||||
...this.lineSource.getFeatures(),
|
|
||||||
];
|
|
||||||
return geoJSONFormat.writeFeatures(allFeatures, {
|
|
||||||
dataProjection: "EPSG:4326",
|
|
||||||
featureProjection: this.map.getView().getProjection().getCode(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private applyHistoryState(geoJSONState: string) {
|
|
||||||
if (!this.map) return;
|
|
||||||
const projection = this.map.getView().getProjection();
|
|
||||||
const geoJSONFormat = new GeoJSON({
|
|
||||||
dataProjection: "EPSG:4326",
|
|
||||||
featureProjection: projection.getCode(),
|
|
||||||
});
|
|
||||||
const features = geoJSONFormat.readFeatures(
|
|
||||||
geoJSONState
|
|
||||||
) as Feature<Geometry>[];
|
|
||||||
|
|
||||||
this.unselect();
|
|
||||||
this.pointSource.clear();
|
|
||||||
this.lineSource.clear();
|
|
||||||
|
|
||||||
const pointFeatures: Feature<Point>[] = [];
|
|
||||||
const lineFeatures: Feature<LineString>[] = [];
|
|
||||||
|
|
||||||
features.forEach((feature) => {
|
|
||||||
const featureType = feature.get("featureType");
|
|
||||||
const isProxy = feature.get("isProxy");
|
|
||||||
if (featureType === "route" && !isProxy) {
|
|
||||||
lineFeatures.push(feature as Feature<LineString>);
|
|
||||||
} else {
|
|
||||||
pointFeatures.push(feature as Feature<Point>);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.pointSource.addFeatures(pointFeatures);
|
|
||||||
this.lineSource.addFeatures(lineFeatures);
|
|
||||||
|
|
||||||
this.updateFeaturesInReact();
|
|
||||||
|
|
||||||
const newStations: ApiStation[] = [];
|
|
||||||
const newRoutes: ApiRoute[] = [];
|
|
||||||
const newSights: ApiSight[] = [];
|
|
||||||
|
|
||||||
features.forEach((feature) => {
|
|
||||||
const id = feature.getId();
|
|
||||||
if (!id || feature.get("isProxy")) return;
|
|
||||||
|
|
||||||
const [featureType, numericIdStr] = String(id).split("-");
|
|
||||||
const numericId = parseInt(numericIdStr, 10);
|
|
||||||
if (isNaN(numericId)) return;
|
|
||||||
const geometry = feature.getGeometry();
|
|
||||||
if (!geometry) return;
|
|
||||||
const properties = feature.getProperties();
|
|
||||||
|
|
||||||
if (featureType === "station") {
|
|
||||||
const coords = (geometry as Point).getCoordinates();
|
|
||||||
const [lon, lat] = toLonLat(coords, projection);
|
|
||||||
newStations.push({
|
|
||||||
id: numericId,
|
|
||||||
name: properties.name,
|
|
||||||
latitude: lat,
|
|
||||||
longitude: lon,
|
|
||||||
city_id: properties.city_id || 1, // Default city_id if not available
|
|
||||||
});
|
|
||||||
} else if (featureType === "sight") {
|
|
||||||
const coords = (geometry as Point).getCoordinates();
|
|
||||||
const [lon, lat] = toLonLat(coords, projection);
|
|
||||||
newSights.push({
|
|
||||||
id: numericId,
|
|
||||||
name: properties.name,
|
|
||||||
description: properties.description,
|
|
||||||
latitude: lat,
|
|
||||||
longitude: lon,
|
|
||||||
city_id: properties.city_id || 1, // Default city_id if not available
|
|
||||||
});
|
|
||||||
} else if (featureType === "route") {
|
|
||||||
const coords = (geometry as LineString).getCoordinates();
|
|
||||||
const path = coords.map((c) => {
|
|
||||||
const [lon, lat] = toLonLat(c, projection);
|
|
||||||
return [lat, lon] as [number, number];
|
|
||||||
});
|
|
||||||
|
|
||||||
const centerCoords = getCenter(geometry.getExtent());
|
|
||||||
const [center_longitude, center_latitude] = toLonLat(
|
|
||||||
centerCoords,
|
|
||||||
projection
|
|
||||||
);
|
|
||||||
|
|
||||||
newRoutes.push({
|
|
||||||
id: numericId,
|
|
||||||
route_number: properties.name,
|
|
||||||
path: path,
|
|
||||||
center_latitude,
|
|
||||||
center_longitude,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mapStore.stations = newStations;
|
|
||||||
mapStore.routes = newRoutes.sort((a, b) =>
|
|
||||||
a.route_number.localeCompare(b.route_number)
|
|
||||||
);
|
|
||||||
mapStore.sights = newSights;
|
|
||||||
}
|
|
||||||
|
|
||||||
public undo(): void {
|
|
||||||
if (this.historyIndex > 0) {
|
|
||||||
this.historyIndex--;
|
|
||||||
const stateToRestore = this.history[this.historyIndex].state;
|
|
||||||
this.applyHistoryState(stateToRestore);
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
...this.pointSource.getFeatures().filter((f) => !f.get("isProxy")),
|
|
||||||
...this.lineSource.getFeatures(),
|
|
||||||
];
|
|
||||||
const updatePromises = features.map((feature) => {
|
|
||||||
const featureType = feature.get("featureType");
|
|
||||||
const geoJSONFormat = new GeoJSON({
|
|
||||||
dataProjection: "EPSG:4326",
|
|
||||||
featureProjection: this.map?.getView().getProjection().getCode(),
|
|
||||||
});
|
|
||||||
const featureGeoJSON = geoJSONFormat.writeFeatureObject(feature);
|
|
||||||
return mapStore.updateFeature(featureType, featureGeoJSON);
|
|
||||||
});
|
|
||||||
|
|
||||||
Promise.all(updatePromises)
|
|
||||||
.then(() => {})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Failed to update backend after undo:", error);
|
|
||||||
this.historyIndex++;
|
|
||||||
const previousState = this.history[this.historyIndex].state;
|
|
||||||
this.applyHistoryState(previousState);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast.info("Больше отменять нечего");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public redo(): void {
|
|
||||||
if (this.historyIndex < this.history.length - 1) {
|
|
||||||
this.historyIndex++;
|
|
||||||
const stateToRestore = this.history[this.historyIndex].state;
|
|
||||||
this.applyHistoryState(stateToRestore);
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
...this.pointSource.getFeatures().filter((f) => !f.get("isProxy")),
|
|
||||||
...this.lineSource.getFeatures(),
|
|
||||||
];
|
|
||||||
const updatePromises = features.map((feature) => {
|
|
||||||
const featureType = feature.get("featureType");
|
|
||||||
const geoJSONFormat = new GeoJSON({
|
|
||||||
dataProjection: "EPSG:4326",
|
|
||||||
featureProjection: this.map?.getView().getProjection().getCode(),
|
|
||||||
});
|
|
||||||
const featureGeoJSON = geoJSONFormat.writeFeatureObject(feature);
|
|
||||||
return mapStore.updateFeature(featureType, featureGeoJSON);
|
|
||||||
});
|
|
||||||
|
|
||||||
Promise.all(updatePromises)
|
|
||||||
.then(() => {
|
|
||||||
toast.info("Действие повторено");
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Failed to update backend after redo:", error);
|
|
||||||
toast.error("Не удалось обновить данные на сервере");
|
|
||||||
this.historyIndex--;
|
|
||||||
const previousState = this.history[this.historyIndex].state;
|
|
||||||
this.applyHistoryState(previousState);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast.info("Больше повторять нечего");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateFeaturesInReact(): void {
|
private updateFeaturesInReact(): void {
|
||||||
@@ -1543,16 +1327,6 @@ class MapService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleKeyDown(event: KeyboardEvent): void {
|
private handleKeyDown(event: KeyboardEvent): void {
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === "z") {
|
|
||||||
event.preventDefault();
|
|
||||||
this.undo();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === "y") {
|
|
||||||
event.preventDefault();
|
|
||||||
this.redo();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (event.key === "Escape") {
|
if (event.key === "Escape") {
|
||||||
this.unselect();
|
this.unselect();
|
||||||
}
|
}
|
||||||
@@ -1619,36 +1393,20 @@ class MapService {
|
|||||||
style: styleForDrawing,
|
style: styleForDrawing,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.currentInteraction.on("drawstart", () => {
|
|
||||||
this.beforeActionState = this.getCurrentStateAsGeoJSON();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentInteraction.on("drawend", async (event: DrawEvent) => {
|
this.currentInteraction.on("drawend", async (event: DrawEvent) => {
|
||||||
if (this.beforeActionState) {
|
|
||||||
this.addStateToHistory(this.beforeActionState);
|
|
||||||
}
|
|
||||||
this.beforeActionState = null;
|
|
||||||
|
|
||||||
const feature = event.feature as Feature<Geometry>;
|
const feature = event.feature as Feature<Geometry>;
|
||||||
const fType = this.currentDrawingFeatureType;
|
const fType = this.currentDrawingFeatureType;
|
||||||
if (!fType) return;
|
if (!fType) return;
|
||||||
feature.set("featureType", fType);
|
feature.set("featureType", fType);
|
||||||
|
|
||||||
let resourceName: string;
|
let resourceName: string;
|
||||||
const allFeatures = [
|
|
||||||
...this.pointSource.getFeatures(),
|
|
||||||
...this.lineSource.getFeatures(),
|
|
||||||
];
|
|
||||||
|
|
||||||
switch (fType) {
|
switch (fType) {
|
||||||
case "station":
|
case "station":
|
||||||
const existingStations = allFeatures.filter(
|
// Используем полный список из mapStore, а не отфильтрованный
|
||||||
(f) => f.get("featureType") === "station"
|
const stationNumbers = mapStore.stations
|
||||||
);
|
.map((station) => {
|
||||||
const stationNumbers = existingStations
|
const match = station.name?.match(/^Остановка (\d+)$/);
|
||||||
.map((f) => {
|
|
||||||
const name = f.get("name") as string;
|
|
||||||
const match = name?.match(/^Остановка (\d+)$/);
|
|
||||||
return match ? parseInt(match[1], 10) : 0;
|
return match ? parseInt(match[1], 10) : 0;
|
||||||
})
|
})
|
||||||
.filter((num) => num > 0);
|
.filter((num) => num > 0);
|
||||||
@@ -1657,13 +1415,10 @@ class MapService {
|
|||||||
resourceName = `Остановка ${nextStationNumber}`;
|
resourceName = `Остановка ${nextStationNumber}`;
|
||||||
break;
|
break;
|
||||||
case "sight":
|
case "sight":
|
||||||
const existingSights = allFeatures.filter(
|
// Используем полный список из mapStore, а не отфильтрованный
|
||||||
(f) => f.get("featureType") === "sight"
|
const sightNumbers = mapStore.sights
|
||||||
);
|
.map((sight) => {
|
||||||
const sightNumbers = existingSights
|
const match = sight.name?.match(/^Достопримечательность (\d+)$/);
|
||||||
.map((f) => {
|
|
||||||
const name = f.get("name") as string;
|
|
||||||
const match = name?.match(/^Достопримечательность (\d+)$/);
|
|
||||||
return match ? parseInt(match[1], 10) : 0;
|
return match ? parseInt(match[1], 10) : 0;
|
||||||
})
|
})
|
||||||
.filter((num) => num > 0);
|
.filter((num) => num > 0);
|
||||||
@@ -1672,13 +1427,10 @@ class MapService {
|
|||||||
resourceName = `Достопримечательность ${nextSightNumber}`;
|
resourceName = `Достопримечательность ${nextSightNumber}`;
|
||||||
break;
|
break;
|
||||||
case "route":
|
case "route":
|
||||||
const existingRoutes = allFeatures.filter(
|
// Используем полный список из mapStore, а не отфильтрованный
|
||||||
(f) => f.get("featureType") === "route" && !f.get("isProxy")
|
const routeNumbers = mapStore.routes
|
||||||
);
|
.map((route) => {
|
||||||
const routeNumbers = existingRoutes
|
const match = route.route_number?.match(/^Маршрут (\d+)$/);
|
||||||
.map((f) => {
|
|
||||||
const name = f.get("name") as string;
|
|
||||||
const match = name?.match(/^Маршрут (\d+)$/);
|
|
||||||
return match ? parseInt(match[1], 10) : 0;
|
return match ? parseInt(match[1], 10) : 0;
|
||||||
})
|
})
|
||||||
.filter((num) => num > 0);
|
.filter((num) => num > 0);
|
||||||
@@ -1841,18 +1593,12 @@ class MapService {
|
|||||||
): void {
|
): void {
|
||||||
if (featureId === undefined) return;
|
if (featureId === undefined) return;
|
||||||
|
|
||||||
this.beforeActionState = this.getCurrentStateAsGeoJSON();
|
|
||||||
|
|
||||||
const numericId = parseInt(String(featureId).split("-")[1], 10);
|
const numericId = parseInt(String(featureId).split("-")[1], 10);
|
||||||
if (!recourse || isNaN(numericId)) return;
|
if (!recourse || isNaN(numericId)) return;
|
||||||
|
|
||||||
mapStore
|
mapStore
|
||||||
.deleteFeature(recourse, numericId)
|
.deleteFeature(recourse, numericId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.beforeActionState)
|
|
||||||
this.addStateToHistory(this.beforeActionState);
|
|
||||||
this.beforeActionState = null;
|
|
||||||
|
|
||||||
if (recourse === "route") {
|
if (recourse === "route") {
|
||||||
const lineFeature = this.lineSource.getFeatureById(featureId);
|
const lineFeature = this.lineSource.getFeatureById(featureId);
|
||||||
if (lineFeature)
|
if (lineFeature)
|
||||||
@@ -1877,8 +1623,6 @@ class MapService {
|
|||||||
public deleteMultipleFeatures(featureIds: (string | number)[]): void {
|
public deleteMultipleFeatures(featureIds: (string | number)[]): void {
|
||||||
if (!featureIds || featureIds.length === 0) return;
|
if (!featureIds || featureIds.length === 0) return;
|
||||||
|
|
||||||
this.beforeActionState = this.getCurrentStateAsGeoJSON();
|
|
||||||
|
|
||||||
const deletePromises = Array.from(featureIds).map((id) => {
|
const deletePromises = Array.from(featureIds).map((id) => {
|
||||||
const recourse = String(id).split("-")[0];
|
const recourse = String(id).split("-")[0];
|
||||||
const numericId = parseInt(String(id).split("-")[1], 10);
|
const numericId = parseInt(String(id).split("-")[1], 10);
|
||||||
@@ -1895,10 +1639,6 @@ class MapService {
|
|||||||
| number
|
| number
|
||||||
)[];
|
)[];
|
||||||
if (successfulDeletes.length > 0) {
|
if (successfulDeletes.length > 0) {
|
||||||
if (this.beforeActionState)
|
|
||||||
this.addStateToHistory(this.beforeActionState);
|
|
||||||
this.beforeActionState = null;
|
|
||||||
|
|
||||||
successfulDeletes.forEach((id) => {
|
successfulDeletes.forEach((id) => {
|
||||||
const recourse = String(id).split("-")[0];
|
const recourse = String(id).split("-")[0];
|
||||||
if (recourse === "route") {
|
if (recourse === "route") {
|
||||||
@@ -2029,9 +1769,6 @@ class MapService {
|
|||||||
// Метод для сброса кешей карты
|
// Метод для сброса кешей карты
|
||||||
public clearCaches() {
|
public clearCaches() {
|
||||||
this.clusterStyleCache = {};
|
this.clusterStyleCache = {};
|
||||||
this.history = [];
|
|
||||||
this.historyIndex = -1;
|
|
||||||
this.beforeActionState = null;
|
|
||||||
this.hoveredFeatureId = null;
|
this.hoveredFeatureId = null;
|
||||||
this.selectedIds.clear();
|
this.selectedIds.clear();
|
||||||
|
|
||||||
@@ -2086,9 +1823,6 @@ class MapService {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to update feature:", error);
|
console.error("Failed to update feature:", error);
|
||||||
toast.error(`Не удалось обновить: ${error}`);
|
toast.error(`Не удалось обновить: ${error}`);
|
||||||
if (this.beforeActionState) {
|
|
||||||
this.applyHistoryState(this.beforeActionState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2156,10 +1890,6 @@ class MapService {
|
|||||||
if (this.pointSource.hasFeature(feature as Feature<Point>))
|
if (this.pointSource.hasFeature(feature as Feature<Point>))
|
||||||
this.pointSource.removeFeature(feature as Feature<Point>);
|
this.pointSource.removeFeature(feature as Feature<Point>);
|
||||||
}
|
}
|
||||||
if (this.beforeActionState) {
|
|
||||||
this.applyHistoryState(this.beforeActionState);
|
|
||||||
}
|
|
||||||
this.beforeActionState = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2994,18 +2724,6 @@ export const MapPage: React.FC = observer(() => {
|
|||||||
<span className="font-mono bg-gray-100 px-1 rounded">Esc</span>{" "}
|
<span className="font-mono bg-gray-100 px-1 rounded">Esc</span>{" "}
|
||||||
- Отменить выделение
|
- Отменить выделение
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<span className="font-mono bg-gray-100 px-1 rounded">
|
|
||||||
Ctrl+Z
|
|
||||||
</span>{" "}
|
|
||||||
- Отменить действие
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="font-mono bg-gray-100 px-1 rounded">
|
|
||||||
Ctrl+Y
|
|
||||||
</span>{" "}
|
|
||||||
- Повторить действие
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowHelp(false)}
|
onClick={() => setShowHelp(false)}
|
||||||
|
|||||||
@@ -60,7 +60,11 @@ export const MediaEditPage = observer(() => {
|
|||||||
if (extension) {
|
if (extension) {
|
||||||
if (["glb", "gltf"].includes(extension)) {
|
if (["glb", "gltf"].includes(extension)) {
|
||||||
setAvailableMediaTypes([6]); // 3D model
|
setAvailableMediaTypes([6]); // 3D model
|
||||||
} else if (["jpg", "jpeg", "png", "gif"].includes(extension)) {
|
} else if (
|
||||||
|
["jpg", "jpeg", "png", "gif", "svg", "webp", "bmp"].includes(
|
||||||
|
extension
|
||||||
|
)
|
||||||
|
) {
|
||||||
setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama
|
setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama
|
||||||
} else if (["mp4", "webm", "mov"].includes(extension)) {
|
} else if (["mp4", "webm", "mov"].includes(extension)) {
|
||||||
setAvailableMediaTypes([2]); // Video
|
setAvailableMediaTypes([2]); // Video
|
||||||
@@ -109,7 +113,11 @@ export const MediaEditPage = observer(() => {
|
|||||||
if (["glb", "gltf"].includes(extension)) {
|
if (["glb", "gltf"].includes(extension)) {
|
||||||
setAvailableMediaTypes([6]); // 3D model
|
setAvailableMediaTypes([6]); // 3D model
|
||||||
setMediaType(6);
|
setMediaType(6);
|
||||||
} else if (["jpg", "jpeg", "png", "gif"].includes(extension)) {
|
} else if (
|
||||||
|
["jpg", "jpeg", "png", "gif", "svg", "webp", "bmp"].includes(
|
||||||
|
extension
|
||||||
|
)
|
||||||
|
) {
|
||||||
setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama
|
setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama
|
||||||
setMediaType(1); // Default to Photo
|
setMediaType(1); // Default to Photo
|
||||||
} else if (["mp4", "webm", "mov"].includes(extension)) {
|
} else if (["mp4", "webm", "mov"].includes(extension)) {
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
||||||
import { ruRU } from "@mui/x-data-grid/locales";
|
import { ruRU } from "@mui/x-data-grid/locales";
|
||||||
import { cityStore, languageStore, sightsStore } from "@shared";
|
import {
|
||||||
import { useEffect, useState } from "react";
|
cityStore,
|
||||||
|
languageStore,
|
||||||
|
sightsStore,
|
||||||
|
selectedCityStore,
|
||||||
|
} from "@shared";
|
||||||
|
import { useEffect, useState, useMemo } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Pencil, Trash2, Minus } from "lucide-react";
|
import { Pencil, Trash2, Minus } from "lucide-react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@@ -92,7 +97,16 @@ export const SightListPage = observer(() => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const rows = sights.map((sight) => ({
|
// Фильтрация достопримечательностей по выбранному городу
|
||||||
|
const filteredSights = useMemo(() => {
|
||||||
|
const { selectedCityId } = selectedCityStore;
|
||||||
|
if (!selectedCityId) {
|
||||||
|
return sights;
|
||||||
|
}
|
||||||
|
return sights.filter((sight: any) => sight.city_id === selectedCityId);
|
||||||
|
}, [sights, selectedCityStore.selectedCityId]);
|
||||||
|
|
||||||
|
const rows = filteredSights.map((sight) => ({
|
||||||
id: sight.id,
|
id: sight.id,
|
||||||
name: sight.name,
|
name: sight.name,
|
||||||
city_id: sight.city_id,
|
city_id: sight.city_id,
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
||||||
import { ruRU } from "@mui/x-data-grid/locales";
|
import { ruRU } from "@mui/x-data-grid/locales";
|
||||||
import { languageStore, stationsStore } from "@shared";
|
import {
|
||||||
import { useEffect, useState } from "react";
|
languageStore,
|
||||||
|
stationsStore,
|
||||||
|
selectedCityStore,
|
||||||
|
cityStore,
|
||||||
|
} from "@shared";
|
||||||
|
import { useEffect, useState, useMemo } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Eye, Pencil, Trash2, Minus } from "lucide-react";
|
import { Eye, Pencil, Trash2, Minus } from "lucide-react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@@ -21,6 +26,7 @@ export const StationListPage = observer(() => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchStations = async () => {
|
const fetchStations = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
await cityStore.getCities(language);
|
||||||
await getStationList();
|
await getStationList();
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
@@ -109,7 +115,18 @@ export const StationListPage = observer(() => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const rows = stationLists[language].data.map((station: any) => ({
|
// Фильтрация станций по выбранному городу
|
||||||
|
const filteredStations = useMemo(() => {
|
||||||
|
const { selectedCityId } = selectedCityStore;
|
||||||
|
if (!selectedCityId) {
|
||||||
|
return stationLists[language].data;
|
||||||
|
}
|
||||||
|
return stationLists[language].data.filter(
|
||||||
|
(station: any) => station.city_id === selectedCityId
|
||||||
|
);
|
||||||
|
}, [stationLists, language, selectedCityStore.selectedCityId]);
|
||||||
|
|
||||||
|
const rows = filteredStations.map((station: any) => ({
|
||||||
id: station.id,
|
id: station.id,
|
||||||
name: station.name,
|
name: station.name,
|
||||||
system_name: station.system_name,
|
system_name: station.system_name,
|
||||||
|
|||||||
@@ -105,7 +105,11 @@ export const UploadMediaDialog = observer(
|
|||||||
setAvailableMediaTypes([6]);
|
setAvailableMediaTypes([6]);
|
||||||
setMediaType(6);
|
setMediaType(6);
|
||||||
}
|
}
|
||||||
if (["jpg", "jpeg", "png", "gif", "svg"].includes(extension)) {
|
if (
|
||||||
|
["jpg", "jpeg", "png", "gif", "svg", "webp", "bmp"].includes(
|
||||||
|
extension
|
||||||
|
)
|
||||||
|
) {
|
||||||
// Для изображений доступны все типы кроме видео
|
// Для изображений доступны все типы кроме видео
|
||||||
setAvailableMediaTypes([1, 3, 4, 5]); // Фото, Иконка, Водяной знак, Панорама, 3Д-модель
|
setAvailableMediaTypes([1, 3, 4, 5]); // Фото, Иконка, Водяной знак, Панорама, 3Д-модель
|
||||||
setMediaType(1); // По умолчанию Фото
|
setMediaType(1); // По умолчанию Фото
|
||||||
|
|||||||
@@ -67,11 +67,6 @@ export function MediaViewer({
|
|||||||
style={{
|
style={{
|
||||||
height: fullHeight ? "100%" : height ? height : "auto",
|
height: fullHeight ? "100%" : height ? height : "auto",
|
||||||
width: fullWidth ? "100%" : width ? width : "auto",
|
width: fullWidth ? "100%" : width ? width : "auto",
|
||||||
...(media?.filename?.toLowerCase().endsWith(".webp") && {
|
|
||||||
maxWidth: "300px",
|
|
||||||
maxHeight: "300px",
|
|
||||||
objectFit: "contain",
|
|
||||||
}),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user