@panoramax/web-viewer 4.0.2-develop-9d664bb8 → 4.0.2-develop-e389d775
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 +4 -0
- package/build/index.css +1 -1
- package/build/index.css.map +1 -1
- package/build/index.js +274 -59
- package/build/index.js.map +1 -1
- package/config/jest/mocks.js +5 -0
- package/docs/reference/components/core/PhotoViewer.md +1 -0
- package/docs/reference/components/core/Viewer.md +1 -0
- package/docs/reference/components/menus/AnnotationsList.md +16 -0
- package/docs/reference/components/ui/HashTags.md +15 -0
- package/docs/reference/components/ui/ListItem.md +38 -0
- package/docs/reference/components/ui/Photo.md +53 -1
- package/docs/reference/components/ui/SemanticsTable.md +32 -0
- package/docs/reference/utils/PresetsManager.md +35 -0
- package/docs/reference.md +4 -0
- package/mkdocs.yml +4 -0
- package/package.json +2 -1
- package/src/components/core/Basic.css +2 -0
- package/src/components/core/PhotoViewer.js +11 -0
- package/src/components/core/Viewer.js +7 -0
- package/src/components/layout/Tabs.js +1 -1
- package/src/components/menus/AnnotationsList.js +146 -0
- package/src/components/menus/PictureLegend.js +2 -4
- package/src/components/menus/PictureMetadata.js +66 -2
- package/src/components/menus/index.js +1 -0
- package/src/components/styles.js +34 -0
- package/src/components/ui/HashTags.js +98 -0
- package/src/components/ui/ListItem.js +83 -0
- package/src/components/ui/Photo.js +137 -0
- package/src/components/ui/SemanticsTable.js +87 -0
- package/src/components/ui/index.js +3 -0
- package/src/img/osm.svg +49 -0
- package/src/img/wd.svg +1 -0
- package/src/translations/en.json +22 -0
- package/src/translations/fr.json +20 -0
- package/src/utils/PresetsManager.js +137 -0
- package/src/utils/geocoder.js +23 -57
- package/src/utils/index.js +3 -1
- package/src/utils/picture.js +28 -0
- package/src/utils/semantics.js +162 -0
- package/src/utils/services.js +38 -0
- package/src/utils/widgets.js +18 -1
- package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +10 -0
- package/tests/components/core/__snapshots__/Viewer.test.js.snap +10 -0
- package/tests/data/Map_geocoder_nominatim.json +25 -40
- package/tests/utils/PresetsManager.test.js +123 -0
- package/tests/utils/__snapshots__/geocoder.test.js.snap +5 -10
- package/tests/utils/geocoder.test.js +1 -1
- package/tests/utils/semantics.test.js +125 -0
|
@@ -1,56 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "FeatureCollection",
|
|
3
|
-
"
|
|
3
|
+
"geocoding": {
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"attribution": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright",
|
|
6
|
+
"licence": "ODbL",
|
|
7
|
+
"query": "paris"
|
|
8
|
+
},
|
|
4
9
|
"features": [
|
|
5
10
|
{
|
|
6
11
|
"type": "Feature",
|
|
7
12
|
"properties": {
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"address": {
|
|
18
|
-
"suburb": "Paris",
|
|
19
|
-
"city_district": "Paris",
|
|
20
|
-
"city": "Paris",
|
|
21
|
-
"ISO3166-2-lvl6": "FR-75",
|
|
13
|
+
"geocoding": {
|
|
14
|
+
"place_id": 88066702,
|
|
15
|
+
"osm_type": "relation",
|
|
16
|
+
"osm_id": 71525,
|
|
17
|
+
"osm_key": "boundary",
|
|
18
|
+
"osm_value": "administrative",
|
|
19
|
+
"type": "city",
|
|
20
|
+
"label": "Paris, Île-de-France, France métropolitaine, France",
|
|
21
|
+
"name": "Paris",
|
|
22
22
|
"state": "Île-de-France",
|
|
23
|
-
"ISO3166-2-lvl4": "FR-IDF",
|
|
24
|
-
"region": "France métropolitaine",
|
|
25
23
|
"country": "France",
|
|
26
|
-
"country_code": "fr"
|
|
24
|
+
"country_code": "fr",
|
|
25
|
+
"admin": {
|
|
26
|
+
"level6": "Paris",
|
|
27
|
+
"level4": "Île-de-France",
|
|
28
|
+
"level3": "France métropolitaine"
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
},
|
|
29
|
-
"bbox": [
|
|
30
|
-
2.224122,
|
|
31
|
-
48.8155755,
|
|
32
|
-
2.4697602,
|
|
33
|
-
48.902156
|
|
34
|
-
],
|
|
35
32
|
"geometry": {
|
|
36
|
-
"type": "
|
|
33
|
+
"type": "Point",
|
|
37
34
|
"coordinates": [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
2.224122,
|
|
41
|
-
48.854199
|
|
42
|
-
],
|
|
43
|
-
[
|
|
44
|
-
2.224125,
|
|
45
|
-
48.85402
|
|
46
|
-
],
|
|
47
|
-
[
|
|
48
|
-
2.224125,
|
|
49
|
-
48.853869
|
|
50
|
-
]
|
|
51
|
-
]
|
|
35
|
+
2.3483915,
|
|
36
|
+
48.8534951
|
|
52
37
|
]
|
|
53
38
|
}
|
|
54
39
|
}
|
|
55
40
|
]
|
|
56
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import PresetsManager from "../../src/utils/PresetsManager";
|
|
2
|
+
|
|
3
|
+
const mockPresets = {
|
|
4
|
+
"osm_traffic_sign": {
|
|
5
|
+
"icon": "fas-directions",
|
|
6
|
+
"tags": {
|
|
7
|
+
"osm|traffic_sign": "*"
|
|
8
|
+
},
|
|
9
|
+
"geometry": [
|
|
10
|
+
"point",
|
|
11
|
+
"vertex"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"osm_traffic_calming": {
|
|
15
|
+
"icon": "temaki-diamond",
|
|
16
|
+
"tags": {
|
|
17
|
+
"osm|traffic_calming": "*"
|
|
18
|
+
},
|
|
19
|
+
"geometry": [
|
|
20
|
+
"vertex"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"osm_shop": {
|
|
24
|
+
"icon": "maki-shop",
|
|
25
|
+
"tags": {
|
|
26
|
+
"osm|shop": "*"
|
|
27
|
+
},
|
|
28
|
+
"geometry": [
|
|
29
|
+
"point",
|
|
30
|
+
"area"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Mock des appels fetch
|
|
36
|
+
global.fetch = jest.fn(() =>
|
|
37
|
+
Promise.resolve({
|
|
38
|
+
ok: true,
|
|
39
|
+
json: () => Promise.resolve({}),
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
fetch.mockClear();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should initialize with default values", () => {
|
|
48
|
+
const presetsManager = new PresetsManager(null, true);
|
|
49
|
+
expect(presetsManager._ready).toBe(false);
|
|
50
|
+
expect(presetsManager._presets).toBe(null);
|
|
51
|
+
expect(presetsManager._translations).toEqual({});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should load translations and presets", async () => {
|
|
55
|
+
const mockTranslationsEN = { en: { presets: { preset1: { name: "Preset 1" } } } };
|
|
56
|
+
const mockTranslationsFR = { fr: { presets: { preset1: { name: "Préréglage 1" } } } };
|
|
57
|
+
|
|
58
|
+
fetch.mockImplementationOnce(() =>
|
|
59
|
+
Promise.resolve({
|
|
60
|
+
ok: true,
|
|
61
|
+
json: () => Promise.resolve(mockTranslationsEN),
|
|
62
|
+
})
|
|
63
|
+
).mockImplementationOnce(() =>
|
|
64
|
+
Promise.resolve({
|
|
65
|
+
ok: true,
|
|
66
|
+
json: () => Promise.resolve(mockTranslationsFR),
|
|
67
|
+
})
|
|
68
|
+
).mockImplementationOnce(() =>
|
|
69
|
+
Promise.resolve({
|
|
70
|
+
ok: true,
|
|
71
|
+
json: () => Promise.resolve(mockPresets),
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const presetsManager = new PresetsManager("fr");
|
|
76
|
+
await presetsManager.onceReady();
|
|
77
|
+
|
|
78
|
+
expect(presetsManager._translations.en).toEqual(mockTranslationsEN.en.presets);
|
|
79
|
+
expect(presetsManager._translations.fr).toEqual(mockTranslationsFR.fr.presets);
|
|
80
|
+
expect(presetsManager._presets).toEqual(mockPresets);
|
|
81
|
+
expect(presetsManager._ready).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should handle errors during load", async () => {
|
|
85
|
+
global.console = { error: jest.fn() };
|
|
86
|
+
|
|
87
|
+
fetch.mockImplementation(() =>
|
|
88
|
+
Promise.resolve({
|
|
89
|
+
ok: false,
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const presetsManager = new PresetsManager();
|
|
94
|
+
await expect(presetsManager.onceReady()).rejects.toBeUndefined();
|
|
95
|
+
expect(presetsManager._ready).toBe(-1);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should find the best matching preset", async () => {
|
|
99
|
+
fetch.mockImplementationOnce(() =>
|
|
100
|
+
Promise.resolve({
|
|
101
|
+
ok: true,
|
|
102
|
+
json: () => Promise.resolve({}),
|
|
103
|
+
})
|
|
104
|
+
).mockImplementationOnce(() =>
|
|
105
|
+
Promise.resolve({
|
|
106
|
+
ok: true,
|
|
107
|
+
json: () => Promise.resolve({}),
|
|
108
|
+
})
|
|
109
|
+
).mockImplementationOnce(() =>
|
|
110
|
+
Promise.resolve({
|
|
111
|
+
ok: true,
|
|
112
|
+
json: () => Promise.resolve(mockPresets),
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const presetsManager = new PresetsManager();
|
|
117
|
+
await presetsManager.onceReady();
|
|
118
|
+
|
|
119
|
+
const feature = { semantics: [{ key: "key1", value: "value1" }, { key: "key2", value: "value2" }] };
|
|
120
|
+
const bestPreset = await presetsManager.getPreset(feature);
|
|
121
|
+
|
|
122
|
+
expect(bestPreset).toEqual(mockPresets.preset2);
|
|
123
|
+
});
|
|
@@ -22,20 +22,15 @@ exports[`forwardGeocodingNominatim works 1`] = `
|
|
|
22
22
|
Object {
|
|
23
23
|
"features": Array [
|
|
24
24
|
Object {
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
"lng": -1.7,
|
|
29
|
-
},
|
|
30
|
-
"sw": Object {
|
|
31
|
-
"lat": 47.8,
|
|
32
|
-
"lng": -1.7,
|
|
33
|
-
},
|
|
25
|
+
"center": Object {
|
|
26
|
+
"lat": 47.8,
|
|
27
|
+
"lng": -1.7,
|
|
34
28
|
},
|
|
35
|
-
"place_name": "Paris",
|
|
29
|
+
"place_name": "Paris, Île-de-France",
|
|
36
30
|
"place_type": Array [
|
|
37
31
|
"place",
|
|
38
32
|
],
|
|
33
|
+
"zoom": 12,
|
|
39
34
|
},
|
|
40
35
|
],
|
|
41
36
|
}
|
|
@@ -13,7 +13,7 @@ describe("forwardGeocodingNominatim", () => {
|
|
|
13
13
|
const cfg = { query: "bla", limit: 5, bbox: "17.7,-45.2,17.8,-45.1" };
|
|
14
14
|
|
|
15
15
|
return geocoder.forwardGeocodingNominatim(cfg).then(res => {
|
|
16
|
-
expect(global.fetch.mock.calls).toEqual([["https://nominatim.openstreetmap.org/search?q=bla&limit=5&viewbox=17.7%2C-45.2%2C17.8%2C-45.1&format=
|
|
16
|
+
expect(global.fetch.mock.calls).toEqual([["https://nominatim.openstreetmap.org/search?q=bla&limit=5&viewbox=17.7%2C-45.2%2C17.8%2C-45.1&format=geocodejson&addressdetails=1"]]);
|
|
17
17
|
expect(res).toMatchSnapshot();
|
|
18
18
|
});
|
|
19
19
|
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { decodeKey, decodeBasicTag, groupByPrefix } from "../../src/utils/semantics";
|
|
2
|
+
|
|
3
|
+
describe("decodeBasicTag", () => {
|
|
4
|
+
test("should return null if no equal sign is present", () => {
|
|
5
|
+
expect(decodeBasicTag("key")).toBeNull();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("should correctly decode a tag with an equal sign", () => {
|
|
9
|
+
expect(decodeBasicTag("key=value")).toEqual({
|
|
10
|
+
key: { prefix: "", subkey: "key", qualifies: null },
|
|
11
|
+
value: "value"
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("should correctly decode a tag with a prefix", () => {
|
|
16
|
+
expect(decodeBasicTag("osm|key=value")).toEqual({
|
|
17
|
+
key: { prefix: "osm", subkey: "key", qualifies: null },
|
|
18
|
+
value: "value"
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("decodeKey", () => {
|
|
24
|
+
test("should return default structure if key does not match regex", () => {
|
|
25
|
+
expect(decodeKey("panoKey")).toEqual({
|
|
26
|
+
prefix: "",
|
|
27
|
+
subkey: "panoKey",
|
|
28
|
+
qualifies: null
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("should correctly decode a key with a prefix", () => {
|
|
33
|
+
expect(decodeKey("osm|traffic_sign")).toEqual({
|
|
34
|
+
prefix: "osm",
|
|
35
|
+
subkey: "traffic_sign",
|
|
36
|
+
qualifies: null
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("should correctly decode a key with qualifiers", () => {
|
|
41
|
+
expect(decodeKey("detection_model[camera_mount=pole]")).toEqual({
|
|
42
|
+
prefix: "",
|
|
43
|
+
subkey: "detection_model",
|
|
44
|
+
qualifies: { key: { prefix: "", subkey: "camera_mount", qualifies: null }, value: "pole" }
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("should correctly decode a key with a prefix and qualifiers", () => {
|
|
49
|
+
expect(decodeKey("osm|source[osm|traffic_sign=stop]")).toEqual({
|
|
50
|
+
prefix: "osm",
|
|
51
|
+
subkey: "source",
|
|
52
|
+
qualifies: { key: { prefix: "osm", subkey: "traffic_sign", qualifies: null }, value: "stop" }
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("groupByPrefix", () => {
|
|
58
|
+
test("should group tags by prefix", () => {
|
|
59
|
+
const tags = [
|
|
60
|
+
{ key: "osm|highway", value: "residential" },
|
|
61
|
+
{ key: "wd|P31", value: "Q5" },
|
|
62
|
+
{ key: "exif|model", value: "CameraModel" }
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const expected = [
|
|
66
|
+
{
|
|
67
|
+
prefix: "osm",
|
|
68
|
+
title: "OpenStreetMap",
|
|
69
|
+
tags: [{ key: "highway", value: "residential" }],
|
|
70
|
+
key_transform: expect.any(Function),
|
|
71
|
+
logo: "osm.svg",
|
|
72
|
+
value_transform: expect.any(Function)
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
prefix: "wd",
|
|
76
|
+
title: "Wikidata",
|
|
77
|
+
tags: [{ key: "P31", value: "Q5" }],
|
|
78
|
+
key_transform: expect.any(Function),
|
|
79
|
+
logo: "wd.svg",
|
|
80
|
+
value_transform: expect.any(Function)
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
prefix: "exif",
|
|
84
|
+
title: "EXIF",
|
|
85
|
+
tags: [{ key: "model", value: "CameraModel" }]
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
expect(groupByPrefix(tags)).toEqual(expected);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("should handle qualifiers correctly", () => {
|
|
93
|
+
const tags = [
|
|
94
|
+
{ key: "osm|highway", value: "residential" },
|
|
95
|
+
{ key: "osm|source[osm|highway=residential]", value: "opendata" }
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const expected = [{
|
|
99
|
+
prefix: "osm",
|
|
100
|
+
title: "OpenStreetMap",
|
|
101
|
+
tags: [{
|
|
102
|
+
key: "highway",
|
|
103
|
+
value: "residential",
|
|
104
|
+
qualifiers: [{ key: "osm|source[osm|highway=residential]", prefix: "osm", subkey: "source", value: "opendata" }]
|
|
105
|
+
}],
|
|
106
|
+
key_transform: expect.any(Function),
|
|
107
|
+
logo: "osm.svg",
|
|
108
|
+
value_transform: expect.any(Function)
|
|
109
|
+
}];
|
|
110
|
+
|
|
111
|
+
expect(groupByPrefix(tags)).toEqual(expected);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("should handle unknown prefixes", () => {
|
|
115
|
+
const tags = [ { key: "unknown|key", value: "value" } ];
|
|
116
|
+
|
|
117
|
+
const expected = [{
|
|
118
|
+
prefix: "unknown",
|
|
119
|
+
title: "unknown",
|
|
120
|
+
tags: [{ key: "key", value: "value" }]
|
|
121
|
+
}];
|
|
122
|
+
|
|
123
|
+
expect(groupByPrefix(tags)).toEqual(expected);
|
|
124
|
+
});
|
|
125
|
+
});
|