@panoramax/web-viewer 3.2.3 → 4.0.0-develop-39167b4d

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 (255) hide show
  1. package/.gitlab-ci.yml +13 -6
  2. package/CHANGELOG.md +53 -1
  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 +12 -12
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +2126 -14
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/photo.html +1 -0
  13. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff +0 -0
  14. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff2 +0 -0
  15. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff +0 -0
  16. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff2 +0 -0
  17. package/build/viewer.html +12 -1
  18. package/build/widgets.html +1 -0
  19. package/config/jest/mocks.js +201 -0
  20. package/config/paths.js +2 -0
  21. package/config/webpack.config.js +52 -0
  22. package/docs/03_URL_settings.md +14 -16
  23. package/docs/05_Compatibility.md +59 -76
  24. package/docs/09_Develop.md +46 -11
  25. package/docs/90_Releases.md +2 -2
  26. package/docs/images/class_diagram.drawio +60 -45
  27. package/docs/images/class_diagram.jpg +0 -0
  28. package/docs/images/screenshot.jpg +0 -0
  29. package/docs/index.md +135 -0
  30. package/docs/reference/components/core/Basic.md +196 -0
  31. package/docs/reference/components/core/CoverageMap.md +210 -0
  32. package/docs/reference/components/core/Editor.md +224 -0
  33. package/docs/reference/components/core/PhotoViewer.md +307 -0
  34. package/docs/reference/components/core/Viewer.md +350 -0
  35. package/docs/reference/components/layout/BottomDrawer.md +35 -0
  36. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  37. package/docs/reference/components/layout/Mini.md +45 -0
  38. package/docs/reference/components/layout/Tabs.md +45 -0
  39. package/docs/reference/components/menus/MapBackground.md +32 -0
  40. package/docs/reference/components/menus/MapFilters.md +15 -0
  41. package/docs/reference/components/menus/MapLayers.md +15 -0
  42. package/docs/reference/components/menus/MapLegend.md +15 -0
  43. package/docs/reference/components/menus/PictureLegend.md +16 -0
  44. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  45. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  46. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  47. package/docs/reference/components/menus/ReportForm.md +15 -0
  48. package/docs/reference/components/menus/ShareMenu.md +15 -0
  49. package/docs/reference/components/ui/Button.md +40 -0
  50. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  51. package/docs/reference/components/ui/CopyButton.md +38 -0
  52. package/docs/reference/components/ui/Grade.md +32 -0
  53. package/docs/reference/components/ui/LinkButton.md +45 -0
  54. package/docs/reference/components/ui/ListGroup.md +22 -0
  55. package/docs/reference/components/ui/Loader.md +56 -0
  56. package/docs/reference/components/ui/Map.md +239 -0
  57. package/docs/reference/components/ui/MapMore.md +256 -0
  58. package/docs/reference/components/ui/Photo.md +385 -0
  59. package/docs/reference/components/ui/Popup.md +56 -0
  60. package/docs/reference/components/ui/ProgressBar.md +32 -0
  61. package/docs/reference/components/ui/QualityScore.md +45 -0
  62. package/docs/reference/components/ui/SearchBar.md +63 -0
  63. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  64. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  65. package/docs/reference/components/ui/widgets/Legend.md +49 -0
  66. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  67. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  68. package/docs/reference/components/ui/widgets/OSMEditors.md +15 -0
  69. package/docs/reference/components/ui/widgets/PictureLegendActions.md +32 -0
  70. package/docs/reference/components/ui/widgets/Player.md +33 -0
  71. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  72. package/docs/reference/utils/API.md +334 -0
  73. package/docs/reference/utils/InitParameters.md +68 -0
  74. package/docs/reference/utils/URLHandler.md +107 -0
  75. package/docs/reference.md +79 -0
  76. package/docs/shortcuts.md +11 -0
  77. package/docs/tutorials/aerial_imagery.md +19 -0
  78. package/docs/tutorials/authentication.md +10 -0
  79. package/docs/tutorials/custom_widgets.md +59 -0
  80. package/docs/tutorials/map_style.md +39 -0
  81. package/docs/tutorials/migrate_v4.md +153 -0
  82. package/docs/tutorials/synced_coverage.md +43 -0
  83. package/mkdocs.yml +66 -5
  84. package/package.json +22 -17
  85. package/public/editor.html +21 -29
  86. package/public/index.html +17 -12
  87. package/public/map.html +19 -18
  88. package/public/photo.html +55 -0
  89. package/public/viewer.html +22 -26
  90. package/public/widgets.html +306 -0
  91. package/scripts/doc.js +79 -0
  92. package/src/components/core/Basic.css +48 -0
  93. package/src/components/core/Basic.js +349 -0
  94. package/src/components/core/CoverageMap.css +9 -0
  95. package/src/components/core/CoverageMap.js +139 -0
  96. package/src/components/core/Editor.css +23 -0
  97. package/src/components/core/Editor.js +390 -0
  98. package/src/components/core/PhotoViewer.css +48 -0
  99. package/src/components/core/PhotoViewer.js +499 -0
  100. package/src/components/core/Viewer.css +98 -0
  101. package/src/components/core/Viewer.js +564 -0
  102. package/src/components/core/index.js +12 -0
  103. package/src/components/index.js +13 -0
  104. package/src/components/layout/BottomDrawer.js +257 -0
  105. package/src/components/layout/CorneredGrid.js +112 -0
  106. package/src/components/layout/Mini.js +117 -0
  107. package/src/components/layout/Tabs.js +133 -0
  108. package/src/components/layout/index.js +9 -0
  109. package/src/components/menus/MapBackground.js +106 -0
  110. package/src/components/menus/MapFilters.js +400 -0
  111. package/src/components/menus/MapLayers.js +143 -0
  112. package/src/components/menus/MapLegend.js +34 -0
  113. package/src/components/menus/PictureLegend.js +257 -0
  114. package/src/components/menus/PictureMetadata.js +317 -0
  115. package/src/components/menus/PlayerOptions.js +95 -0
  116. package/src/components/menus/QualityScoreDoc.js +36 -0
  117. package/src/components/menus/ReportForm.js +133 -0
  118. package/src/components/menus/Share.js +100 -0
  119. package/src/components/menus/index.js +15 -0
  120. package/src/components/styles.js +383 -0
  121. package/src/components/ui/Button.js +77 -0
  122. package/src/components/ui/ButtonGroup.css +57 -0
  123. package/src/components/ui/ButtonGroup.js +68 -0
  124. package/src/components/ui/CopyButton.js +106 -0
  125. package/src/components/ui/Grade.js +54 -0
  126. package/src/components/ui/LinkButton.js +67 -0
  127. package/src/components/ui/ListGroup.js +66 -0
  128. package/src/components/ui/Loader.js +203 -0
  129. package/src/components/{Map.css → ui/Map.css} +5 -17
  130. package/src/components/{Map.js → ui/Map.js} +148 -156
  131. package/src/components/ui/MapMore.js +324 -0
  132. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  133. package/src/components/{Photo.js → ui/Photo.js} +313 -101
  134. package/src/components/ui/Popup.js +145 -0
  135. package/src/components/ui/ProgressBar.js +104 -0
  136. package/src/components/ui/QualityScore.js +147 -0
  137. package/src/components/ui/SearchBar.js +367 -0
  138. package/src/components/ui/TogglableGroup.js +157 -0
  139. package/src/components/ui/index.js +22 -0
  140. package/src/components/ui/widgets/GeoSearch.css +21 -0
  141. package/src/components/ui/widgets/GeoSearch.js +139 -0
  142. package/src/components/ui/widgets/Legend.js +113 -0
  143. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  144. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  145. package/src/components/ui/widgets/OSMEditors.js +155 -0
  146. package/src/components/ui/widgets/PictureLegendActions.js +117 -0
  147. package/src/components/ui/widgets/Player.css +7 -0
  148. package/src/components/ui/widgets/Player.js +151 -0
  149. package/src/components/ui/widgets/Zoom.js +82 -0
  150. package/src/components/ui/widgets/index.js +13 -0
  151. package/src/img/loader_base.jpg +0 -0
  152. package/src/img/panoramax.svg +13 -0
  153. package/src/img/switch_big.svg +20 -10
  154. package/src/index.js +7 -9
  155. package/src/translations/br.json +1 -0
  156. package/src/translations/da.json +38 -15
  157. package/src/translations/de.json +5 -3
  158. package/src/translations/en.json +35 -15
  159. package/src/translations/eo.json +38 -15
  160. package/src/translations/es.json +1 -1
  161. package/src/translations/fr.json +36 -16
  162. package/src/translations/hu.json +1 -1
  163. package/src/translations/it.json +39 -16
  164. package/src/translations/ja.json +182 -1
  165. package/src/translations/nl.json +106 -6
  166. package/src/translations/pl.json +1 -1
  167. package/src/translations/sv.json +182 -0
  168. package/src/translations/zh_Hant.json +35 -14
  169. package/src/utils/API.js +109 -49
  170. package/src/utils/InitParameters.js +388 -0
  171. package/src/utils/PhotoAdapter.js +1 -0
  172. package/src/utils/URLHandler.js +362 -0
  173. package/src/utils/geocoder.js +152 -0
  174. package/src/utils/{I18n.js → i18n.js} +7 -3
  175. package/src/utils/index.js +11 -0
  176. package/src/utils/{Map.js → map.js} +256 -77
  177. package/src/utils/picture.js +442 -0
  178. package/src/utils/utils.js +324 -0
  179. package/src/utils/widgets.js +55 -0
  180. package/tests/components/core/Basic.test.js +121 -0
  181. package/tests/components/core/BasicMock.js +25 -0
  182. package/tests/components/core/CoverageMap.test.js +20 -0
  183. package/tests/components/core/Editor.test.js +20 -0
  184. package/tests/components/core/PhotoViewer.test.js +57 -0
  185. package/tests/components/core/Viewer.test.js +84 -0
  186. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +73 -0
  187. package/tests/components/core/__snapshots__/Viewer.test.js.snap +145 -0
  188. package/tests/components/ui/CopyButton.test.js +52 -0
  189. package/tests/components/ui/Loader.test.js +55 -0
  190. package/tests/components/{Map.test.js → ui/Map.test.js} +73 -61
  191. package/tests/components/{Photo.test.js → ui/Photo.test.js} +97 -63
  192. package/tests/components/ui/Popup.test.js +26 -0
  193. package/tests/components/ui/QualityScore.test.js +18 -0
  194. package/tests/components/ui/SearchBar.test.js +110 -0
  195. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +33 -0
  196. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  197. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  198. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +70 -6
  199. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  200. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  201. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  202. package/tests/utils/API.test.js +83 -83
  203. package/tests/utils/InitParameters.test.js +499 -0
  204. package/tests/utils/URLHandler.test.js +401 -0
  205. package/tests/utils/__snapshots__/API.test.js.snap +10 -0
  206. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  207. package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +1 -1
  208. package/tests/utils/__snapshots__/map.test.js.snap +11 -0
  209. package/tests/utils/__snapshots__/picture.test.js.snap +327 -0
  210. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  211. package/tests/utils/geocoder.test.js +37 -0
  212. package/tests/utils/{I18n.test.js → i18n.test.js} +8 -8
  213. package/tests/utils/map.test.js +126 -0
  214. package/tests/utils/picture.test.js +745 -0
  215. package/tests/utils/utils.test.js +288 -0
  216. package/tests/utils/widgets.test.js +31 -0
  217. package/docs/01_Start.md +0 -149
  218. package/docs/02_Usage.md +0 -831
  219. package/docs/04_Advanced_examples.md +0 -216
  220. package/src/Editor.css +0 -37
  221. package/src/Editor.js +0 -361
  222. package/src/StandaloneMap.js +0 -114
  223. package/src/Viewer.css +0 -203
  224. package/src/Viewer.js +0 -1246
  225. package/src/components/CoreView.css +0 -70
  226. package/src/components/CoreView.js +0 -175
  227. package/src/components/Loader.css +0 -74
  228. package/src/components/Loader.js +0 -120
  229. package/src/img/loader_hd.jpg +0 -0
  230. package/src/utils/Exif.js +0 -193
  231. package/src/utils/Utils.js +0 -631
  232. package/src/utils/Widgets.js +0 -562
  233. package/src/viewer/URLHash.js +0 -469
  234. package/src/viewer/Widgets.css +0 -880
  235. package/src/viewer/Widgets.js +0 -1470
  236. package/tests/Editor.test.js +0 -126
  237. package/tests/StandaloneMap.test.js +0 -45
  238. package/tests/Viewer.test.js +0 -366
  239. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  240. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  241. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  242. package/tests/components/CoreView.test.js +0 -92
  243. package/tests/components/Loader.test.js +0 -38
  244. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  245. package/tests/utils/Exif.test.js +0 -124
  246. package/tests/utils/Map.test.js +0 -113
  247. package/tests/utils/Utils.test.js +0 -300
  248. package/tests/utils/Widgets.test.js +0 -107
  249. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  250. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  251. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  252. package/tests/viewer/URLHash.test.js +0 -559
  253. package/tests/viewer/Widgets.test.js +0 -127
  254. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  255. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
