@panoramax/web-viewer 3.2.3-develop-f219e404 → 3.2.3-develop-6257391e

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 (221) hide show
  1. package/.gitlab-ci.yml +3 -0
  2. package/CHANGELOG.md +19 -0
  3. package/CODE_OF_CONDUCT.md +1 -1
  4. package/README.md +1 -1
  5. package/build/editor.html +10 -1
  6. package/build/index.css +2 -2
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +1682 -5
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/viewer.html +10 -1
  13. package/build/widgets.html +1 -0
  14. package/config/jest/mocks.js +172 -0
  15. package/config/paths.js +1 -0
  16. package/config/webpack.config.js +26 -0
  17. package/docs/03_URL_settings.md +3 -11
  18. package/docs/05_Compatibility.md +59 -76
  19. package/docs/09_Develop.md +30 -11
  20. package/docs/90_Releases.md +2 -2
  21. package/docs/images/class_diagram.drawio +28 -28
  22. package/docs/images/class_diagram.jpg +0 -0
  23. package/docs/index.md +112 -0
  24. package/docs/reference/components/core/Basic.md +153 -0
  25. package/docs/reference/components/core/CoverageMap.md +160 -0
  26. package/docs/reference/components/core/Editor.md +172 -0
  27. package/docs/reference/components/core/Viewer.md +288 -0
  28. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  29. package/docs/reference/components/layout/Mini.md +45 -0
  30. package/docs/reference/components/menus/MapBackground.md +32 -0
  31. package/docs/reference/components/menus/MapFilters.md +15 -0
  32. package/docs/reference/components/menus/MapLayers.md +15 -0
  33. package/docs/reference/components/menus/MapLegend.md +15 -0
  34. package/docs/reference/components/menus/PictureLegend.md +15 -0
  35. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  36. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  37. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  38. package/docs/reference/components/menus/ReportForm.md +15 -0
  39. package/docs/reference/components/menus/ShareMenu.md +15 -0
  40. package/docs/reference/components/ui/Button.md +39 -0
  41. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  42. package/docs/reference/components/ui/CopyButton.md +35 -0
  43. package/docs/reference/components/ui/Grade.md +32 -0
  44. package/docs/reference/components/ui/LinkButton.md +44 -0
  45. package/docs/reference/components/ui/Loader.md +54 -0
  46. package/docs/reference/components/ui/Map.md +214 -0
  47. package/docs/reference/components/ui/MapMore.md +233 -0
  48. package/docs/reference/components/ui/Photo.md +369 -0
  49. package/docs/reference/components/ui/Popup.md +56 -0
  50. package/docs/reference/components/ui/QualityScore.md +45 -0
  51. package/docs/reference/components/ui/SearchBar.md +63 -0
  52. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  53. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  54. package/docs/reference/components/ui/widgets/Legend.md +32 -0
  55. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  56. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  57. package/docs/reference/components/ui/widgets/Player.md +32 -0
  58. package/docs/reference/components/ui/widgets/Share.md +15 -0
  59. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  60. package/docs/reference/utils/API.md +311 -0
  61. package/docs/reference/utils/InitParameters.md +67 -0
  62. package/docs/reference/utils/URLHandler.md +102 -0
  63. package/docs/reference.md +73 -0
  64. package/docs/shortcuts.md +11 -0
  65. package/docs/tutorials/aerial_imagery.md +19 -0
  66. package/docs/tutorials/authentication.md +10 -0
  67. package/docs/tutorials/custom_widgets.md +64 -0
  68. package/docs/tutorials/map_style.md +27 -0
  69. package/docs/tutorials/migrate_v4.md +122 -0
  70. package/docs/tutorials/synced_coverage.md +42 -0
  71. package/mkdocs.yml +60 -5
  72. package/package.json +10 -7
  73. package/public/editor.html +21 -29
  74. package/public/index.html +3 -3
  75. package/public/map.html +19 -18
  76. package/public/viewer.html +18 -24
  77. package/public/widgets.html +265 -0
  78. package/scripts/doc.js +77 -0
  79. package/src/components/core/Basic.css +44 -0
  80. package/src/components/core/Basic.js +258 -0
  81. package/src/components/core/CoverageMap.css +9 -0
  82. package/src/components/core/CoverageMap.js +105 -0
  83. package/src/components/core/Editor.css +23 -0
  84. package/src/components/core/Editor.js +354 -0
  85. package/src/components/core/Viewer.css +109 -0
  86. package/src/components/core/Viewer.js +707 -0
  87. package/src/components/core/index.js +11 -0
  88. package/src/components/index.js +13 -0
  89. package/src/components/layout/CorneredGrid.js +109 -0
  90. package/src/components/layout/Mini.js +117 -0
  91. package/src/components/layout/index.js +7 -0
  92. package/src/components/menus/MapBackground.js +106 -0
  93. package/src/components/menus/MapFilters.js +386 -0
  94. package/src/components/menus/MapLayers.js +143 -0
  95. package/src/components/menus/MapLegend.js +54 -0
  96. package/src/components/menus/PictureLegend.js +103 -0
  97. package/src/components/menus/PictureMetadata.js +188 -0
  98. package/src/components/menus/PlayerOptions.js +96 -0
  99. package/src/components/menus/QualityScoreDoc.js +36 -0
  100. package/src/components/menus/ReportForm.js +133 -0
  101. package/src/components/menus/Share.js +228 -0
  102. package/src/components/menus/index.js +15 -0
  103. package/src/components/styles.js +365 -0
  104. package/src/components/ui/Button.js +75 -0
  105. package/src/components/ui/ButtonGroup.css +49 -0
  106. package/src/components/ui/ButtonGroup.js +68 -0
  107. package/src/components/ui/CopyButton.js +71 -0
  108. package/src/components/ui/Grade.js +54 -0
  109. package/src/components/ui/LinkButton.js +68 -0
  110. package/src/components/ui/Loader.js +188 -0
  111. package/src/components/{Map.css → ui/Map.css} +5 -17
  112. package/src/components/{Map.js → ui/Map.js} +114 -138
  113. package/src/components/ui/MapMore.js +324 -0
  114. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  115. package/src/components/{Photo.js → ui/Photo.js} +279 -90
  116. package/src/components/ui/Popup.js +145 -0
  117. package/src/components/ui/QualityScore.js +152 -0
  118. package/src/components/ui/SearchBar.js +363 -0
  119. package/src/components/ui/TogglableGroup.js +162 -0
  120. package/src/components/ui/index.js +20 -0
  121. package/src/components/ui/widgets/GeoSearch.css +21 -0
  122. package/src/components/ui/widgets/GeoSearch.js +139 -0
  123. package/src/components/ui/widgets/Legend.js +51 -0
  124. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  125. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  126. package/src/components/ui/widgets/Player.css +7 -0
  127. package/src/components/ui/widgets/Player.js +148 -0
  128. package/src/components/ui/widgets/Share.js +30 -0
  129. package/src/components/ui/widgets/Zoom.js +82 -0
  130. package/src/components/ui/widgets/index.js +12 -0
  131. package/src/img/panoramax.svg +13 -0
  132. package/src/img/switch_big.svg +20 -10
  133. package/src/index.js +6 -9
  134. package/src/translations/da.json +1 -1
  135. package/src/translations/de.json +1 -1
  136. package/src/translations/en.json +5 -3
  137. package/src/translations/eo.json +1 -1
  138. package/src/translations/es.json +1 -1
  139. package/src/translations/fr.json +5 -3
  140. package/src/translations/hu.json +1 -1
  141. package/src/translations/it.json +1 -1
  142. package/src/translations/ja.json +1 -1
  143. package/src/translations/nl.json +1 -1
  144. package/src/translations/pl.json +1 -1
  145. package/src/translations/sv.json +33 -3
  146. package/src/translations/zh_Hant.json +1 -1
  147. package/src/utils/API.js +74 -42
  148. package/src/utils/InitParameters.js +354 -0
  149. package/src/utils/URLHandler.js +364 -0
  150. package/src/utils/geocoder.js +116 -0
  151. package/src/utils/{I18n.js → i18n.js} +3 -1
  152. package/src/utils/index.js +11 -0
  153. package/src/utils/{Map.js → map.js} +216 -80
  154. package/src/utils/picture.js +433 -0
  155. package/src/utils/utils.js +315 -0
  156. package/src/utils/widgets.js +93 -0
  157. package/tests/components/ui/CopyButton.test.js +52 -0
  158. package/tests/components/ui/Loader.test.js +54 -0
  159. package/tests/components/{Map.test.js → ui/Map.test.js} +19 -61
  160. package/tests/components/{Photo.test.js → ui/Photo.test.js} +89 -57
  161. package/tests/components/ui/Popup.test.js +24 -0
  162. package/tests/components/ui/QualityScore.test.js +17 -0
  163. package/tests/components/ui/SearchBar.test.js +107 -0
  164. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +34 -0
  165. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  166. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  167. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +57 -4
  168. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  169. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  170. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  171. package/tests/utils/API.test.js +1 -14
  172. package/tests/utils/InitParameters.test.js +485 -0
  173. package/tests/utils/URLHandler.test.js +350 -0
  174. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  175. package/tests/utils/__snapshots__/picture.test.js.snap +315 -0
  176. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  177. package/tests/utils/geocoder.test.js +37 -0
  178. package/tests/utils/{I18n.test.js → i18n.test.js} +1 -1
  179. package/tests/utils/map.test.js +67 -0
  180. package/tests/utils/picture.test.js +745 -0
  181. package/tests/utils/utils.test.js +288 -0
  182. package/tests/utils/widgets.test.js +90 -0
  183. package/docs/01_Start.md +0 -149
  184. package/docs/02_Usage.md +0 -831
  185. package/docs/04_Advanced_examples.md +0 -216
  186. package/src/Editor.css +0 -37
  187. package/src/Editor.js +0 -361
  188. package/src/StandaloneMap.js +0 -114
  189. package/src/Viewer.css +0 -203
  190. package/src/Viewer.js +0 -1246
  191. package/src/components/CoreView.css +0 -70
  192. package/src/components/CoreView.js +0 -175
  193. package/src/components/Loader.css +0 -74
  194. package/src/components/Loader.js +0 -120
  195. package/src/utils/Exif.js +0 -193
  196. package/src/utils/Utils.js +0 -631
  197. package/src/utils/Widgets.js +0 -562
  198. package/src/viewer/URLHash.js +0 -469
  199. package/src/viewer/Widgets.css +0 -880
  200. package/src/viewer/Widgets.js +0 -1470
  201. package/tests/Editor.test.js +0 -126
  202. package/tests/StandaloneMap.test.js +0 -45
  203. package/tests/Viewer.test.js +0 -366
  204. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  205. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  206. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  207. package/tests/components/CoreView.test.js +0 -92
  208. package/tests/components/Loader.test.js +0 -38
  209. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  210. package/tests/utils/Exif.test.js +0 -124
  211. package/tests/utils/Map.test.js +0 -113
  212. package/tests/utils/Utils.test.js +0 -300
  213. package/tests/utils/Widgets.test.js +0 -107
  214. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  215. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  216. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  217. package/tests/viewer/URLHash.test.js +0 -559
  218. package/tests/viewer/Widgets.test.js +0 -127
  219. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  220. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
  221. /package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +0 -0
