@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/index.css +1 -1
  3. package/build/index.css.map +1 -1
  4. package/build/index.js +274 -59
  5. package/build/index.js.map +1 -1
  6. package/config/jest/mocks.js +5 -0
  7. package/docs/reference/components/core/PhotoViewer.md +1 -0
  8. package/docs/reference/components/core/Viewer.md +1 -0
  9. package/docs/reference/components/menus/AnnotationsList.md +16 -0
  10. package/docs/reference/components/ui/HashTags.md +15 -0
  11. package/docs/reference/components/ui/ListItem.md +38 -0
  12. package/docs/reference/components/ui/Photo.md +53 -1
  13. package/docs/reference/components/ui/SemanticsTable.md +32 -0
  14. package/docs/reference/utils/PresetsManager.md +35 -0
  15. package/docs/reference.md +4 -0
  16. package/mkdocs.yml +4 -0
  17. package/package.json +2 -1
  18. package/src/components/core/Basic.css +2 -0
  19. package/src/components/core/PhotoViewer.js +11 -0
  20. package/src/components/core/Viewer.js +7 -0
  21. package/src/components/layout/Tabs.js +1 -1
  22. package/src/components/menus/AnnotationsList.js +146 -0
  23. package/src/components/menus/PictureLegend.js +2 -4
  24. package/src/components/menus/PictureMetadata.js +66 -2
  25. package/src/components/menus/index.js +1 -0
  26. package/src/components/styles.js +34 -0
  27. package/src/components/ui/HashTags.js +98 -0
  28. package/src/components/ui/ListItem.js +83 -0
  29. package/src/components/ui/Photo.js +137 -0
  30. package/src/components/ui/SemanticsTable.js +87 -0
  31. package/src/components/ui/index.js +3 -0
  32. package/src/img/osm.svg +49 -0
  33. package/src/img/wd.svg +1 -0
  34. package/src/translations/en.json +22 -0
  35. package/src/translations/fr.json +20 -0
  36. package/src/utils/PresetsManager.js +137 -0
  37. package/src/utils/geocoder.js +23 -57
  38. package/src/utils/index.js +3 -1
  39. package/src/utils/picture.js +28 -0
  40. package/src/utils/semantics.js +162 -0
  41. package/src/utils/services.js +38 -0
  42. package/src/utils/widgets.js +18 -1
  43. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +10 -0
  44. package/tests/components/core/__snapshots__/Viewer.test.js.snap +10 -0
  45. package/tests/data/Map_geocoder_nominatim.json +25 -40
  46. package/tests/utils/PresetsManager.test.js +123 -0
  47. package/tests/utils/__snapshots__/geocoder.test.js.snap +5 -10
  48. package/tests/utils/geocoder.test.js +1 -1
  49. package/tests/utils/semantics.test.js +125 -0
@@ -1,56 +1,41 @@
1
1
  {
2
2
  "type": "FeatureCollection",
3
- "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
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
- "place_id": 297417241,
9
- "osm_type": "relation",
10
- "osm_id": 7444,
11
- "display_name": "Paris, Île-de-France, France métropolitaine, France",
12
- "place_rank": 15,
13
- "category": "boundary",
14
- "type": "administrative",
15
- "importance": 0.9317101715588673,
16
- "icon": "https://nominatim.openstreetmap.org/ui/mapicons/poi_boundary_administrative.p.20.png",
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": "Polygon",
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
- "bounds": Object {
26
- "ne": Object {
27
- "lat": 47.8,
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=geojson&polygon_geojson=1&addressdetails=1"]]);
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
+ });