@geops/rvf-mobility-web-component 0.1.64 → 0.1.65
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 +25 -0
- package/docutils.js +29 -19
- package/index.html +0 -1
- package/index.js +276 -235
- package/package.json +12 -12
- package/src/BaseLayer/BaseLayer.tsx +18 -2
- package/src/Copyright/Copyright.tsx +2 -2
- package/src/Copyright/index.tsx +1 -1
- package/src/LinesNetworkPlanLayerHighlight/LinesNetworkPlanLayerHighlight.tsx +1 -0
- package/src/Map/Map.tsx +27 -1
- package/src/MapLayout/MapLayout.tsx +1 -1
- package/src/MapLayout/index.tsx +1 -1
- package/src/MobilityMap/MobilityMap.tsx +5 -11
- package/src/MobilityMap/MobilityMapAttributes.ts +8 -5
- package/src/NotificationDetails/NotificationDetails.tsx +75 -57
- package/src/Permalink/Permalink.tsx +17 -6
- package/src/PermalinkInput/PermalinkInput.tsx +4 -1
- package/src/RealtimeLayer/index.tsx +1 -1
- package/src/RvfCopyright/RvfCopyright.tsx +32 -0
- package/src/RvfCopyright/index.tsx +1 -0
- package/src/RvfInputCopy/RvfInputCopy.tsx +18 -8
- package/src/RvfMapLayout/RvfMapLayout.tsx +198 -0
- package/src/RvfMapLayout/index.tsx +1 -0
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +10 -580
- package/src/RvfRealtimeLayer/RvfRealtimeLayer.tsx +64 -0
- package/src/RvfRealtimeLayer/index.tsx +1 -0
- package/src/RvfStationsLayer/RvfStationsLayer.tsx +19 -0
- package/src/RvfStationsLayer/index.tsx +1 -0
- package/src/ShareMenu/ShareMenu.tsx +3 -1
- package/src/StationsLayer/index.tsx +1 -1
- package/src/ui/InputCopy/InputCopy.tsx +21 -10
- package/src/utils/constants.ts +1 -1
- package/src/utils/getUrlFromTemplate.test.ts +23 -0
- package/src/utils/getUrlFromTemplate.ts +47 -0
- package/src/utils/hooks/useI18n.tsx +2 -4
- package/src/utils/hooks/useInitialLayersVisiblity.tsx +27 -4
- package/src/utils/hooks/useInitialPermalink.tsx +31 -21
- package/src/utils/hooks/usePermalink.tsx +25 -0
- package/src/utils/translations.ts +4 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { memo } from "preact/compat";
|
|
2
|
+
|
|
3
|
+
import StationsLayer from "../StationsLayer/StationsLayer";
|
|
4
|
+
|
|
5
|
+
import type { MaplibreStyleLayerOptions } from "mobility-toolbox-js/ol";
|
|
6
|
+
|
|
7
|
+
const stationsLayerProps = () => {
|
|
8
|
+
return {
|
|
9
|
+
layersFilter: ({ metadata }) => {
|
|
10
|
+
return metadata?.["general.filter"] === "stations";
|
|
11
|
+
},
|
|
12
|
+
minZoom: 10,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
function RvfStationsLayer(props: Partial<MaplibreStyleLayerOptions>) {
|
|
16
|
+
return <StationsLayer {...stationsLayerProps} {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default memo(RvfStationsLayer);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./RvfStationsLayer";
|
|
@@ -7,6 +7,7 @@ import PermalinkInput from "../PermalinkInput";
|
|
|
7
7
|
import Button from "../ui/Button";
|
|
8
8
|
import useI18n from "../utils/hooks/useI18n";
|
|
9
9
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
10
|
+
import usePermalink from "../utils/hooks/usePermalink";
|
|
10
11
|
|
|
11
12
|
import type { HTMLAttributes, PreactDOMAttributes } from "preact";
|
|
12
13
|
|
|
@@ -16,13 +17,14 @@ function ShareMenu({
|
|
|
16
17
|
}: HTMLAttributes<HTMLDivElement> & PreactDOMAttributes) {
|
|
17
18
|
const { map } = useMapContext();
|
|
18
19
|
const { t } = useI18n();
|
|
20
|
+
const permalink = usePermalink();
|
|
19
21
|
|
|
20
22
|
return (
|
|
21
23
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
|
|
22
24
|
<div className={twMerge(`flex flex-col gap-4 ${className}`)} {...props}>
|
|
23
25
|
<Button
|
|
24
26
|
className="w-fit"
|
|
25
|
-
href={`mailto:?subject=Karte&body=${
|
|
27
|
+
href={`mailto:?subject=Karte&body=${permalink}`}
|
|
26
28
|
>
|
|
27
29
|
<Email />
|
|
28
30
|
<span>{t("share_email_send")}</span>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from "
|
|
1
|
+
export { default } from "../RvfStationsLayer";
|
|
@@ -2,6 +2,7 @@ import { useId, useState } from "preact/hooks";
|
|
|
2
2
|
import { twMerge } from "tailwind-merge";
|
|
3
3
|
|
|
4
4
|
import Copy from "../../icons/Copy";
|
|
5
|
+
import useI18n from "../../utils/hooks/useI18n";
|
|
5
6
|
import IconButton from "../IconButton";
|
|
6
7
|
import Input from "../Input";
|
|
7
8
|
|
|
@@ -24,31 +25,38 @@ function InputCopy({
|
|
|
24
25
|
tooltipProps = emptyProps,
|
|
25
26
|
...props
|
|
26
27
|
}: InputCopyProps) {
|
|
28
|
+
const { t } = useI18n();
|
|
27
29
|
const [positionTooltip, setPositionTooltip] = useState<DOMRect>();
|
|
28
30
|
const [isTooptipShowed, setIsTooltipShowed] = useState(false);
|
|
29
31
|
const inputId = useId();
|
|
32
|
+
const [node, setNode] = useState<HTMLDivElement | null>(null);
|
|
30
33
|
|
|
31
34
|
const handleCopyClick = (event) => {
|
|
32
35
|
setPositionTooltip(event.currentTarget.getBoundingClientRect());
|
|
33
|
-
|
|
36
|
+
const input: HTMLInputElement | null = node.querySelector(`#${inputId}`);
|
|
37
|
+
void navigator.clipboard.writeText(input?.value).then(() => {
|
|
34
38
|
setIsTooltipShowed(true);
|
|
35
39
|
setTimeout(() => {
|
|
36
40
|
setIsTooltipShowed(false);
|
|
37
41
|
}, 1000);
|
|
38
42
|
});
|
|
39
|
-
|
|
43
|
+
input?.select();
|
|
40
44
|
};
|
|
41
45
|
|
|
42
46
|
const handleInputFocus = () => {
|
|
43
|
-
|
|
47
|
+
const input: HTMLInputElement | null = node.querySelector(`#${inputId}`);
|
|
48
|
+
input?.select();
|
|
44
49
|
};
|
|
45
50
|
|
|
46
51
|
return (
|
|
47
52
|
<div
|
|
53
|
+
ref={(elt) => {
|
|
54
|
+
setNode(elt);
|
|
55
|
+
}}
|
|
48
56
|
{...containerProps}
|
|
49
57
|
className={twMerge(
|
|
50
|
-
"relative flex items-center",
|
|
51
|
-
containerProps?.className,
|
|
58
|
+
"relative flex h-7 items-center",
|
|
59
|
+
containerProps?.className as string,
|
|
52
60
|
)}
|
|
53
61
|
>
|
|
54
62
|
<Input
|
|
@@ -57,27 +65,30 @@ function InputCopy({
|
|
|
57
65
|
readOnly
|
|
58
66
|
type="text"
|
|
59
67
|
{...props}
|
|
60
|
-
className={twMerge(
|
|
68
|
+
className={twMerge(
|
|
69
|
+
"h-7 flex-1 border border-r-0",
|
|
70
|
+
props?.className as string,
|
|
71
|
+
)}
|
|
61
72
|
/>
|
|
62
73
|
<IconButton
|
|
63
|
-
className="
|
|
74
|
+
className="size-7 rounded-none border p-2 shadow-none"
|
|
64
75
|
onClick={handleCopyClick}
|
|
65
76
|
>
|
|
66
|
-
<Copy />
|
|
77
|
+
<Copy size={20} />
|
|
67
78
|
</IconButton>
|
|
68
79
|
<div
|
|
69
80
|
{...tooltipProps}
|
|
70
81
|
className={twMerge(
|
|
71
82
|
`fixed hidden rounded bg-gray-600 p-1 text-sm text-white`,
|
|
72
83
|
isTooptipShowed && "block",
|
|
73
|
-
tooltipProps?.className,
|
|
84
|
+
tooltipProps?.className as string,
|
|
74
85
|
)}
|
|
75
86
|
style={{
|
|
76
87
|
left: positionTooltip?.left - 30,
|
|
77
88
|
top: positionTooltip?.top - 30,
|
|
78
89
|
}}
|
|
79
90
|
>
|
|
80
|
-
|
|
91
|
+
{t("input_copy_success")}!
|
|
81
92
|
</div>
|
|
82
93
|
</div>
|
|
83
94
|
);
|
package/src/utils/constants.ts
CHANGED
|
@@ -71,6 +71,7 @@ export const DEFAULT_QUERYABLE_LAYERS = Object.values(LAYERS_NAMES).filter(
|
|
|
71
71
|
// Order of the first level
|
|
72
72
|
export const LAYER_TREE_ORDER = [
|
|
73
73
|
LAYER_NAME_NOTIFICATIONS,
|
|
74
|
+
LAYER_NAME_MAPSET,
|
|
74
75
|
LAYER_NAME_REALTIME,
|
|
75
76
|
LAYER_NAME_STATIONS,
|
|
76
77
|
LAYER_NAME_LINESNETWORKPLAN,
|
|
@@ -78,7 +79,6 @@ export const LAYER_TREE_ORDER = [
|
|
|
78
79
|
LAYERS_NAMES.verkaufsstellen,
|
|
79
80
|
LAYERS_NAMES.pois,
|
|
80
81
|
LAYERS_NAMES.sharedMobility,
|
|
81
|
-
LAYER_NAME_MAPSET,
|
|
82
82
|
];
|
|
83
83
|
|
|
84
84
|
export const LAYERS_WITH_LINK = Object.values(LAYERS_NAMES).filter((name) => {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import getUrlFromTemplate from "./getUrlFromTemplate";
|
|
2
|
+
|
|
3
|
+
describe("getUrlFromTemplate", () => {
|
|
4
|
+
it("should replace parameters in the template", () => {
|
|
5
|
+
const template = "?z={{z}}&x={{x}}&y={{y}}";
|
|
6
|
+
const params = new URLSearchParams({ x: "512", y: "200", z: "10" });
|
|
7
|
+
const url = getUrlFromTemplate(template, params);
|
|
8
|
+
expect(url).toBe("http://localhost/?z=10&x=512&y=200");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should handle hash templates", () => {
|
|
12
|
+
const template = "#/map/{{z}}/{{x}}/{{y}}";
|
|
13
|
+
const params = new URLSearchParams({ x: "512", y: "200", z: "10" });
|
|
14
|
+
const url = getUrlFromTemplate(template, params);
|
|
15
|
+
expect(url).toBe("http://localhost/#/map/10/512/200");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should handle null templates returning the window location", () => {
|
|
19
|
+
const params = new URLSearchParams({ x: "512", y: "200", z: "10" });
|
|
20
|
+
const url = getUrlFromTemplate(null, params);
|
|
21
|
+
expect(url).toBe("http://localhost/");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return an url as a string from a template and a list of parameters.
|
|
3
|
+
* Example:
|
|
4
|
+
* template: "https://example.com/{{z}}/{{x}}/{{y}}.png"
|
|
5
|
+
* params: {z: "10", x: "512", y: "512"}
|
|
6
|
+
* return: "https://example.com/10/512/512.png"
|
|
7
|
+
*
|
|
8
|
+
* If a parameter is missing, the template is not replaced.
|
|
9
|
+
*
|
|
10
|
+
* @param template - The url template containing parameters in the form {{param}}
|
|
11
|
+
* @param params - An object containing the parameters to replace in the template
|
|
12
|
+
* @returns The url with the parameters replaced
|
|
13
|
+
*/
|
|
14
|
+
function getUrlFromTemplate(template: string, params: URLSearchParams): string {
|
|
15
|
+
let tpl = template || "";
|
|
16
|
+
params?.forEach((value, key) => {
|
|
17
|
+
tpl = tpl.replace(`{{${key}}}`, value);
|
|
18
|
+
});
|
|
19
|
+
if (tpl.startsWith("#")) {
|
|
20
|
+
tpl = `${window.location.href.split("#")[0]}${tpl}`;
|
|
21
|
+
} else if (tpl.startsWith("?") || !tpl) {
|
|
22
|
+
const existingParams = new URLSearchParams(window.location.search);
|
|
23
|
+
|
|
24
|
+
// Set current values of the template parameters
|
|
25
|
+
const tplParams = new URLSearchParams(tpl);
|
|
26
|
+
tplParams.forEach((value, key) => {
|
|
27
|
+
existingParams.set(key, value);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Remove duplicated parameters if the template already includes them
|
|
31
|
+
if (template?.includes("{{x}}") && template?.includes("{{y}}")) {
|
|
32
|
+
existingParams.delete("center");
|
|
33
|
+
}
|
|
34
|
+
if (template?.includes("{{z}}")) {
|
|
35
|
+
existingParams.delete("zoom");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let str = existingParams.toString();
|
|
39
|
+
if (!str.startsWith("?") && tpl.length) {
|
|
40
|
+
str = `?${str}`;
|
|
41
|
+
}
|
|
42
|
+
tpl = `${window.location.href.split("?")[0]}${str}${window.location.hash}`;
|
|
43
|
+
}
|
|
44
|
+
return tpl;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default getUrlFromTemplate;
|
|
@@ -3,11 +3,9 @@ import { useContext } from "preact/hooks";
|
|
|
3
3
|
|
|
4
4
|
import type { Rosetta } from "rosetta";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export type I18NContextType = Rosetta<Record<string, string>>;
|
|
7
7
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
export const I18nContext = createContext({
|
|
8
|
+
export const I18nContext = createContext<I18NContextType>({
|
|
11
9
|
t: (id: string, templateValues?: Record<string, string>) => {
|
|
12
10
|
return `${id} ${JSON.stringify(templateValues)}`;
|
|
13
11
|
},
|
|
@@ -1,28 +1,51 @@
|
|
|
1
1
|
import { getLayersAsFlatArray } from "mobility-toolbox-js/ol";
|
|
2
2
|
import { unByKey } from "ol/Observable";
|
|
3
|
-
import { useEffect } from "preact/hooks";
|
|
3
|
+
import { useEffect, useRef } from "preact/hooks";
|
|
4
4
|
|
|
5
5
|
import applyInitialLayerVisibility from "../applyInitialLayerVisibility";
|
|
6
6
|
|
|
7
|
+
import useInitialPermalink from "./useInitialPermalink";
|
|
8
|
+
|
|
7
9
|
import type { Map } from "ol";
|
|
10
|
+
const useInitialLayersVisiblity = (
|
|
11
|
+
map: Map,
|
|
12
|
+
layers: string,
|
|
13
|
+
permalinkTemplate: string,
|
|
14
|
+
) => {
|
|
15
|
+
const isPermalinkAlreadyUsed = useRef(false);
|
|
16
|
+
const permalinkLayersRef = useRef(
|
|
17
|
+
useInitialPermalink(permalinkTemplate)?.layers,
|
|
18
|
+
);
|
|
8
19
|
|
|
9
|
-
const useInitialLayersVisiblity = (map: Map, layers: string) => {
|
|
10
20
|
// Apply initial visibility of layers from layers attribute
|
|
11
21
|
useEffect(() => {
|
|
12
22
|
if (!map) {
|
|
13
23
|
return;
|
|
14
24
|
}
|
|
25
|
+
let layersToUse = layers;
|
|
26
|
+
|
|
27
|
+
// We use the permalink param only once, at the first render
|
|
28
|
+
if (
|
|
29
|
+
permalinkLayersRef.current !== null &&
|
|
30
|
+
permalinkLayersRef.current !== undefined &&
|
|
31
|
+
!isPermalinkAlreadyUsed.current
|
|
32
|
+
) {
|
|
33
|
+
layersToUse = permalinkLayersRef.current;
|
|
34
|
+
isPermalinkAlreadyUsed.current = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
15
37
|
getLayersAsFlatArray(map.getLayers().getArray()).forEach((layer) => {
|
|
16
|
-
applyInitialLayerVisibility(
|
|
38
|
+
applyInitialLayerVisibility(layersToUse, layer);
|
|
17
39
|
});
|
|
18
40
|
|
|
19
41
|
const key = map.getLayers().on("add", (event) => {
|
|
20
|
-
applyInitialLayerVisibility(
|
|
42
|
+
applyInitialLayerVisibility(layersToUse, event.element);
|
|
21
43
|
});
|
|
22
44
|
return () => {
|
|
23
45
|
unByKey(key);
|
|
24
46
|
};
|
|
25
47
|
}, [map, layers]);
|
|
48
|
+
|
|
26
49
|
return null;
|
|
27
50
|
};
|
|
28
51
|
|
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
import { useMemo
|
|
1
|
+
import { useMemo } from "preact/hooks";
|
|
2
|
+
|
|
3
|
+
import useMapContext from "./useMapContext";
|
|
2
4
|
|
|
3
5
|
import type { MobilityMapProps } from "../../MobilityMap/MobilityMap";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
* Return x,y and
|
|
8
|
+
* Return x,y,z and layers values from the url. This hook should not managed more usecases than that.
|
|
7
9
|
* The application should be responsible to read url parameters then provides these parameters as attributes to the web-component.
|
|
8
10
|
*/
|
|
9
11
|
const useInitialPermalink = (
|
|
10
|
-
|
|
12
|
+
permalinkTemplate?: string,
|
|
11
13
|
): null | Partial<MobilityMapProps> => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
+
const { permalinktemplate } = useMapContext();
|
|
14
15
|
const props = useMemo(() => {
|
|
15
|
-
|
|
16
|
+
const template = permalinkTemplate || permalinktemplate;
|
|
17
|
+
console.log("template", template);
|
|
18
|
+
if (!template) {
|
|
16
19
|
return null;
|
|
17
20
|
}
|
|
18
21
|
try {
|
|
19
|
-
let
|
|
22
|
+
let layers: null | string,
|
|
23
|
+
x: null | string,
|
|
20
24
|
y: null | string,
|
|
21
|
-
z: null | string
|
|
25
|
+
z: null | string;
|
|
22
26
|
|
|
23
|
-
if (
|
|
24
|
-
const urlSearchParams = new URLSearchParams(
|
|
27
|
+
if (template?.startsWith("?")) {
|
|
28
|
+
const urlSearchParams = new URLSearchParams(template);
|
|
25
29
|
const names = [...urlSearchParams.keys()];
|
|
26
30
|
const nameX = names.find((name) => {
|
|
27
31
|
return urlSearchParams.get(name).includes("{{x}}");
|
|
@@ -32,12 +36,16 @@ const useInitialPermalink = (
|
|
|
32
36
|
const nameZ = names.find((name) => {
|
|
33
37
|
return urlSearchParams.get(name).includes("{{z}}");
|
|
34
38
|
});
|
|
39
|
+
const nameLayers = names.find((name) => {
|
|
40
|
+
return urlSearchParams.get(name).includes("{{layers}}");
|
|
41
|
+
});
|
|
35
42
|
const currSearchParams = new URLSearchParams(window.location.search);
|
|
36
43
|
x = currSearchParams.get(nameX);
|
|
37
44
|
y = currSearchParams.get(nameY);
|
|
38
45
|
z = currSearchParams.get(nameZ);
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
layers = currSearchParams.get(nameLayers);
|
|
47
|
+
} else if (template?.startsWith("#")) {
|
|
48
|
+
const values = template.substring(1).split("/");
|
|
41
49
|
const currHash = window.location.hash;
|
|
42
50
|
const currIndexes = currHash.substring(1).split("/");
|
|
43
51
|
const indexX = values.findIndex((name) => {
|
|
@@ -49,9 +57,13 @@ const useInitialPermalink = (
|
|
|
49
57
|
const indexZ = values.findIndex((name) => {
|
|
50
58
|
return name.includes("{{z}}");
|
|
51
59
|
});
|
|
60
|
+
const indexLayers = values.findIndex((name) => {
|
|
61
|
+
return name.includes("{{layers}}");
|
|
62
|
+
});
|
|
52
63
|
x = indexX > -1 ? currIndexes[indexX] : null;
|
|
53
64
|
y = indexY > -1 ? currIndexes[indexY] : null;
|
|
54
65
|
z = indexZ > -1 ? currIndexes[indexZ] : null;
|
|
66
|
+
layers = indexLayers > -1 ? currIndexes[indexLayers] : null;
|
|
55
67
|
}
|
|
56
68
|
const propsFromPermalink: Partial<MobilityMapProps> = {};
|
|
57
69
|
if (x && y) {
|
|
@@ -60,24 +72,22 @@ const useInitialPermalink = (
|
|
|
60
72
|
if (z) {
|
|
61
73
|
propsFromPermalink.zoom = z;
|
|
62
74
|
}
|
|
75
|
+
if (layers !== null && layers !== undefined) {
|
|
76
|
+
propsFromPermalink.layers = layers;
|
|
77
|
+
}
|
|
63
78
|
return propsFromPermalink;
|
|
64
79
|
} catch (error) {
|
|
65
80
|
// eslint-disable-next-line no-console
|
|
66
81
|
console.warn(
|
|
67
|
-
"Impossible to read x,y,z from the url with
|
|
68
|
-
|
|
82
|
+
"Impossible to read x,y,z and layers from the url with template",
|
|
83
|
+
template,
|
|
69
84
|
error,
|
|
70
85
|
);
|
|
71
86
|
}
|
|
72
87
|
return null;
|
|
73
|
-
}, [permalinktemplate]);
|
|
88
|
+
}, [permalinktemplate, permalinkTemplate]);
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
if (!prevProps.current && props) {
|
|
77
|
-
prevProps.current = props;
|
|
78
|
-
return props;
|
|
79
|
-
}
|
|
80
|
-
return {};
|
|
90
|
+
return props;
|
|
81
91
|
};
|
|
82
92
|
|
|
83
93
|
export default useInitialPermalink;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// import debounce from "lodash.debounce";
|
|
2
|
+
// import { getLayersAsFlatArray } from "mobility-toolbox-js/ol";
|
|
3
|
+
// import { unByKey } from "ol/Observable";
|
|
4
|
+
// import { useCallback, useEffect } from "preact/hooks";
|
|
5
|
+
|
|
6
|
+
import getUrlFromTemplate from "../getUrlFromTemplate";
|
|
7
|
+
|
|
8
|
+
import useMapContext from "./useMapContext";
|
|
9
|
+
|
|
10
|
+
// import { LAYER_PROP_IS_EXPORTING } from "../constants";
|
|
11
|
+
// import getPermalinkParameters from "../getPermalinkParameters";
|
|
12
|
+
// // import getLayersAsFlatArray from "../getLayersAsFlatArray";
|
|
13
|
+
|
|
14
|
+
// import useMapContext from "./useMapContext";
|
|
15
|
+
|
|
16
|
+
// import type { Map } from "ol";
|
|
17
|
+
// import type { EventsKey } from "ol/events";
|
|
18
|
+
|
|
19
|
+
function usePermalink() {
|
|
20
|
+
const { permalinktemplate, permalinkUrlSearchParams } = useMapContext();
|
|
21
|
+
const url = getUrlFromTemplate(permalinktemplate, permalinkUrlSearchParams);
|
|
22
|
+
return url;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default usePermalink;
|
|
@@ -20,6 +20,7 @@ const translations: Translations = {
|
|
|
20
20
|
from_to: "von {{from}} bis {{to}}",
|
|
21
21
|
geolocation_button_title_off: "Geolokalisierung deaktivieren",
|
|
22
22
|
geolocation_button_title_on: "Geolokalisierung aktivieren",
|
|
23
|
+
input_copy_success: "Kopiert!",
|
|
23
24
|
[LAYERS_NAMES.bikeFrelo]: "Frelo",
|
|
24
25
|
[LAYERS_NAMES.bikeOthers]: "Fahrrad, andere Anbieter",
|
|
25
26
|
[LAYERS_NAMES.cargobikeFrelo]: "Lastenfrelo",
|
|
@@ -76,6 +77,7 @@ const translations: Translations = {
|
|
|
76
77
|
from_to: "from {{from}} to {{to}}",
|
|
77
78
|
geolocation_button_title_off: "Disable geolocation",
|
|
78
79
|
geolocation_button_title_on: "Enable geolocation",
|
|
80
|
+
input_copy_success: "Copied!",
|
|
79
81
|
[LAYERS_NAMES.bikeFrelo]: "Frelo",
|
|
80
82
|
[LAYERS_NAMES.bikeOthers]: "Bicycle, other providers",
|
|
81
83
|
[LAYERS_NAMES.cargobikeFrelo]: "Cargo bike Frelo",
|
|
@@ -129,6 +131,7 @@ const translations: Translations = {
|
|
|
129
131
|
from_to: "de {{from}} à {{to}}",
|
|
130
132
|
geolocation_button_title_off: "Désactiver la géolocalisation",
|
|
131
133
|
geolocation_button_title_on: "Activer la géolocalisation",
|
|
134
|
+
input_copy_success: "Copié!",
|
|
132
135
|
[LAYERS_NAMES.bikeFrelo]: "Frelo",
|
|
133
136
|
[LAYERS_NAMES.bikeOthers]: "Vélo, autres fournisseurs",
|
|
134
137
|
[LAYERS_NAMES.cargobikeFrelo]: "Cargobike Frelo",
|
|
@@ -182,6 +185,7 @@ const translations: Translations = {
|
|
|
182
185
|
from_to: "da {{from}} a {{to}}",
|
|
183
186
|
geolocation_button_title_off: "Disattiva geolocalizzazione",
|
|
184
187
|
geolocation_button_title_on: "Attiva geolocalizzazione",
|
|
188
|
+
input_copy_success: "Copiato!",
|
|
185
189
|
[LAYERS_NAMES.bikeFrelo]: "Frelo",
|
|
186
190
|
[LAYERS_NAMES.bikeOthers]: "Bicicletta, altri fornitori",
|
|
187
191
|
[LAYERS_NAMES.cargobikeFrelo]: "Cargobike Frelo",
|