@@ -0,0 +1,113 @@
1
+ import {LitElement, html, css} from "lit";
2
+ import { panel } from "../../styles";
3
+ import { fa } from "../../../utils/widgets";
4
+ import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
5
+ import PanoramaxImg from "../../../img/panoramax.svg";
6
+ import { classMap } from "lit/directives/class-map.js";
7
+
8
+ /**
9
+ * Legend widget, handling switch between map and photo components.
10
+ * Also displays a default "About Panoramax" message.
11
+ * @class Panoramax.components.ui.widgets.Legend
12
+ * @element pnx-widget-legend
13
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
14
+ * @slot `editors` External links to map editors, or any tool that may be helpful. Defaults to OSM tools (iD & JOSM).
15
+ * @example
16
+ * ```html
17
+ * <!-- Default legend -->
18
+ * <pnx-widget-legend
19
+ * _parent=${viewer}
20
+ * focus="map"
21
+ * picture="PICTURE-ID-IF-ANY"
22
+ * />
23
+ *
24
+ * <!-- With custom editor links -->
25
+ * <pnx-widget-legend
26
+ * _parent=${viewer}
27
+ * focus="map"
28
+ * picture="PICTURE-ID-IF-ANY"
29
+ * >
30
+ * <div slot="editors"><a href="http://my.own.tool">Edit in my own tool</a></div>
31
+ * </pnx-widget-legend>
32
+ * ```
33
+ */
34
+ export default class Legend extends LitElement {
35
+ /** @private */
36
+ static styles = [panel, css`
37
+ .pnx-panel[part="panel"] {
38
+ border-radius: 10px;
39
+ position: relative;
40
+ max-width: 80vw;
41
+ z-index: 121; /* To appear above mini component */
42
+ min-width: unset;
43
+ }
44
+ .pnx-panel[part="panel"].pnx-padded {
45
+ padding: 10px;
46
+ width: 250px;
47
+ }
48
+ .presentation {
49
+ font-size: 0.9em;
50
+ display: flex;
51
+ gap: 5px;
52
+ align-items: center;
53
+ }
54
+ .logo {
55
+ width: 45px;
56
+ }
57
+ `];
58
+
59
+ /**
60
+ * Component properties.
61
+ * @memberof Panoramax.components.ui.widgets.Legend#
62
+ * @type {Object}
63
+ * @property {string} [focus] The focused main component (map, pic)
64
+ * @property {string} [picture] The picture ID
65
+ */
66
+ static properties = {
67
+ focus: {type: String},
68
+ picture: {type: String},
69
+ };
70
+
71
+ render() {
72
+ const classes = {
73
+ "pnx-panel": true,
74
+ "pnx-padded": this.focus == "map",
75
+ };
76
+
77
+ return html`<div class=${classMap(classes)} part="panel">
78
+ <div
79
+ class="presentation"
80
+ style=${this.focus != "map" && this.picture ? "display: none": ""}
81
+ >
82
+ <img class="logo" src=${PanoramaxImg} alt="" />
83
+ <div>
84
+ Panoramax est le géocommun des photos de rues.
85
+ <pnx-link-button
86
+ title=${this._parent?._t.map.more_panoramax}
87
+ kind="superinline"
88
+ href="https://panoramax.fr"
89
+ target="_blank"
90
+ size="sm"
91
+ >
92
+ ${fa(faInfoCircle)}
93
+ </pnx-link-button>
94
+ </div>
95
+ </div>
96
+ <pnx-picture-legend
97
+ ._parent=${this._parent}
98
+ style=${this.focus == "map" ? "display: none": ""}
99
+ collapsable
100
+ >
101
+ <slot slot="editors" name="editors">
102
+ <pnx-widget-osmeditors ._parent=${this._parent} />
103
+ </slot>
104
+ </pnx-picture-legend>
105
+ <pnx-map-legend
106
+ ._parent=${this._parent}
107
+ style=${this.focus != "map" ? "display: none": ""}
108
+ ></pnx-map-legend>
109
+ </div>`;
110
+ }
111
+ }
112
+
113
+ customElements.define("pnx-widget-legend", Legend);
@@ -0,0 +1,104 @@
1
+ import { LitElement, html, nothing } from "lit";
2
+ import { fa } from "../../../utils/widgets";
3
+ import { faSliders } from "@fortawesome/free-solid-svg-icons/faSliders";
4
+ import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
5
+ import { faXmark } from "@fortawesome/free-solid-svg-icons/faXmark";
6
+ import { activeIcon } from "../../styles";
7
+ import { MAP_FILTERS } from "../MapMore";
8
+
9
+ /**
10
+ * Collapsible button showing off map filters menus.
11
+ * @class Panoramax.components.ui.widgets.MapFiltersButton
12
+ * @element pnx-widget-mapfilters
13
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
14
+ * @example
15
+ * ```html
16
+ * <pnx-widget-mapfilters user-search="" _parent=${viewer} />
17
+ * ```
18
+ */
19
+ export default class MapFiltersButton extends LitElement {
20
+ /** @private */
21
+ static styles = [activeIcon];
22
+
23
+ /**
24
+ * Component properties.
25
+ * @memberof Panoramax.components.ui.widgets.MapFiltersButton#
26
+ * @type {Object}
27
+ * @property {boolean} [user-search=false] Should user search filter show up ?
28
+ * @property {boolean} [quality-score=false] Should quality score filter show up ?
29
+ */
30
+ static properties = {
31
+ "user-search": {type: Boolean},
32
+ "quality-score": {type: Boolean},
33
+ _active: {state: true},
34
+ };
35
+
36
+ constructor() {
37
+ super();
38
+ this["user-search"] = false;
39
+ this["quality-score"] = false;
40
+ this._active = false;
41
+ }
42
+
43
+ /** @private */
44
+ connectedCallback() {
45
+ super.connectedCallback();
46
+
47
+ // Listen to user visibility changes to switch the filter active icon
48
+ this._parent?.onceMapReady?.().then(() => {
49
+ this._active = (
50
+ Object.keys(this._parent.map._mapFilters).filter(d => d && d !== "theme").length > 0
51
+ || this._parent.map.getVisibleUsers().filter(u => u !== "geovisio").length > 0
52
+ );
53
+
54
+ this._parent.map.on("filters-changed", e => {
55
+ this._active = (
56
+ Object.keys(e).filter(d => d && MAP_FILTERS.includes(d) && d != "theme").length > 0
57
+ || this._parent.map.getVisibleUsers().filter(u => u !== "geovisio").length > 0
58
+ );
59
+ });
60
+
61
+ this._parent.map.on("users-changed", e => {
62
+ this._active = (
63
+ Object.keys(this._parent.map._mapFilters).filter(d => d && d !== "theme").length > 0
64
+ || e.usersIds.filter(u => u !== "geovisio").length > 0
65
+ );
66
+ });
67
+ });
68
+ }
69
+
70
+ /** @private */
71
+ render() {
72
+ const isSmall = this._parent?.isWidthSmall();
73
+ const resetIcon = fa(faXmark);
74
+ resetIcon.addEventListener("click", e => {
75
+ e.stopPropagation();
76
+ this.shadowRoot.querySelector("pnx-map-filters-menu")._onReset();
77
+ this.shadowRoot.querySelector("#pnx-widget-filter")._opened = false;
78
+ });
79
+
80
+ return html`
81
+ <pnx-togglable-group
82
+ id="pnx-widget-filter"
83
+ padded="false"
84
+ class="pnx-only-map pnx-print-hidden"
85
+ ._parent=${this._parent}
86
+ >
87
+ <pnx-button kind="flat" size="xl" slot="button">
88
+ ${fa(faSliders)}
89
+ ${this._active ? html`<span class="pnx-active-icon"></span>` : nothing}
90
+ ${isSmall ? nothing : this._parent?._t.pnx.filters}
91
+ ${isSmall ? nothing : (this._active ? resetIcon : fa(faChevronDown))}
92
+ </pnx-button>
93
+ <pnx-map-filters-menu
94
+ id="pnx-map-filters-menu"
95
+ ._parent=${this._parent}
96
+ user-search=${this["user-search"]}
97
+ quality-score=${this["quality-score"]}
98
+ ></pnx-map-filters-menu>
99
+ </pnx-togglable-group>
100
+ `;
101
+ }
102
+ }
103
+
104
+ customElements.define("pnx-widget-mapfilters", MapFiltersButton);
@@ -0,0 +1,79 @@
1
+ import { LitElement, html, nothing } from "lit";
2
+ import { fa } from "../../../utils/widgets";
3
+ import { faLayerGroup } from "@fortawesome/free-solid-svg-icons/faLayerGroup";
4
+ import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
5
+ import { faXmark } from "@fortawesome/free-solid-svg-icons/faXmark";
6
+ import { activeIcon } from "../../styles";
7
+
8
+ /**
9
+ * Collapsible button showing off map filters menus.
10
+ * @class Panoramax.components.ui.widgets.MapLayersButton
11
+ * @element pnx-widget-maplayers
12
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
13
+ * @example
14
+ * ```html
15
+ * <pnx-widget-maplayers _parent=${viewer} />
16
+ * ```
17
+ */
18
+ export default class MapLayersButton extends LitElement {
19
+ /** @private */
20
+ static styles = [activeIcon];
21
+
22
+ /** @private */
23
+ static properties = {
24
+ _active: {state: true},
25
+ };
26
+
27
+ constructor() {
28
+ super();
29
+ this._active = false;
30
+ }
31
+
32
+ /** @private */
33
+ connectedCallback() {
34
+ super.connectedCallback();
35
+
36
+ const nullThemes = [undefined, null, "", "default"];
37
+
38
+ this._parent?.onceMapReady?.().then(() => {
39
+ this._active = !nullThemes.includes(this._parent.map._mapFilters.theme);
40
+ this._parent.map.on("filters-changed", e => {
41
+ this._active = !nullThemes.includes(e.theme);
42
+ });
43
+ });
44
+ }
45
+
46
+ /** @private */
47
+ render() {
48
+ const isSmall = this._parent?.isWidthSmall();
49
+ const resetIcon = fa(faXmark);
50
+ resetIcon.addEventListener("click", e => {
51
+ e.stopPropagation();
52
+ const menu = this.shadowRoot.querySelector("pnx-map-layers-menu");
53
+ menu.shadowRoot.querySelector("#pnx-map-theme").value = "default";
54
+ menu._onThemeSelect({target: {value: "default"}});
55
+ this.shadowRoot.querySelector("#pnx-widget-map-layers")._opened = false;
56
+ });
57
+
58
+ return html`
59
+ <pnx-togglable-group
60
+ id="pnx-widget-map-layers"
61
+ class="pnx-print-hidden"
62
+ ._parent=${this._parent}
63
+ >
64
+ <pnx-button kind="flat" size="xl" slot="button">
65
+ ${fa(faLayerGroup)}
66
+ ${this._active ? html`<span class="pnx-active-icon"></span>` : nothing}
67
+ ${isSmall ? nothing : this._parent?._t.pnx.layers}
68
+ ${isSmall ? nothing : (this._active ? resetIcon : fa(faChevronDown))}
69
+ </pnx-button>
70
+ <pnx-map-layers-menu
71
+ id="pnx-map-layers-menu"
72
+ ._parent=${this._parent}
73
+ ></pnx-map-layers-menu>
74
+ </pnx-togglable-group>
75
+ `;
76
+ }
77
+ }
78
+
79
+ customElements.define("pnx-widget-maplayers", MapLayersButton);
@@ -0,0 +1,155 @@
1
+ import { LitElement, html, nothing, css } from "lit";
2
+ import { fa } from "../../../utils/widgets";
3
+ import { josmBboxParameters } from "../../../utils/utils";
4
+ import { faLocationDot } from "@fortawesome/free-solid-svg-icons/faLocationDot";
5
+ import { faSatelliteDish } from "@fortawesome/free-solid-svg-icons/faSatelliteDish";
6
+ import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt";
7
+
8
+ const JOSM_REMOTE_URL = "http://127.0.0.1:8111";
9
+ const ID_URL = "https://www.openstreetmap.org/edit?editor=id";
10
+
11
+ /**
12
+ * OSM Editors component offers direct links to OpenStreetMap's iD and JOSM editors.
13
+ * @class Panoramax.components.ui.widgets.OSMEditors
14
+ * @element pnx-widget-osmeditors
15
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
16
+ * @example
17
+ * ```html
18
+ * <pnx-widget-osmeditors _parent=${viewer} />
19
+ * ```
20
+ */
21
+ export default class OSMEditors extends LitElement {
22
+ /** @private */
23
+ static properties = {
24
+ _pic: {state: true},
25
+ _josm: {state: true},
26
+ };
27
+
28
+ /** @private */
29
+ static styles = css`
30
+ :host { display: inline-flex; gap: 5px; }
31
+ :host > * { flex: 1; }
32
+ pnx-link-button::part(btn) { height: auto; }
33
+ `;
34
+
35
+ constructor() {
36
+ super();
37
+ this._josm = false;
38
+ }
39
+
40
+ /** @private */
41
+ connectedCallback() {
42
+ super.connectedCallback();
43
+ this._parent?.onceReady().then(() => {
44
+ this._parent.onceFirstPicLoaded().then(this._onPictureLoad.bind(this));
45
+ this._parent.psv.addEventListener("picture-loaded", this._onPictureLoad.bind(this));
46
+ });
47
+ }
48
+
49
+ /** @private */
50
+ _onPictureLoad() {
51
+ this._pic = this._parent?.psv?.getPictureMetadata();
52
+ }
53
+
54
+ /**
55
+ * Enable or disable JOSM live editing using [Remote](https://josm.openstreetmap.de/wiki/Help/RemoteControlCommands)
56
+ * @private
57
+ */
58
+ _toggleJOSMLive() {
59
+ this._josm = !this._josm;
60
+
61
+ if(this._josm) {
62
+ // Check if JOSM remote is enabled
63
+ fetch(JOSM_REMOTE_URL+"/version")
64
+ .then(() => {
65
+ // First loading : download + zoom
66
+ const p1 = josmBboxParameters(this._parent?.psv?.getPictureMetadata?.());
67
+ if(p1) {
68
+ const url = `${JOSM_REMOTE_URL}/load_and_zoom?${p1}`;
69
+ fetch(url).catch(e => {
70
+ console.warn(e);
71
+ this._toggleJOSMLive();
72
+ });
73
+ }
74
+
75
+ // Enable event listening
76
+ this._josmListener = () => {
77
+ const p2 = josmBboxParameters(this._parent?.psv?.getPictureMetadata?.());
78
+ if(p2) {
79
+ // Next loadings : just zoom
80
+ // This avoids desktop focus to go on JOSM instead of
81
+ // staying on web browser
82
+ const url = `${JOSM_REMOTE_URL}/zoom?${p2}`;
83
+ fetch(url).catch(e => {
84
+ console.warn(e);
85
+ this._toggleJOSMLive();
86
+ });
87
+ }
88
+ };
89
+ this._parent?.psv?.addEventListener?.("picture-loaded", this._josmListener);
90
+ this._parent?.psv?.addEventListener?.("picture-loading", this._josmListener);
91
+ })
92
+ .catch(e => {
93
+ console.warn(e);
94
+ alert(this._parent?._t.pnx.error_josm);
95
+ this._toggleJOSMLive();
96
+ });
97
+ }
98
+ else {
99
+ if(this._josmListener) {
100
+ this._parent?.psv?.removeEventListener?.("picture-loading", this._josmListener);
101
+ this._parent?.psv?.removeEventListener?.("picture-loaded", this._josmListener);
102
+ delete this._josmListener;
103
+ }
104
+ }
105
+ }
106
+
107
+ /** @private */
108
+ render() {
109
+ if(!this._pic) { return nothing; }
110
+
111
+ // Mobile -> Geo URI
112
+ if(this._parent?.isWidthSmall()) {
113
+ return html`
114
+ <pnx-link-button
115
+ size="sm"
116
+ href="geo:${this._pic.gps[1]},${this._pic.gps[0]};u=3"
117
+ >
118
+ ${fa(faExternalLinkAlt)} ${this._parent?._t.pnx.geo_uri}
119
+ </pnx-link-button>
120
+ `;
121
+ }
122
+ else {
123
+ const idOpts = {
124
+ "map": `19/${this._pic.gps[1]}/${this._pic.gps[0]}`,
125
+ "source": "Panoramax",
126
+ "photo_overlay": "panoramax",
127
+ "photo": `panoramax/${this._pic.id}`,
128
+ };
129
+ const idUrl = idOpts && `${ID_URL}#${new URLSearchParams(idOpts).toString()}`;
130
+
131
+ return html`
132
+ <pnx-link-button
133
+ size="sm"
134
+ href=${idUrl}
135
+ target="_blank"
136
+ title="${this._parent?._t.pnx.contribute_id}"
137
+ >
138
+ ${fa(faLocationDot)} ${this._parent?._t.pnx.id}
139
+ </pnx-link-button>
140
+
141
+ <pnx-button
142
+ id="pnx-edit-josm"
143
+ size="sm"
144
+ active=${this._josm ? "" : nothing}
145
+ @click=${this._toggleJOSMLive}
146
+ title="${this._parent?._t.pnx.josm_live}"
147
+ >
148
+ ${fa(faSatelliteDish)} ${this._parent?._t.pnx.josm}
149
+ </pnx-button>
150
+ `;
151
+ }
152
+ }
153
+ }
154
+
155
+ customElements.define("pnx-widget-osmeditors", OSMEditors);
@@ -0,0 +1,117 @@
1
+ import { LitElement, html, nothing, css } from "lit";
2
+ import { fa } from "../../../utils/widgets";
3
+ import { faEllipsisV } from "@fortawesome/free-solid-svg-icons/faEllipsisV";
4
+ import { noprint } from "../../styles";
5
+
6
+ /**
7
+ * Picture Legend Actions is a menu showing up complementary actions for picture legend.
8
+ * @class Panoramax.components.ui.widgets.PictureLegendActions
9
+ * @element pnx-picture-legend-actions
10
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
11
+ * @example
12
+ * ```html
13
+ * <pnx-picture-legend-actions _parent=${viewer} />
14
+ * ```
15
+ */
16
+ export default class PictureLegendActions extends LitElement {
17
+ /** @private */
18
+ static styles = [ noprint, css`
19
+ pnx-togglable-group::part(menu) {
20
+ border-radius: 5px;
21
+ min-width: unset;
22
+ }
23
+ `];
24
+
25
+ /**
26
+ * Component properties.
27
+ * @memberof Panoramax.components.ui.widgets.PictureLegendActions#
28
+ * @type {Object}
29
+ * @property {boolean} [full=false] Show advanced actions
30
+ */
31
+ static properties = {
32
+ full: { type: Boolean },
33
+ _meta: { state: true },
34
+ };
35
+
36
+ constructor() {
37
+ super();
38
+ this.full = false;
39
+ }
40
+
41
+ /** @private */
42
+ connectedCallback() {
43
+ super.connectedCallback();
44
+
45
+ this._parent?.onceReady().then(() => {
46
+ this._meta = this._parent.psv.getPictureMetadata();
47
+ this._parent.psv.addEventListener("picture-loaded", () => {
48
+ this._meta = this._parent.psv.getPictureMetadata();
49
+ });
50
+ });
51
+ }
52
+
53
+ /** @private */
54
+ _onPrint() {
55
+ this._closeGroup();
56
+ window.print();
57
+ }
58
+
59
+ /** @private */
60
+ _closeGroup() {
61
+ this.renderRoot.querySelector("pnx-togglable-group").close();
62
+ }
63
+
64
+ /** @private */
65
+ _onShareClick() {
66
+ this._closeGroup();
67
+ this._parent._showShareOptions();
68
+ }
69
+
70
+ /** @private */
71
+ _onReportClick() {
72
+ this._closeGroup();
73
+ this._parent._showReportForm();
74
+ }
75
+
76
+ /** @private */
77
+ render() {
78
+ return html`<pnx-togglable-group padded="false" id="pic-legend-headline-menu" ._parent=${this._parent}>
79
+ <pnx-button slot="button" kind="inline">${fa(faEllipsisV)}</pnx-button>
80
+ <pnx-list-group class="pnx-print-hidden" @click=${this._closeMenu}>
81
+ ${this.full ? html`
82
+ <a
83
+ download
84
+ target="_blank"
85
+ href=${this._meta?.panorama?.hdUrl}
86
+ @click=${this._closeGroup}
87
+ >${this._parent?._t.pnx.share_image}</a>
88
+ ${this._parent.isWidthSmall() ? nothing : html`<button @click=${this._onPrint}>
89
+ ${this._parent?._t.pnx.share_print}
90
+ </button>`}
91
+ ${this._parent?.api?.getRSSURL() && html`
92
+ <a
93
+ target="_blank"
94
+ href=${this._parent?.api.getRSSURL(this._parent?.map?.getBounds?.())}
95
+ title=${this._parent?._t.pnx.share_rss_title}
96
+ @click=${this._closeGroup}
97
+ >
98
+ ${this._parent?._t.pnx.share_rss}
99
+ </a>
100
+ `}
101
+ ` : html`
102
+ <button @click=${this._onReportClick}>
103
+ ${this._parent?._t.pnx.report}
104
+ </button>
105
+ <button @click=${this._onShareClick}>
106
+ ${this._parent?._t.pnx.share}
107
+ </button>
108
+ ${this._meta ? html`<pnx-copy-button ._t=${this._parent?._t} text=${this._meta.id} unstyled>
109
+ ${this._parent?._t.pnx.metadata_general_copy_picid}
110
+ </pnx-copy-button>` : nothing}
111
+ ` }
112
+ </pnx-list-group>
113
+ </pnx-togglable-group>`;
114
+ }
115
+ }
116
+
117
+ customElements.define("pnx-picture-legend-actions", PictureLegendActions);
@@ -0,0 +1,7 @@
1
+ pnx-widget-player {
2
+ pointer-events: none;
3
+ }
4
+
5
+ pnx-widget-player > pnx-button-group {
6
+ pointer-events: auto;
7
+ }