@geops/rvf-mobility-web-component 0.1.59 → 0.1.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +16 -123
- package/docutils.js +1 -1
- package/index.js +152 -149
- package/package.json +1 -1
- package/src/ExportMenu/ExportMenu.tsx +7 -5
- package/src/ExportMenuButton/ExportMenuButton.tsx +8 -1
- package/src/GeolocationButton/GeolocationButton.tsx +9 -3
- package/src/LayerTree/TreeItem/TreeItem.tsx +3 -1
- package/src/LayerTreeButton/LayerTreeButton.tsx +10 -4
- package/src/LayerTreeMenu/LayerTreeMenu.tsx +15 -5
- package/src/LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx +5 -2
- package/src/MapDispatchEvents/MapDispatchEvents.tsx +7 -0
- package/src/MapLayout/MapLayout.tsx +176 -0
- package/src/MapLayout/index.tsx +1 -0
- package/src/MobilityMap/MobilityMap.tsx +25 -139
- package/src/MobilityMap/MobilityMapAttributes.ts +15 -3
- package/src/NotificationDetails/NotificationDetails.tsx +23 -8
- package/src/OverlayContent/OverlayContent.tsx +5 -3
- package/src/OverlayDetails/OverlayDetails.tsx +29 -11
- package/src/OverlayDetailsHeader/OverlayDetailsHeader.tsx +11 -14
- package/src/Permalink/Permalink.tsx +5 -5
- package/src/PermalinkInput/PermalinkInput.tsx +6 -4
- package/src/RealtimeLayer/RealtimeLayer.tsx +10 -9
- package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +1 -1
- package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +23 -8
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +45 -41
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +6 -6
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +76 -58
- package/src/Search/Search.tsx +1 -1
- package/src/SearchButton/SearchButton.tsx +10 -4
- package/src/ShareMenu/ShareMenu.tsx +4 -2
- package/src/ShareMenuButton/ShareMenuButton.tsx +10 -3
- package/src/StationsLayer/StationsLayer.tsx +4 -1
- package/src/ZoomButtons/ZoomButtons.tsx +12 -2
- package/src/index.tsx +13 -5
- package/src/utils/constants.ts +20 -40
- package/src/utils/getPermalinkParameters.ts +12 -4
- package/src/utils/hooks/useInitialPermalink.tsx +76 -0
- package/src/utils/hooks/useLayerConfig.tsx +1 -3
- package/src/utils/hooks/useLayersConfig.tsx +2 -2
- package/src/utils/i18n.ts +0 -10
- package/src/utils/translations.ts +165 -0
- package/src/RvfFeatureDetailsFooter/RvfFeatureDetailsFooter.tsx +0 -43
- package/src/RvfFeatureDetailsFooter/index.tsx +0 -1
- package/src/RvfFeatureDetailsTitle/RvfFeatureDetailsTitle.tsx +0 -81
- package/src/RvfFeatureDetailsTitle/index.tsx +0 -1
- package/src/RvfLayerTree/RvfLayerTree.tsx +0 -40
- package/src/RvfLayerTree/TreeItem/TreeItem.tsx +0 -145
- package/src/RvfLayerTree/TreeItem/index.tsx +0 -1
- package/src/RvfLayerTree/index.tsx +0 -1
- package/src/RvfLayerTree/layersTreeContext.ts +0 -4
- package/src/RvfLayerTree/layersTreeReducer.ts +0 -158
- package/src/RvfOverlayContent/RvfOverlayContent.tsx +0 -128
- package/src/RvfOverlayContent/index.ts +0 -0
- package/src/utils/hooks/useUpdatePermalink.tsx +0 -76
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { memo } from "preact/compat";
|
|
2
|
-
import { useEffect, useReducer } from "preact/hooks";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
LayersTreeContext,
|
|
6
|
-
LayersTreeDispatchContext,
|
|
7
|
-
} from "./layersTreeContext";
|
|
8
|
-
import layersTreeReducer from "./layersTreeReducer";
|
|
9
|
-
import TreeItem from "./TreeItem/TreeItem";
|
|
10
|
-
|
|
11
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
12
|
-
|
|
13
|
-
import type { TreeItemProps } from "./TreeItem/TreeItem";
|
|
14
|
-
|
|
15
|
-
export type RvfLayerTreeProps = {
|
|
16
|
-
layers: TreeItemProps[];
|
|
17
|
-
} & JSX.HTMLAttributes<HTMLDivElement> &
|
|
18
|
-
PreactDOMAttributes;
|
|
19
|
-
|
|
20
|
-
function RvfLayerTree({ layers, ...props }: RvfLayerTreeProps) {
|
|
21
|
-
const [tree, dispatch] = useReducer(layersTreeReducer, layers);
|
|
22
|
-
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
dispatch({ payload: layers, type: "INIT" });
|
|
25
|
-
}, [layers]);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<LayersTreeContext.Provider value={tree}>
|
|
29
|
-
<LayersTreeDispatchContext.Provider value={dispatch}>
|
|
30
|
-
<div {...props}>
|
|
31
|
-
{layers.map((item) => {
|
|
32
|
-
return <TreeItem className="w-full" key={item.id} {...item} />;
|
|
33
|
-
})}
|
|
34
|
-
</div>
|
|
35
|
-
</LayersTreeDispatchContext.Provider>
|
|
36
|
-
</LayersTreeContext.Provider>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export default memo(RvfLayerTree);
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { useContext, useEffect, useId, useState } from "preact/compat";
|
|
2
|
-
|
|
3
|
-
import ArrowDown from "../../icons/ArrowDown";
|
|
4
|
-
import ArrowUp from "../../icons/ArrowUp";
|
|
5
|
-
import minusGrey from "../../icons/Minus/minus-grey.svg";
|
|
6
|
-
import RvfCheckbox from "../../RvfCheckbox";
|
|
7
|
-
import RvfRadioButton from "../../RvfRadioButton";
|
|
8
|
-
import { LayersTreeDispatchContext } from "../layersTreeContext";
|
|
9
|
-
|
|
10
|
-
import type BaseLayer from "ol/layer/Base";
|
|
11
|
-
import type { JSX, PreactDOMAttributes } from "preact";
|
|
12
|
-
import type { SVGProps } from "preact/compat";
|
|
13
|
-
|
|
14
|
-
export enum SelectionType {
|
|
15
|
-
CHECKBOX = "checkbox",
|
|
16
|
-
RADIO = "radio",
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type TreeItemProps = {
|
|
20
|
-
childItems: TreeItemProps[];
|
|
21
|
-
Icon?: (props: SVGProps<SVGSVGElement>) => preact.JSX.Element;
|
|
22
|
-
id: string;
|
|
23
|
-
isCollapsedOnControlClick?: boolean;
|
|
24
|
-
isControlChecked?: boolean;
|
|
25
|
-
layer?: BaseLayer;
|
|
26
|
-
onIconClick?: () => void;
|
|
27
|
-
selectionType: SelectionType;
|
|
28
|
-
title: string;
|
|
29
|
-
} & JSX.HTMLAttributes<HTMLButtonElement> &
|
|
30
|
-
PreactDOMAttributes;
|
|
31
|
-
|
|
32
|
-
function TreeItem({
|
|
33
|
-
childItems,
|
|
34
|
-
isCollapsedOnControlClick,
|
|
35
|
-
isControlChecked,
|
|
36
|
-
layer,
|
|
37
|
-
selectionType,
|
|
38
|
-
title,
|
|
39
|
-
}: TreeItemProps) {
|
|
40
|
-
const [isContainerVisible, setIsContainerVisible] = useState(true);
|
|
41
|
-
const dispatch = useContext(LayersTreeDispatchContext);
|
|
42
|
-
const inputId = useId();
|
|
43
|
-
const buttonId = useId();
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
if (isCollapsedOnControlClick) {
|
|
47
|
-
setIsContainerVisible(isControlChecked);
|
|
48
|
-
}
|
|
49
|
-
}, [isControlChecked, isCollapsedOnControlClick, layer]);
|
|
50
|
-
|
|
51
|
-
const handleItemClick = () => {
|
|
52
|
-
setIsContainerVisible(!isContainerVisible);
|
|
53
|
-
|
|
54
|
-
if (isCollapsedOnControlClick && !isContainerVisible) {
|
|
55
|
-
dispatch({
|
|
56
|
-
payload: {
|
|
57
|
-
...this.props,
|
|
58
|
-
isControlChecked: true,
|
|
59
|
-
},
|
|
60
|
-
type: "SELECT_ITEM",
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const handleSelectionChange = (event) => {
|
|
66
|
-
dispatch({
|
|
67
|
-
payload: {
|
|
68
|
-
...this.props,
|
|
69
|
-
isControlChecked: event.target.checked,
|
|
70
|
-
},
|
|
71
|
-
type: "SELECT_ITEM",
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const renderedLayers = childItems
|
|
76
|
-
.filter(({ title: titlee }) => {
|
|
77
|
-
return !!titlee;
|
|
78
|
-
})
|
|
79
|
-
.map((item, idx) => {
|
|
80
|
-
return <TreeItem key={idx} {...item} />;
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
if (!title) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const isMiddleState = () => {
|
|
88
|
-
if (childItems.length > 0) {
|
|
89
|
-
const checkedItems = childItems.filter((item) => {
|
|
90
|
-
return item.isControlChecked;
|
|
91
|
-
});
|
|
92
|
-
if (checkedItems.length === childItems.length) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return childItems.some((item) => {
|
|
97
|
-
return item.isControlChecked;
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return false;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div>
|
|
106
|
-
<div className="flex items-center gap-2 border-b py-2 pr-1">
|
|
107
|
-
{selectionType === SelectionType.RADIO ? (
|
|
108
|
-
<RvfRadioButton
|
|
109
|
-
checked={isControlChecked}
|
|
110
|
-
id={inputId}
|
|
111
|
-
onChange={handleSelectionChange}
|
|
112
|
-
/>
|
|
113
|
-
) : (
|
|
114
|
-
<RvfCheckbox
|
|
115
|
-
checked={isControlChecked}
|
|
116
|
-
checkedIconUrl={isMiddleState() ? minusGrey : null}
|
|
117
|
-
className={isMiddleState() ? "bg-[length:18px]" : ""}
|
|
118
|
-
id={inputId}
|
|
119
|
-
onChange={handleSelectionChange}
|
|
120
|
-
/>
|
|
121
|
-
)}
|
|
122
|
-
<label
|
|
123
|
-
className={`flex-1 cursor-pointer`}
|
|
124
|
-
htmlFor={renderedLayers.length > 0 ? buttonId : inputId}
|
|
125
|
-
>
|
|
126
|
-
{title}
|
|
127
|
-
</label>
|
|
128
|
-
{renderedLayers.length > 0 && (
|
|
129
|
-
<button
|
|
130
|
-
className={`flex cursor-pointer items-center gap-2`}
|
|
131
|
-
id={buttonId}
|
|
132
|
-
onClick={handleItemClick}
|
|
133
|
-
>
|
|
134
|
-
{isContainerVisible ? <ArrowUp /> : <ArrowDown />}
|
|
135
|
-
</button>
|
|
136
|
-
)}
|
|
137
|
-
</div>
|
|
138
|
-
{isContainerVisible && renderedLayers.length > 0 && (
|
|
139
|
-
<div className="pl-6">{renderedLayers}</div>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export default TreeItem;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./TreeItem";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./RvfLayerTree";
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { SelectionType } from "./TreeItem/TreeItem";
|
|
2
|
-
|
|
3
|
-
const ROOT = {
|
|
4
|
-
childItems: [],
|
|
5
|
-
parent: null,
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
const mapNode = (childItems, parent) => {
|
|
9
|
-
for (const child of childItems) {
|
|
10
|
-
child.parent = parent;
|
|
11
|
-
|
|
12
|
-
if (child.childItems.length) {
|
|
13
|
-
mapNode(child.childItems, child);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const initTree = (tree) => {
|
|
19
|
-
const initializedTree = { ...ROOT };
|
|
20
|
-
initializedTree.childItems = tree;
|
|
21
|
-
mapNode(initializedTree.childItems, initializedTree);
|
|
22
|
-
|
|
23
|
-
return initializedTree;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const findNodeInTree = (node, nodeToFind) => {
|
|
27
|
-
if (node.id === nodeToFind.id) {
|
|
28
|
-
return node;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (node.childItems.length) {
|
|
32
|
-
for (const child of node.childItems) {
|
|
33
|
-
const res = findNodeInTree(child, nodeToFind);
|
|
34
|
-
if (res) {
|
|
35
|
-
return res;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const updateCheckedControlStatus = (currentItem, newItem, isParentUpdate) => {
|
|
42
|
-
if (newItem.isControlChecked) {
|
|
43
|
-
if (newItem.selectionType === SelectionType.CHECKBOX) {
|
|
44
|
-
currentItem.isControlChecked = newItem.isControlChecked;
|
|
45
|
-
currentItem.layer.setVisible(currentItem.isControlChecked);
|
|
46
|
-
} else {
|
|
47
|
-
for (const child of currentItem.parent.childItems) {
|
|
48
|
-
child.isControlChecked = child.id === currentItem.id;
|
|
49
|
-
|
|
50
|
-
if (!child.isControlChecked) {
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
52
|
-
updateRadioChildNodes(child);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
if (newItem.selectionType === SelectionType.CHECKBOX) {
|
|
58
|
-
currentItem.isControlChecked = newItem.isControlChecked;
|
|
59
|
-
currentItem.layer.setVisible(currentItem.isControlChecked);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// check all children
|
|
64
|
-
if (currentItem.childItems.length && !isParentUpdate) {
|
|
65
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
66
|
-
updateChildNodes(currentItem);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// check all parents
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
71
|
-
updateParentNodes(currentItem);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const setNewControlCheckedStatus = (tree, newItem) => {
|
|
75
|
-
const currentItem = findNodeInTree(tree, newItem);
|
|
76
|
-
|
|
77
|
-
if (currentItem) {
|
|
78
|
-
updateCheckedControlStatus(currentItem, newItem, false);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return { ...tree };
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const updateChildNodes = (node) => {
|
|
85
|
-
if (node.childItems[0].selectionType === SelectionType.RADIO) {
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
87
|
-
updateRadioChildNodes(node);
|
|
88
|
-
} else {
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
90
|
-
updateCheckboxChildNodes(node);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const updateRadioChildNodes = (parent) => {
|
|
95
|
-
if (parent.isControlChecked) {
|
|
96
|
-
for (let i = 0; i < parent.childItems.length; i++) {
|
|
97
|
-
parent.childItems[i].isControlChecked = i === 0;
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
for (const child of parent.childItems) {
|
|
101
|
-
child.isControlChecked = false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (parent.childItems.length) {
|
|
106
|
-
if (parent.childItems[0].childItems.length) {
|
|
107
|
-
updateChildNodes(parent.childItems[0]);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const updateCheckboxChildNodes = (parent) => {
|
|
113
|
-
for (const child of parent.childItems) {
|
|
114
|
-
child.isControlChecked = parent.isControlChecked;
|
|
115
|
-
child.layer.setVisible(child.isControlChecked);
|
|
116
|
-
|
|
117
|
-
if (child.childItems.length) {
|
|
118
|
-
updateChildNodes(child);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const updateParentNodes = (node) => {
|
|
124
|
-
if (node.parent) {
|
|
125
|
-
if (node.parent.selectionType === SelectionType.CHECKBOX) {
|
|
126
|
-
const newItem = {
|
|
127
|
-
...node.parent,
|
|
128
|
-
isControlChecked: node.parent.childItems.some((child) => {
|
|
129
|
-
return child.isControlChecked;
|
|
130
|
-
}),
|
|
131
|
-
};
|
|
132
|
-
updateCheckedControlStatus(node.parent, newItem, true);
|
|
133
|
-
} else {
|
|
134
|
-
if (node?.parent?.parent) {
|
|
135
|
-
const newItem = {
|
|
136
|
-
...node.parent,
|
|
137
|
-
isControlChecked: node.parent.childItems.some((child) => {
|
|
138
|
-
return child.isControlChecked;
|
|
139
|
-
}),
|
|
140
|
-
};
|
|
141
|
-
updateCheckedControlStatus(node.parent, newItem, true);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
function layersTreeReducer(state = ROOT, action) {
|
|
148
|
-
switch (action.type) {
|
|
149
|
-
case "INIT":
|
|
150
|
-
return initTree(action.payload);
|
|
151
|
-
case "SELECT_ITEM":
|
|
152
|
-
return setNewControlCheckedStatus(state, action.payload);
|
|
153
|
-
default:
|
|
154
|
-
return state;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export default layersTreeReducer;
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { twMerge } from "tailwind-merge";
|
|
2
|
-
|
|
3
|
-
import RouteSchedule from "../RouteSchedule";
|
|
4
|
-
import RvfExportMenu from "../RvfExportMenu";
|
|
5
|
-
import RvfFeatureDetails from "../RvfFeatureDetails";
|
|
6
|
-
import RvfFeatureDetailsFooter from "../RvfFeatureDetailsFooter";
|
|
7
|
-
import RvfFeatureDetailsTitle from "../RvfFeatureDetailsTitle/RvfFeatureDetailsTitle";
|
|
8
|
-
import RvfOverlayHeader from "../RvfOverlayHeader";
|
|
9
|
-
import RvfShare from "../RvfShare";
|
|
10
|
-
import RvfTopics from "../RvfTopics";
|
|
11
|
-
import Search from "../Search";
|
|
12
|
-
import Station from "../Station";
|
|
13
|
-
import { LAYERS_TITLES } from "../utils/constants";
|
|
14
|
-
import useMapContext from "../utils/hooks/useMapContext";
|
|
15
|
-
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
16
|
-
|
|
17
|
-
const contentClassName = `relative h-full overflow-x-hidden overflow-y-auto text-base`;
|
|
18
|
-
|
|
19
|
-
function RvfOverlayContent({
|
|
20
|
-
hasDetails,
|
|
21
|
-
hasLayerTree,
|
|
22
|
-
hasPrint,
|
|
23
|
-
hasRealtime,
|
|
24
|
-
hasSearch,
|
|
25
|
-
hasShare,
|
|
26
|
-
}: {
|
|
27
|
-
hasDetails: boolean;
|
|
28
|
-
hasLayerTree: boolean;
|
|
29
|
-
hasPrint: boolean;
|
|
30
|
-
hasRealtime: boolean;
|
|
31
|
-
hasSearch: boolean;
|
|
32
|
-
hasShare: boolean;
|
|
33
|
-
}) {
|
|
34
|
-
const {
|
|
35
|
-
isExportMenuOpen,
|
|
36
|
-
isLayerTreeOpen,
|
|
37
|
-
isSearchOpen,
|
|
38
|
-
isShareMenuOpen,
|
|
39
|
-
selectedFeature,
|
|
40
|
-
setIsExportMenuOpen,
|
|
41
|
-
setIsLayerTreeOpen,
|
|
42
|
-
setIsShareMenuOpen,
|
|
43
|
-
setSelectedFeature,
|
|
44
|
-
} = useRvfContext();
|
|
45
|
-
const { setStationId, setTrainId, stationId, tenant, trainId } =
|
|
46
|
-
useMapContext();
|
|
47
|
-
return (
|
|
48
|
-
<>
|
|
49
|
-
{hasRealtime && trainId && (
|
|
50
|
-
<>
|
|
51
|
-
<RvfOverlayHeader
|
|
52
|
-
onClose={() => {
|
|
53
|
-
setTrainId(null);
|
|
54
|
-
}}
|
|
55
|
-
title={LAYERS_TITLES.echtzeit}
|
|
56
|
-
></RvfOverlayHeader>
|
|
57
|
-
<RouteSchedule className={contentClassName} />
|
|
58
|
-
</>
|
|
59
|
-
)}
|
|
60
|
-
{tenant && stationId && (
|
|
61
|
-
<>
|
|
62
|
-
<RvfOverlayHeader
|
|
63
|
-
onClose={() => {
|
|
64
|
-
setStationId(null);
|
|
65
|
-
}}
|
|
66
|
-
title="Station"
|
|
67
|
-
></RvfOverlayHeader>
|
|
68
|
-
<Station className={twMerge(contentClassName, "flex flex-col p-2")} />
|
|
69
|
-
</>
|
|
70
|
-
)}
|
|
71
|
-
{hasDetails && selectedFeature && (
|
|
72
|
-
<>
|
|
73
|
-
<RvfOverlayHeader
|
|
74
|
-
onClose={() => {
|
|
75
|
-
setSelectedFeature(null);
|
|
76
|
-
}}
|
|
77
|
-
title={<RvfFeatureDetailsTitle feature={selectedFeature} />}
|
|
78
|
-
></RvfOverlayHeader>
|
|
79
|
-
<RvfFeatureDetails
|
|
80
|
-
className={twMerge(contentClassName, "relative")}
|
|
81
|
-
/>
|
|
82
|
-
<RvfFeatureDetailsFooter className={"flex flex-row p-4 pt-2"} />
|
|
83
|
-
</>
|
|
84
|
-
)}
|
|
85
|
-
{hasPrint && isExportMenuOpen && (
|
|
86
|
-
<>
|
|
87
|
-
<RvfOverlayHeader
|
|
88
|
-
onClose={() => {
|
|
89
|
-
setIsExportMenuOpen(false);
|
|
90
|
-
}}
|
|
91
|
-
title="Drucken"
|
|
92
|
-
></RvfOverlayHeader>
|
|
93
|
-
<RvfExportMenu
|
|
94
|
-
className={twMerge(contentClassName, "flex flex-col gap-4 p-4")}
|
|
95
|
-
/>
|
|
96
|
-
</>
|
|
97
|
-
)}
|
|
98
|
-
{hasLayerTree && isLayerTreeOpen && (
|
|
99
|
-
<>
|
|
100
|
-
<RvfOverlayHeader
|
|
101
|
-
onClose={() => {
|
|
102
|
-
setIsLayerTreeOpen(false);
|
|
103
|
-
}}
|
|
104
|
-
title="Layers"
|
|
105
|
-
></RvfOverlayHeader>
|
|
106
|
-
<RvfTopics className="relative flex h-full flex-col overflow-x-hidden overflow-y-auto p-2 text-base" />
|
|
107
|
-
</>
|
|
108
|
-
)}
|
|
109
|
-
{hasShare && isShareMenuOpen && (
|
|
110
|
-
<>
|
|
111
|
-
<RvfOverlayHeader
|
|
112
|
-
onClose={() => {
|
|
113
|
-
setIsShareMenuOpen(false);
|
|
114
|
-
}}
|
|
115
|
-
title="Share"
|
|
116
|
-
></RvfOverlayHeader>
|
|
117
|
-
<RvfShare className="relative flex h-full flex-col overflow-x-hidden overflow-y-auto p-4 text-base" />
|
|
118
|
-
</>
|
|
119
|
-
)}
|
|
120
|
-
{hasSearch && isSearchOpen && (
|
|
121
|
-
<>
|
|
122
|
-
<Search className="relative flex h-full flex-col overflow-x-hidden overflow-y-auto p-2 text-base" />
|
|
123
|
-
</>
|
|
124
|
-
)}
|
|
125
|
-
</>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
export default RvfOverlayContent;
|
|
File without changes
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import debounce from "lodash.debounce";
|
|
2
|
-
import { getLayersAsFlatArray } from "mobility-toolbox-js/ol";
|
|
3
|
-
import { unByKey } from "ol/Observable";
|
|
4
|
-
import { useEffect } from "preact/hooks";
|
|
5
|
-
|
|
6
|
-
import { LAYER_PROP_IS_EXPORTING } from "../constants";
|
|
7
|
-
import getPermalinkParameters from "../getPermalinkParameters";
|
|
8
|
-
import MobilityEvent from "../MobilityEvent";
|
|
9
|
-
|
|
10
|
-
import type { Map } from "ol";
|
|
11
|
-
import type { EventsKey } from "ol/events";
|
|
12
|
-
import type { MutableRef } from "preact/hooks";
|
|
13
|
-
|
|
14
|
-
const updatePermalink = (
|
|
15
|
-
map: Map,
|
|
16
|
-
eventNodeRef: MutableRef<HTMLDivElement>,
|
|
17
|
-
) => {
|
|
18
|
-
// No update when exporting
|
|
19
|
-
if (map.get(LAYER_PROP_IS_EXPORTING)) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const currentUrlParams = new URLSearchParams(window.location.search);
|
|
23
|
-
const urlParams = getPermalinkParameters(map, currentUrlParams);
|
|
24
|
-
urlParams.set("permalink", "true");
|
|
25
|
-
window.history.replaceState(null, null, `?${urlParams.toString()}`);
|
|
26
|
-
eventNodeRef?.current?.dispatchEvent(
|
|
27
|
-
new MobilityEvent<string>("mwc:permalink", window.location.href),
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const updatePermalinkDebounced = debounce(updatePermalink, 1000);
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* This hook only update parameters in the url, it does not apply the url parameters.
|
|
35
|
-
*/
|
|
36
|
-
const useUpdatePermalink = (
|
|
37
|
-
map: Map,
|
|
38
|
-
permalink: boolean,
|
|
39
|
-
eventNodeRef: MutableRef<HTMLDivElement>,
|
|
40
|
-
) => {
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
let moveEndKey: EventsKey;
|
|
43
|
-
let loadEndKey: EventsKey;
|
|
44
|
-
let changeVisibleKeys: EventsKey[];
|
|
45
|
-
|
|
46
|
-
if (map && permalink) {
|
|
47
|
-
updatePermalinkDebounced(map);
|
|
48
|
-
|
|
49
|
-
// Update x,y,z in URL on moveend
|
|
50
|
-
moveEndKey = map?.on("moveend", (evt) => {
|
|
51
|
-
updatePermalinkDebounced(evt.map, eventNodeRef);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Update layers in URL on change:visible event
|
|
55
|
-
loadEndKey = map.once("loadend", (evt) => {
|
|
56
|
-
updatePermalinkDebounced(evt.map, eventNodeRef);
|
|
57
|
-
changeVisibleKeys = getLayersAsFlatArray(
|
|
58
|
-
evt.map.getLayers().getArray(),
|
|
59
|
-
).map((layer) => {
|
|
60
|
-
return layer.on("change:visible", () => {
|
|
61
|
-
updatePermalinkDebounced(evt.map, eventNodeRef);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return () => {
|
|
68
|
-
unByKey(moveEndKey);
|
|
69
|
-
unByKey(loadEndKey);
|
|
70
|
-
unByKey(changeVisibleKeys);
|
|
71
|
-
};
|
|
72
|
-
}, [map, permalink, eventNodeRef]);
|
|
73
|
-
return null;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export default useUpdatePermalink;
|