@@ -0,0 +1,350 @@
1
+ import URLHandler from "../../src/utils/URLHandler";
2
+
3
+ describe("listenToChanges", () => {
4
+ it("should add event listeners to window, parent, psv, and map", () => {
5
+ window.addEventListener = jest.fn();
6
+ const parent = {
7
+ addEventListener: jest.fn(),
8
+ psv: { addEventListener: jest.fn() },
9
+ map: { on: jest.fn() },
10
+ };
11
+ const urlHandler = new URLHandler(parent);
12
+ urlHandler.listenToChanges();
13
+ expect(window.addEventListener).toHaveBeenCalledWith("popstate", expect.any(Function), false);
14
+ ["focus-changed", "pictures-navigation-changed"].forEach(event => {
15
+ expect(parent.addEventListener).toHaveBeenCalledWith(event, expect.any(Function));
16
+ });
17
+ ["position-updated", "zoom-updated", "view-rotated", "picture-loaded", "transition-duration-changed"].forEach(event => {
18
+ expect(parent.psv.addEventListener).toHaveBeenCalledWith(event, expect.any(Function));
19
+ });
20
+ ["moveend", "zoomend", "boxzoomend", "background-changed", "users-changed", "filters-changed"].forEach(event => {
21
+ expect(parent.map.on).toHaveBeenCalledWith(event, expect.any(Function));
22
+ });
23
+ });
24
+ });
25
+
26
+ describe("nextURLString", () => {
27
+ it("works without any specific values set", () => {
28
+ const v = {
29
+ addEventListener: jest.fn(),
30
+ psv: {
31
+ getPicturesNavigation: () => null,
32
+ getTransitionDuration: () => null,
33
+ getPictureMetadata: () => null,
34
+ },
35
+ };
36
+ const uh = new URLHandler(v);
37
+ expect(uh.nextURLString()).toBe("?map=none");
38
+ });
39
+
40
+ it("works with picture metadata", () => {
41
+ const v = {
42
+ addEventListener: jest.fn(),
43
+ psv: {
44
+ getPicturesNavigation: () => null,
45
+ getTransitionDuration: () => null,
46
+ getPictureMetadata: () => ({ "id": "cbfc3add-8173-4464-98c8-de2a43c6a50f" })
47
+ },
48
+ };
49
+ const uh = new URLHandler(v);
50
+ uh.currentPSVString = () => "0/1/2";
51
+ expect(uh.nextURLString()).toBe("?map=none&pic=cbfc3add-8173-4464-98c8-de2a43c6a50f&xyz=0/1/2");
52
+ });
53
+
54
+ it("works with map started + wide", () => {
55
+ const v = {
56
+ addEventListener: jest.fn(),
57
+ psv: {
58
+ getPicturesNavigation: () => null,
59
+ getTransitionDuration: () => null,
60
+ getPictureMetadata: () => null,
61
+ },
62
+ map: {
63
+ getVisibleUsers: () => ["geovisio"],
64
+ hasTwoBackgrounds: () => false,
65
+ loaded: () => true,
66
+ },
67
+ isMapWide: () => true,
68
+ popup: { hasAttribute: () => false },
69
+ };
70
+ const uh = new URLHandler(v);
71
+ uh.currentMapString = () => "18/0.5/-12";
72
+ expect(uh.nextURLString()).toBe("?focus=map&map=18/0.5/-12");
73
+ });
74
+
75
+ it("works with map + picture wide", () => {
76
+ const v = {
77
+ addEventListener: jest.fn(),
78
+ psv: {
79
+ getPicturesNavigation: () => null,
80
+ getTransitionDuration: () => null,
81
+ getPictureMetadata: () => ({ "id": "cbfc3add-8173-4464-98c8-de2a43c6a50f" }),
82
+ },
83
+ map: {
84
+ getVisibleUsers: () => ["geovisio"],
85
+ hasTwoBackgrounds: () => false,
86
+ loaded: () => true,
87
+ },
88
+ isMapWide: () => false,
89
+ popup: { hasAttribute: () => false },
90
+ };
91
+ const uh = new URLHandler(v);
92
+ uh.currentPSVString = () => "0/1/2";
93
+ uh.currentMapString = () => "18/0.5/-12";
94
+ expect(uh.nextURLString()).toBe("?focus=pic&map=18/0.5/-12&pic=cbfc3add-8173-4464-98c8-de2a43c6a50f&xyz=0/1/2");
95
+ });
96
+
97
+ it("works with map filters", () => {
98
+ const v = {
99
+ addEventListener: jest.fn(),
100
+ psv: {
101
+ getPicturesNavigation: () => null,
102
+ getTransitionDuration: () => null,
103
+ getPictureMetadata: () => null,
104
+ },
105
+ map: {
106
+ getVisibleUsers: () => ["geovisio"],
107
+ hasTwoBackgrounds: () => false,
108
+ loaded: () => true,
109
+ _mapFilters: {
110
+ "minDate": "2023-01-01",
111
+ "maxDate": "2023-08-08",
112
+ "camera": "sony",
113
+ "pic_type": "flat",
114
+ "theme": "age",
115
+ },
116
+ },
117
+ isMapWide: () => false,
118
+ popup: { hasAttribute: () => false },
119
+ };
120
+ const uh = new URLHandler(v);
121
+ uh.currentMapString = () => "18/0.5/-12";
122
+ expect(uh.nextURLString()).toBe("?camera=sony&date_from=2023-01-01&date_to=2023-08-08&focus=pic&map=18/0.5/-12&pic_type=flat&theme=age");
123
+ });
124
+
125
+ it("works with speed", () => {
126
+ const v = {
127
+ addEventListener: jest.fn(),
128
+ psv: {
129
+ getPicturesNavigation: () => null,
130
+ getTransitionDuration: () => 250,
131
+ getPictureMetadata: () => null,
132
+ },
133
+ };
134
+ const uh = new URLHandler(v);
135
+ expect(uh.nextURLString()).toBe("?map=none&speed=250");
136
+ });
137
+
138
+ it("works with popup", () => {
139
+ const v = {
140
+ addEventListener: jest.fn(),
141
+ psv: {
142
+ getPicturesNavigation: () => null,
143
+ getTransitionDuration: () => null,
144
+ getPictureMetadata: () => null,
145
+ },
146
+ map: {
147
+ getVisibleUsers: () => ["geovisio"],
148
+ hasTwoBackgrounds: () => false,
149
+ loaded: () => true,
150
+ },
151
+ isMapWide: () => false,
152
+ popup: { hasAttribute: () => true },
153
+ };
154
+ const uh = new URLHandler(v);
155
+ uh.currentMapString = () => "18/0.5/-12";
156
+ expect(uh.nextURLString()).toBe("?focus=meta&map=18/0.5/-12");
157
+ });
158
+
159
+ it("works with nav", () => {
160
+ const v = {
161
+ addEventListener: jest.fn(),
162
+ psv: {
163
+ getPicturesNavigation: () => "pic",
164
+ getTransitionDuration: () => null,
165
+ getPictureMetadata: () => null,
166
+ },
167
+ };
168
+ const uh = new URLHandler(v);
169
+ expect(uh.nextURLString()).toBe("?map=none&nav=pic");
170
+ });
171
+ });
172
+
173
+ describe("currentURLParams", () => {
174
+ it("works if empty", () => {
175
+ delete window.location;
176
+ window.location = { search: "" };
177
+ const v = { addEventListener: jest.fn() };
178
+ const uh = new URLHandler(v);
179
+ expect(uh.currentURLParams()).toStrictEqual({});
180
+ });
181
+
182
+ it("works with single param", () => {
183
+ delete window.location;
184
+ window.location = { search: "?a=b" };
185
+ const v = { addEventListener: jest.fn() };
186
+ const uh = new URLHandler(v);
187
+ expect(uh.currentURLParams()).toStrictEqual({"a": "b"});
188
+ });
189
+
190
+ it("works with multiple params", () => {
191
+ delete window.location;
192
+ window.location = { search: "?a=b&c=d" };
193
+ const v = { addEventListener: jest.fn() };
194
+ const uh = new URLHandler(v);
195
+ expect(uh.currentURLParams()).toStrictEqual({"a": "b", "c": "d"});
196
+ });
197
+ });
198
+
199
+ describe("currentMapString", () => {
200
+ it("works with zoom+center", () => {
201
+ const v = {
202
+ addEventListener: jest.fn(),
203
+ map: {
204
+ getZoom: () => 18,
205
+ getCenter: () => ({ lng: -12.5, lat: 48.75 }),
206
+ getBearing: () => null,
207
+ getPitch: () => null,
208
+ }
209
+ };
210
+ const uh = new URLHandler(v);
211
+ expect(uh.currentMapString()).toBe("18/48.75/-12.5");
212
+ });
213
+
214
+ it("works with zoom+center+bearing", () => {
215
+ const v = {
216
+ addEventListener: jest.fn(),
217
+ map: {
218
+ getZoom: () => 18,
219
+ getCenter: () => ({ lng: -12.5, lat: 48.75 }),
220
+ getBearing: () => 12,
221
+ getPitch: () => null,
222
+ }
223
+ };
224
+ const uh = new URLHandler(v);
225
+ expect(uh.currentMapString()).toBe("18/48.75/-12.5/12");
226
+ });
227
+
228
+ it("works with zoom+center+pitch", () => {
229
+ const v = {
230
+ addEventListener: jest.fn(),
231
+ map: {
232
+ getZoom: () => 18,
233
+ getCenter: () => ({ lng: -12.5, lat: 48.75 }),
234
+ getBearing: () => null,
235
+ getPitch: () => 65,
236
+ },
237
+ };
238
+ const uh = new URLHandler(v);
239
+ expect(uh.currentMapString()).toBe("18/48.75/-12.5/0/65");
240
+ });
241
+
242
+ it("works with zoom+center+bearing+pitch", () => {
243
+ const v = {
244
+ addEventListener: jest.fn(),
245
+ map: {
246
+ getZoom: () => 18,
247
+ getCenter: () => ({ lng: -12.5, lat: 48.75 }),
248
+ getBearing: () => 42,
249
+ getPitch: () => 65,
250
+ },
251
+ };
252
+ const uh = new URLHandler(v);
253
+ expect(uh.currentMapString()).toBe("18/48.75/-12.5/42/65");
254
+ });
255
+ });
256
+
257
+ describe("currentPSVString", () => {
258
+ it("works", () => {
259
+ const v = {
260
+ addEventListener: jest.fn(),
261
+ psv: {
262
+ getXYZ: () => ({ x: 12, y: 50, z: 75 }),
263
+ },
264
+ };
265
+ const uh = new URLHandler(v);
266
+ expect(uh.currentPSVString()).toBe("12.00/50.00/75");
267
+ });
268
+
269
+ it("rounds to 2 decimals", () => {
270
+ const v = {
271
+ addEventListener: jest.fn(),
272
+ psv: {
273
+ getXYZ: () => ({ x: 12.123456, y: 50.789456, z: 75 }),
274
+ },
275
+ };
276
+ const uh = new URLHandler(v);
277
+ expect(uh.currentPSVString()).toBe("12.12/50.79/75");
278
+ });
279
+
280
+ it("works without z", () => {
281
+ const v = {
282
+ addEventListener: jest.fn(),
283
+ psv: {
284
+ getXYZ: () => ({ x: 12, y: 50 }),
285
+ },
286
+ };
287
+ const uh = new URLHandler(v);
288
+ expect(uh.currentPSVString()).toBe("12.00/50.00/0");
289
+ });
290
+ });
291
+
292
+ describe("_onParentChange", () => {
293
+ it("works", async () => {
294
+ delete window.history;
295
+ delete window.location;
296
+
297
+ window.history = { replaceState: jest.fn(), state: {} };
298
+ window.location = { href: "http://localhost:5000/?nav=pic&speed=2", search: "?nav=pic&speed=2" };
299
+
300
+ const v = { addEventListener: jest.fn() };
301
+ const uh = new URLHandler(v);
302
+ uh.nextURLString = () => "?map=1/2/3";
303
+ uh.dispatchEvent = jest.fn();
304
+
305
+ uh._onParentChange();
306
+ await new Promise((r) => setTimeout(r, 1000));
307
+
308
+ expect(window.history.replaceState.mock.calls.pop()).toEqual([{}, null, "http://localhost:5000/?map=1/2/3"]);
309
+ expect(uh.dispatchEvent.mock.calls).toMatchSnapshot();
310
+ });
311
+
312
+ it("works with pic change", async () => {
313
+ delete window.history;
314
+ delete window.location;
315
+
316
+ window.history = { pushState: jest.fn(), state: {} };
317
+ window.location = { href: "http://localhost:5000/?pic=bla", search: "?pic=bla" };
318
+
319
+ const v = { addEventListener: jest.fn() };
320
+ const uh = new URLHandler(v);
321
+ uh.nextURLString = () => "?nav=seq";
322
+ uh.dispatchEvent = jest.fn();
323
+
324
+ uh._onParentChange();
325
+ await new Promise((r) => setTimeout(r, 1000));
326
+
327
+ expect(window.history.pushState.mock.calls.pop()).toEqual([{}, null, "http://localhost:5000/?nav=seq"]);
328
+ expect(uh.dispatchEvent.mock.calls).toMatchSnapshot();
329
+ });
330
+
331
+ it("deduplicates calls", async () => {
332
+ delete window.history;
333
+ delete window.location;
334
+
335
+ window.history = { replaceState: jest.fn(), state: {} };
336
+ window.location = { href: "http://localhost:5000/?speed=1&nav=seq", search: "?speed=1&nav=seq" };
337
+
338
+ const v = { addEventListener: jest.fn() };
339
+ const uh = new URLHandler(v);
340
+ uh.nextURLString = () => "?map=1/2/3";
341
+
342
+ for(let i=0; i <= 10; i++) {
343
+ uh._onParentChange();
344
+ }
345
+
346
+ await new Promise((r) => setTimeout(r, 1000));
347
+
348
+ expect(window.history.replaceState.mock.calls).toEqual([[{}, null, "http://localhost:5000/?map=1/2/3"]]);
349
+ });
350
+ });
@@ -0,0 +1,21 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`_onParentChange works 1`] = `
4
+ Array [
5
+ Array [
6
+ CustomEvent {
7
+ "isTrusted": false,
8
+ },
9
+ ],
10
+ ]
11
+ `;
12
+
13
+ exports[`_onParentChange works with pic change 1`] = `
14
+ Array [
15
+ Array [
16
+ CustomEvent {
17
+ "isTrusted": false,
18
+ },
19
+ ],
20
+ ]
21
+ `;
@@ -0,0 +1,315 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`apiFeatureToPSVNode works 1`] = `
4
+ Object {
5
+ "caption": Object {
6
+ "date": mockConstructor {},
7
+ "license": "<a href=\\"https://spdx.org/licenses/CC-BY-SA-4.0.html\\" title=\\"\\" target=\\"_blank\\">CC-BY-SA-4.0</a>",
8
+ "producer": "Hopen111",
9
+ },
10
+ "gps": Array [
11
+ -92.70188245,
12
+ 41.322064692,
13
+ ],
14
+ "horizontalFov": 360,
15
+ "id": "00000000-76a0-4bec-b19e-a56f51ef997d",
16
+ "links": Array [
17
+ Object {
18
+ "arrowStyle": Object {
19
+ "element": <img
20
+ alt=""
21
+ src="arrow_triangle.svg"
22
+ />,
23
+ "size": Object {
24
+ "height": 75,
25
+ "width": 75,
26
+ },
27
+ },
28
+ "gps": Array [
29
+ -92.701854443,
30
+ 41.322047796,
31
+ ],
32
+ "linkOffset": Object {
33
+ "yaw": -5.3930673886624785,
34
+ },
35
+ "nodeId": "66ea29cd-941c-4201-977f-efb87bd5465e",
36
+ },
37
+ Object {
38
+ "arrowStyle": Object {
39
+ "element": <img
40
+ alt=""
41
+ src="arrow_triangle.svg"
42
+ />,
43
+ "size": Object {
44
+ "height": 75,
45
+ "width": 75,
46
+ },
47
+ },
48
+ "gps": Array [
49
+ -92.701910458,
50
+ 41.322081588,
51
+ ],
52
+ "linkOffset": Object {
53
+ "yaw": -5.3930673886624785,
54
+ },
55
+ "nodeId": "5fb8e767-6fe3-4bcb-b19f-7031d9a64fc8",
56
+ },
57
+ ],
58
+ "panorama": Object {
59
+ "basePanoData": [Function],
60
+ "baseUrl": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/sd.jpg",
61
+ "cols": 8,
62
+ "hdUrl": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/hd.jpg",
63
+ "origBaseUrl": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/sd.jpg",
64
+ "rows": 4,
65
+ "thumbUrl": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/thumb.jpg",
66
+ "tileUrl": [Function],
67
+ "width": 5376,
68
+ },
69
+ "properties": Object {
70
+ "created": "2024-09-04T02:40:11.836165+00:00",
71
+ "datetime": "2024-09-01T23:35:37.797105+00:00",
72
+ "datetimetz": "2024-09-01T23:35:37.797105+00:00",
73
+ "exif": Object {
74
+ "Xmp.GPano.CroppedAreaImageHeightPixels": "2688",
75
+ "Xmp.GPano.CroppedAreaImageWidthPixels": "5376",
76
+ "Xmp.GPano.CroppedAreaLeftPixels": "0",
77
+ "Xmp.GPano.CroppedAreaTopPixels": "0",
78
+ "Xmp.GPano.FullPanoHeightPixels": "2688",
79
+ "Xmp.GPano.FullPanoWidthPixels": "5376",
80
+ "Xmp.GPano.ProjectionType": "equirectangular",
81
+ "Xmp.GPano.UsePanoramaViewer": "True",
82
+ },
83
+ "geovisio:image": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/hd.jpg",
84
+ "geovisio:producer": "Hopen111",
85
+ "geovisio:thumbnail": "https://panoramax.openstreetmap.fr/api/pictures/00000000-76a0-4bec-b19e-a56f51ef997d/thumb.jpg",
86
+ "license": "CC-BY-SA-4.0",
87
+ "original_file:name": "GS010837-003545.jpg",
88
+ "original_file:size": 788436,
89
+ "panoramax:horizontal_pixel_density": 15,
90
+ "pers:interior_orientation": Object {
91
+ "field_of_view": 360,
92
+ "sensor_array_dimensions": Array [
93
+ 5376,
94
+ 2688,
95
+ ],
96
+ },
97
+ "tiles:tile_matrix_sets": Object {
98
+ "geovisio": Object {
99
+ "identifier": "geovisio-00000000-76a0-4bec-b19e-a56f51ef997d",
100
+ "tileMatrix": Array [
101
+ Object {
102
+ "identifier": "0",
103
+ "matrixHeight": 4,
104
+ "matrixWidth": 8,
105
+ "scaleDenominator": 1,
106
+ "tileHeight": 672,
107
+ "tileWidth": 672,
108
+ "topLeftCorner": Array [
109
+ 0,
110
+ 0,
111
+ ],
112
+ "type": "TileMatrixType",
113
+ },
114
+ ],
115
+ "title": "GeoVisio tile matrix for picture 00000000-76a0-4bec-b19e-a56f51ef997d",
116
+ "type": "TileMatrixSetType",
117
+ },
118
+ },
119
+ "view:azimuth": 309,
120
+ },
121
+ "sequence": Object {
122
+ "id": "ec31c324-b43a-425e-a24c-3de56d7914c1",
123
+ "nextPic": "5fb8e767-6fe3-4bcb-b19f-7031d9a64fc8",
124
+ "prevPic": "66ea29cd-941c-4201-977f-efb87bd5465e",
125
+ },
126
+ "sphereCorrection": Object {},
127
+ }
128
+ `;
129
+
130
+ exports[`filterRelatedPicsLinks works 1`] = `
131
+ Array [
132
+ Object {
133
+ "arrowStyle": Object {
134
+ "element": <img
135
+ alt=""
136
+ src="arrow_turn.svg"
137
+ />,
138
+ "size": Object {
139
+ "height": 128,
140
+ "width": 42.666666666666664,
141
+ },
142
+ },
143
+ "gps": Array [
144
+ 4.840134667,
145
+ 45.756240466,
146
+ ],
147
+ "linkOffset": Object {
148
+ "yaw": -1.8849555921538759,
149
+ },
150
+ "nodeId": "aaa1ae2f-b48a-4291-972e-030fcd44760b",
151
+ },
152
+ Object {
153
+ "arrowStyle": Object {
154
+ "element": <img
155
+ alt=""
156
+ src="arrow_triangle.svg"
157
+ />,
158
+ "size": Object {
159
+ "height": 75,
160
+ "width": 75,
161
+ },
162
+ },
163
+ "gps": Array [
164
+ 4.8401792,
165
+ 45.7562024,
166
+ ],
167
+ "linkOffset": Object {
168
+ "yaw": -1.8849555921538759,
169
+ },
170
+ "nodeId": "38abdc16-b878-4762-a433-33e52e62ae9b",
171
+ },
172
+ Object {
173
+ "arrowStyle": Object {
174
+ "element": <img
175
+ alt=""
176
+ src="arrow_turn.svg"
177
+ />,
178
+ "size": Object {
179
+ "height": 128,
180
+ "width": 42.666666666666664,
181
+ },
182
+ },
183
+ "gps": Array [
184
+ 4.8401379,
185
+ 45.7561616,
186
+ ],
187
+ "linkOffset": Object {
188
+ "yaw": -1.8849555921538759,
189
+ },
190
+ "nodeId": "5e1d8461-fe5d-4d57-9c87-f2403baff37d",
191
+ },
192
+ Object {
193
+ "arrowStyle": Object {
194
+ "element": <img
195
+ alt=""
196
+ src="arrow_turn.svg"
197
+ />,
198
+ "size": Object {
199
+ "height": 128,
200
+ "width": 42.666666666666664,
201
+ },
202
+ },
203
+ "gps": Array [
204
+ 4.8400918,
205
+ 45.7561938,
206
+ ],
207
+ "linkOffset": Object {
208
+ "yaw": -1.8849555921538759,
209
+ },
210
+ "nodeId": "abff42de-2862-4b15-8c2a-dca22ed2deaf",
211
+ },
212
+ Object {
213
+ "arrowStyle": Object {
214
+ "element": <img
215
+ alt=""
216
+ src="arrow_triangle.svg"
217
+ />,
218
+ "size": Object {
219
+ "height": 75,
220
+ "width": 75,
221
+ },
222
+ },
223
+ "gps": Array [
224
+ 4.8400633,
225
+ 45.7562389,
226
+ ],
227
+ "linkOffset": Object {
228
+ "yaw": -1.8849555921538759,
229
+ },
230
+ "nodeId": "1c5025ed-3e03-4cf0-8879-7ed9091a9e33",
231
+ },
232
+ ]
233
+ `;
234
+
235
+ exports[`getCroppedPanoData works with API props 1`] = `
236
+ Object {
237
+ "croppedHeight": 2606,
238
+ "croppedWidth": 15872,
239
+ "croppedX": 0,
240
+ "croppedY": 2538,
241
+ "fullHeight": 7936,
242
+ "fullWidth": 15872,
243
+ }
244
+ `;
245
+
246
+ exports[`getCroppedPanoData works with API props and unneeded 1`] = `Object {}`;
247
+
248
+ exports[`getCroppedPanoData works with exif tags 1`] = `
249
+ Object {
250
+ "croppedHeight": 2606,
251
+ "croppedWidth": 15872,
252
+ "croppedX": 0,
253
+ "croppedY": 2538,
254
+ "fullHeight": 7936,
255
+ "fullWidth": 15872,
256
+ }
257
+ `;
258
+
259
+ exports[`getCroppedPanoData works with exif tags and unneeded 1`] = `Object {}`;
260
+
261
+ exports[`getNodeCaption works with date + 2 producers 1`] = `
262
+ Object {
263
+ "date": Object {
264
+ "toLocaleDateString": [Function],
265
+ },
266
+ "producer": "GeoVisio Corp., PanierAvide",
267
+ }
268
+ `;
269
+
270
+ exports[`getNodeCaption works with date + producer 1`] = `
271
+ Object {
272
+ "date": Object {
273
+ "toLocaleDateString": [Function],
274
+ },
275
+ "producer": "PanierAvide",
276
+ }
277
+ `;
278
+
279
+ exports[`getNodeCaption works with date 1`] = `
280
+ Object {
281
+ "date": Object {
282
+ "toLocaleDateString": [Function],
283
+ },
284
+ }
285
+ `;
286
+
287
+ exports[`getNodeCaption works with date+tz 1`] = `
288
+ Object {
289
+ "date": Object {
290
+ "toLocaleDateString": [Function],
291
+ },
292
+ }
293
+ `;
294
+
295
+ exports[`getNodeCaption works with producer 1`] = `
296
+ Object {
297
+ "producer": "PanierAvide",
298
+ }
299
+ `;
300
+
301
+ exports[`getSphereCorrection works with API props 1`] = `
302
+ Object {
303
+ "pan": 0.7330382858376184,
304
+ "roll": 1.260127719939906,
305
+ "tilt": -0.5235987755982988,
306
+ }
307
+ `;
308
+
309
+ exports[`getSphereCorrection works with exif tags 1`] = `
310
+ Object {
311
+ "pan": 0.7330382858376184,
312
+ "roll": 1.260127719939906,
313
+ "tilt": -0.5235987755982988,
314
+ }
315
+ `;
@@ -0,0 +1,19 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`fa works 1`] = `
4
+ <svg
5
+ aria-hidden="true"
6
+ class="svg-inline--fa fa-chevron-down"
7
+ data-icon="chevron-down"
8
+ data-prefix="fas"
9
+ focusable="false"
10
+ role="img"
11
+ viewBox="0 0 512 512"
12
+ xmlns="http://www.w3.org/2000/svg"
13
+ >
14
+ <path
15
+ d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"
16
+ fill="currentColor"
17
+ />
18
+ </svg>
19
+ `;