fix: Add route-station
link area
This commit is contained in:
@ -172,7 +172,7 @@ class MapStore {
|
||||
} else if (featureType === "route") {
|
||||
data = {
|
||||
route_number: properties.name,
|
||||
path: geometry.coordinates,
|
||||
path: geometry.coordinates.map((coord: any) => [coord[1], coord[0]]), // Swap coordinates
|
||||
};
|
||||
} else if (featureType === "sight") {
|
||||
data = {
|
||||
@ -210,8 +210,8 @@ class MapStore {
|
||||
{
|
||||
...oldData,
|
||||
path: data.path,
|
||||
center_latitude: data.path[0][1],
|
||||
center_longitude: data.path[0][0],
|
||||
center_latitude: data.path[0][0], // First coordinate is latitude
|
||||
center_longitude: data.path[0][1], // Second coordinate is longitude
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -485,65 +485,38 @@ class MapService {
|
||||
const isHovered = this.hoveredFeatureId === fId;
|
||||
const isLassoSelected = fId !== undefined && this.selectedIds.has(fId);
|
||||
|
||||
if (geometryType === "Point") {
|
||||
const defaultPointStyle =
|
||||
featureType === "sight" ? this.sightIconStyle : this.busIconStyle;
|
||||
const selectedPointStyle =
|
||||
featureType === "sight"
|
||||
? this.selectedSightIconStyle
|
||||
: this.selectedBusIconStyle;
|
||||
|
||||
if (isEditSelected) {
|
||||
return selectedPointStyle;
|
||||
if (isHovered) {
|
||||
if (geometryType === "Point") {
|
||||
return featureType === "sight"
|
||||
? this.hoverSightIconStyle
|
||||
: this.universalHoverStylePoint;
|
||||
}
|
||||
if (isHovered) {
|
||||
// Only apply hover styles if not in edit mode
|
||||
if (this.mode !== "edit") {
|
||||
return featureType === "sight"
|
||||
? this.hoverSightIconStyle
|
||||
: this.universalHoverStylePoint;
|
||||
}
|
||||
return defaultPointStyle;
|
||||
}
|
||||
|
||||
if (isLassoSelected) {
|
||||
let imageStyle;
|
||||
if (featureType === "sight") {
|
||||
imageStyle = new RegularShape({
|
||||
fill: new Fill({ color: "#14b8a6" }),
|
||||
stroke: new Stroke({ color: "#fff", width: 2 }),
|
||||
points: 5,
|
||||
radius: 12,
|
||||
radius2: 6,
|
||||
angle: 0,
|
||||
});
|
||||
} else {
|
||||
imageStyle = new CircleStyle({
|
||||
radius: 10,
|
||||
fill: new Fill({ color: "#14b8a6" }),
|
||||
stroke: new Stroke({ color: "#fff", width: 2 }),
|
||||
});
|
||||
}
|
||||
return new Style({ image: imageStyle, zIndex: Infinity });
|
||||
}
|
||||
|
||||
return defaultPointStyle;
|
||||
} else if (geometryType === "LineString") {
|
||||
if (isEditSelected) {
|
||||
return this.selectedStyle;
|
||||
}
|
||||
if (isHovered) {
|
||||
return this.universalHoverStyleLine;
|
||||
}
|
||||
if (isLassoSelected) {
|
||||
return new Style({
|
||||
stroke: new Stroke({ color: "#14b8a6", width: 6 }),
|
||||
zIndex: Infinity,
|
||||
});
|
||||
}
|
||||
return this.defaultStyle;
|
||||
return this.universalHoverStyleLine;
|
||||
}
|
||||
|
||||
if (isLassoSelected) {
|
||||
if (geometryType === "Point") {
|
||||
return featureType === "sight"
|
||||
? this.selectedSightIconStyle
|
||||
: this.selectedBusIconStyle;
|
||||
}
|
||||
return this.selectedStyle;
|
||||
}
|
||||
|
||||
if (isEditSelected) {
|
||||
if (geometryType === "Point") {
|
||||
return featureType === "sight"
|
||||
? this.selectedSightIconStyle
|
||||
: this.selectedBusIconStyle;
|
||||
}
|
||||
return this.selectedStyle;
|
||||
}
|
||||
|
||||
if (geometryType === "Point") {
|
||||
return featureType === "sight"
|
||||
? this.sightIconStyle
|
||||
: this.busIconStyle;
|
||||
}
|
||||
return this.defaultStyle;
|
||||
},
|
||||
});
|
||||
@ -763,7 +736,9 @@ class MapService {
|
||||
if (!route.path || route.path.length === 0) return;
|
||||
const coordinates = route.path
|
||||
.filter((c) => c[0] != null && c[1] != null)
|
||||
.map((c) => transform(c, "EPSG:4326", projection));
|
||||
.map((c: [number, number]) =>
|
||||
transform([c[1], c[0]], "EPSG:4326", projection)
|
||||
); // Swap coordinates
|
||||
if (coordinates.length === 0) return;
|
||||
const line = new LineString(coordinates);
|
||||
const feature = new Feature({ geometry: line, name: route.route_number });
|
||||
@ -866,6 +841,11 @@ class MapService {
|
||||
this.redo();
|
||||
return;
|
||||
}
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === "r") {
|
||||
event.preventDefault();
|
||||
this.unselect();
|
||||
return;
|
||||
}
|
||||
if (event.key === "Escape") {
|
||||
this.unselect();
|
||||
}
|
||||
@ -1090,29 +1070,29 @@ class MapService {
|
||||
);
|
||||
|
||||
if (!featureAtPixel) {
|
||||
if (ctrlKey) {
|
||||
// При ctrl + клик вне сущности сбрасываем выбор
|
||||
this.setSelectedIds(new Set());
|
||||
}
|
||||
if (ctrlKey) this.unselect();
|
||||
return;
|
||||
}
|
||||
|
||||
const featureId = featureAtPixel.getId();
|
||||
if (featureId === undefined) return;
|
||||
|
||||
const newSet = new Set(this.selectedIds);
|
||||
|
||||
if (ctrlKey) {
|
||||
// При ctrl + клик на сущность добавляем/удаляем её из выбора
|
||||
const newSet = new Set(this.selectedIds);
|
||||
// Toggle selection for the clicked feature
|
||||
if (newSet.has(featureId)) {
|
||||
newSet.delete(featureId);
|
||||
} else {
|
||||
newSet.add(featureId);
|
||||
}
|
||||
this.setSelectedIds(newSet);
|
||||
} else {
|
||||
// При обычном клике на сущность выбираем только её
|
||||
this.setSelectedIds(new Set([featureId]));
|
||||
// Single selection
|
||||
newSet.clear();
|
||||
newSet.add(featureId);
|
||||
}
|
||||
|
||||
this.setSelectedIds(newSet);
|
||||
}
|
||||
|
||||
public selectFeature(featureId: string | number | undefined): void {
|
||||
@ -1127,14 +1107,6 @@ class MapService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.mode === "edit") {
|
||||
this.selectInteraction.getFeatures().clear();
|
||||
this.selectInteraction.getFeatures().push(feature);
|
||||
// @ts-ignore
|
||||
const selectEvent = new SelectEvent("select", [feature], []);
|
||||
this.selectInteraction.dispatchEvent(selectEvent);
|
||||
}
|
||||
|
||||
this.setSelectedIds(new Set([featureId]));
|
||||
|
||||
const view = this.map.getView();
|
||||
@ -1286,7 +1258,30 @@ class MapService {
|
||||
public setSelectedIds(ids: Set<string | number>) {
|
||||
this.selectedIds = new Set(ids);
|
||||
if (this.onSelectionChange) this.onSelectionChange(this.selectedIds);
|
||||
this.vectorLayer.changed();
|
||||
|
||||
// Update selectInteraction to match selectedIds
|
||||
if (this.selectInteraction) {
|
||||
this.selectInteraction.getFeatures().clear();
|
||||
ids.forEach((id) => {
|
||||
const feature = this.vectorSource.getFeatureById(id);
|
||||
if (feature) {
|
||||
this.selectInteraction.getFeatures().push(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update modifyInteraction
|
||||
this.modifyInteraction.setActive(ids.size > 0);
|
||||
|
||||
// Update feature selection in sidebar
|
||||
if (ids.size === 1) {
|
||||
const feature = this.vectorSource.getFeatureById(Array.from(ids)[0]);
|
||||
if (feature) {
|
||||
this.onFeatureSelect(feature);
|
||||
}
|
||||
} else {
|
||||
this.onFeatureSelect(null);
|
||||
}
|
||||
}
|
||||
|
||||
public getSelectedIds() {
|
||||
@ -1501,8 +1496,10 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
}, [mapFeatures, searchQuery]);
|
||||
|
||||
const handleFeatureClick = useCallback(
|
||||
// @ts-ignore
|
||||
(id) => mapService?.selectFeature(id),
|
||||
(id: string | number | undefined) => {
|
||||
if (!id || !mapService) return;
|
||||
mapService.selectFeature(id);
|
||||
},
|
||||
[mapService]
|
||||
);
|
||||
|
||||
@ -1521,7 +1518,7 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
|
||||
const handleCheckboxChange = useCallback(
|
||||
(id: string | number | undefined) => {
|
||||
if (id === undefined) return;
|
||||
if (!id || !mapService) return;
|
||||
const newSet = new Set(selectedIds);
|
||||
if (newSet.has(id)) {
|
||||
newSet.delete(id);
|
||||
@ -1529,11 +1526,9 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
newSet.add(id);
|
||||
}
|
||||
setSelectedIds(newSet);
|
||||
if (mapService) {
|
||||
mapService.setSelectedIds(newSet);
|
||||
}
|
||||
mapService.setSelectedIds(newSet);
|
||||
},
|
||||
[selectedIds, setSelectedIds, mapService]
|
||||
[mapService, selectedIds, setSelectedIds]
|
||||
);
|
||||
|
||||
const handleBulkDelete = useCallback(() => {
|
||||
@ -1630,7 +1625,7 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer"
|
||||
checked={!!isChecked}
|
||||
checked={isChecked}
|
||||
onChange={() => handleCheckboxChange(sId)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
aria-label={`Выбрать ${sName}`}
|
||||
@ -1719,7 +1714,7 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer"
|
||||
checked={!!isChecked}
|
||||
checked={isChecked}
|
||||
onChange={() => handleCheckboxChange(lId)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
aria-label={`Выбрать ${lName}`}
|
||||
@ -1808,7 +1803,7 @@ const MapSightbar: React.FC<MapSightbarProps> = ({
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer"
|
||||
checked={!!isChecked}
|
||||
checked={isChecked}
|
||||
onChange={() => handleCheckboxChange(sId)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
aria-label={`Выбрать ${sName}`}
|
||||
@ -2008,11 +2003,13 @@ export const MapPage: React.FC = () => {
|
||||
);
|
||||
|
||||
const handleMapClick = useCallback(
|
||||
(event: MapBrowserEvent<any>) => {
|
||||
if (!mapServiceInstance) return;
|
||||
mapServiceInstance.handleMapClick(event, event.originalEvent.ctrlKey);
|
||||
(event: any) => {
|
||||
if (!mapServiceInstance || isLassoActive) return;
|
||||
const ctrlKey =
|
||||
event.originalEvent.ctrlKey || event.originalEvent.metaKey;
|
||||
mapServiceInstance.handleMapClick(event, ctrlKey);
|
||||
},
|
||||
[mapServiceInstance]
|
||||
[mapServiceInstance, isLassoActive]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -2211,6 +2208,12 @@ export const MapPage: React.FC = () => {
|
||||
</span>{" "}
|
||||
- Повторить действие
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-mono bg-gray-100 px-1 rounded">
|
||||
Ctrl+R
|
||||
</span>{" "}
|
||||
- Отменить выделение
|
||||
</li>
|
||||
</ul>
|
||||
<button
|
||||
onClick={() => setShowHelp(false)}
|
||||
|
Reference in New Issue
Block a user