@panoramax/web-viewer 4.0.3-develop-d48b09a7 → 4.0.3-develop-90cc79b9

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.
@@ -4,6 +4,11 @@
4
4
  **Kind**: static class of <code>Panoramax.components.menus</code>
5
5
  **Extends**: <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
6
6
  **Element**: pnx-map-legend
7
+
8
+ * [.MapLegend](#Panoramax.components.menus.MapLegend) ⇐ <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
9
+ * [new MapLegend()](#new_Panoramax.components.menus.MapLegend_new)
10
+ * [.properties](#Panoramax.components.menus.MapLegend+properties) : <code>Object</code>
11
+
7
12
  <a name="new_Panoramax.components.menus.MapLegend_new"></a>
8
13
 
9
14
  ### new MapLegend()
@@ -13,3 +18,15 @@ Map legend displays information about map sources.
13
18
  ```html
14
19
  <pnx-map-legend ._parent=${viewer} />
15
20
  ```
21
+ <a name="Panoramax.components.menus.MapLegend+properties"></a>
22
+
23
+ ### mapLegend.properties : <code>Object</code>
24
+ Component properties.
25
+
26
+ **Kind**: instance property of [<code>MapLegend</code>](#Panoramax.components.menus.MapLegend)
27
+ **Properties**
28
+
29
+ | Name | Type | Default | Description |
30
+ | --- | --- | --- | --- |
31
+ | [light] | <code>boolean</code> | <code>false</code> | Lighter version (for iframes) |
32
+
@@ -5,6 +5,11 @@
5
5
  **Extends**: <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
6
6
  **Element**: pnx-picture-legend
7
7
  **Slot**: `editors` External links to map editors, or any tool that may be helpful. Defaults to OSM tools (iD & JOSM).
8
+
9
+ * [.PictureLegend](#Panoramax.components.menus.PictureLegend) ⇐ <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
10
+ * [new PictureLegend()](#new_Panoramax.components.menus.PictureLegend_new)
11
+ * [.properties](#Panoramax.components.menus.PictureLegend+properties) : <code>Object</code>
12
+
8
13
  <a name="new_Panoramax.components.menus.PictureLegend_new"></a>
9
14
 
10
15
  ### new PictureLegend()
@@ -14,3 +19,15 @@ Picture legend shows info about picture author, capture date, address, and acces
14
19
  ```html
15
20
  <pnx-picture-legend ._parent=${viewer} />
16
21
  ```
22
+ <a name="Panoramax.components.menus.PictureLegend+properties"></a>
23
+
24
+ ### pictureLegend.properties : <code>Object</code>
25
+ Component properties.
26
+
27
+ **Kind**: instance property of [<code>PictureLegend</code>](#Panoramax.components.menus.PictureLegend)
28
+ **Properties**
29
+
30
+ | Name | Type | Default | Description |
31
+ | --- | --- | --- | --- |
32
+ | [light] | <code>boolean</code> | <code>false</code> | Lighter version (for iframes) |
33
+
@@ -0,0 +1,15 @@
1
+ <a name="Panoramax.components.ui.AnnotationsSwitch"></a>
2
+
3
+ ## Panoramax.components.ui.AnnotationsSwitch ⇐ <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
4
+ **Kind**: static class of <code>Panoramax.components.ui</code>
5
+ **Extends**: <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
6
+ **Element**: pnx-annotations-switch
7
+ <a name="new_Panoramax.components.ui.AnnotationsSwitch_new"></a>
8
+
9
+ ### new AnnotationsSwitch()
10
+ AnnotationsSwitch component allows to switch on/off pictures annotations.
11
+
12
+ **Example**
13
+ ```html
14
+ <pnx-annotations-switch ._parent=${viewer} />
15
+ ```
@@ -42,8 +42,9 @@ Component properties.
42
42
  **Kind**: instance property of [<code>Legend</code>](#Panoramax.components.ui.widgets.Legend)
43
43
  **Properties**
44
44
 
45
- | Name | Type | Description |
46
- | --- | --- | --- |
47
- | [focus] | <code>string</code> | The focused main component (map, pic) |
48
- | [picture] | <code>string</code> | The picture ID |
45
+ | Name | Type | Default | Description |
46
+ | --- | --- | --- | --- |
47
+ | [focus] | <code>string</code> | | The focused main component (map, pic) |
48
+ | [picture] | <code>string</code> | | The picture ID |
49
+ | [light] | <code>boolean</code> | <code>false</code> | Lighter version (for iframes) |
49
50
 
package/docs/reference.md CHANGED
@@ -41,11 +41,11 @@ All-in-one, ready-to-use menus for complex operations. Note that they don't embe
41
41
 
42
42
  Basic UI components:
43
43
 
44
+ - [AnnotationsSwitch](./reference/components/ui/AnnotationsSwitch.md) : a switch button for showing/hiding picture annotations.
44
45
  - [Button](./reference/components/ui/Button.md) : a simple button.
45
46
  - [ButtonGroup](./reference/components/ui/ButtonGroup.md) : button bar.
46
47
  - [CopyButton](./reference/components/ui/CopyButton.md) : a copy-to-clipboard button.
47
48
  - [Grade](./reference/components/ui/Grade.md) : a 5-star rating display.
48
- - [HashTags](./reference/components/ui/HashTags.md) : a list of hashtags associated to a picture.
49
49
  - [LinkButton](./reference/components/ui/LinkButton.md) : a link button.
50
50
  - [ListGroup](./reference/components/ui/ListGroup.md) : a menu-like list of buttons and links.
51
51
  - [ListItem](./reference/components/ui/ListItem.md) : a Material Design-like list entry.
package/mkdocs.yml CHANGED
@@ -87,11 +87,11 @@ nav:
87
87
  - PictureLegendActions: 'reference/components/ui/widgets/PictureLegendActions.md'
88
88
  - Player: 'reference/components/ui/widgets/Player.md'
89
89
  - Zoom: 'reference/components/ui/widgets/Zoom.md'
90
+ - AnnotationsSwitch: 'reference/components/ui/AnnotationsSwitch.md'
90
91
  - Button: 'reference/components/ui/Button.md'
91
92
  - ButtonGroup: 'reference/components/ui/ButtonGroup.md'
92
93
  - CopyButton: 'reference/components/ui/CopyButton.md'
93
94
  - Grade: 'reference/components/ui/Grade.md'
94
- - HashTags: 'reference/components/ui/HashTags.md'
95
95
  - LinkButton: 'reference/components/ui/LinkButton.md'
96
96
  - ListGroup: 'reference/components/ui/ListGroup.md'
97
97
  - ListItem: 'reference/components/ui/ListItem.md'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panoramax/web-viewer",
3
- "version": "4.0.3-develop-d48b09a7",
3
+ "version": "4.0.3-develop-90cc79b9",
4
4
  "description": "Panoramax web viewer for geolocated pictures",
5
5
  "main": "build/index.js",
6
6
  "author": "Panoramax team",
@@ -7,7 +7,7 @@ import URLHandler from "../../utils/URLHandler";
7
7
  import Basic from "./Basic";
8
8
  import Photo, { PSV_DEFAULT_ZOOM, PSV_ANIM_DURATION } from "../ui/Photo";
9
9
  import { createWebComp } from "../../utils/widgets";
10
- import { isNullId } from "../../utils/utils";
10
+ import { isNullId, isInIframe } from "../../utils/utils";
11
11
  import { default as InitParameters, alterPSVState, alterMapState, alterPhotoViewerState } from "../../utils/InitParameters";
12
12
  import PresetManager from "../../utils/PresetsManager";
13
13
 
@@ -125,14 +125,33 @@ export default class PhotoViewer extends Basic {
125
125
  /** @private */
126
126
  _initWidgets() {
127
127
  if(this._initParams.getParentPostInit().widgets !== "false") {
128
- this.grid.appendChild(createWebComp("pnx-widget-player", {
129
- slot: "top",
130
- _parent: this,
131
- class: "pnx-only-psv pnx-print-hidden",
132
- size: this.isHeightSmall() ? "md": "xl",
133
- }));
134
-
135
- if(!this.isWidthSmall()) {
128
+ if(!isInIframe()) {
129
+ this.grid.appendChild(createWebComp("pnx-widget-player", {
130
+ slot: "top",
131
+ _parent: this,
132
+ class: "pnx-only-psv pnx-print-hidden",
133
+ size: this.isHeightSmall() ? "md": "xl",
134
+ }));
135
+
136
+ this.grid.appendChild(createWebComp("pnx-annotations-switch", {
137
+ slot: "top",
138
+ _parent: this,
139
+ class: "pnx-only-psv pnx-print-hidden",
140
+ size: this.isHeightSmall() ? "md": "xl",
141
+ }));
142
+ }
143
+
144
+ if(isInIframe()) {
145
+ this.legend = createWebComp("pnx-widget-legend", {
146
+ slot: "bottom-right",
147
+ light: true,
148
+ _parent: this,
149
+ focus: this._initParams.getParentPostInit().focus,
150
+ picture: this._initParams.getParentPostInit().picture,
151
+ });
152
+ this.grid.appendChild(this.legend);
153
+ }
154
+ else if(!this.isWidthSmall()) {
136
155
  this.legend = createWebComp("pnx-widget-legend", {
137
156
  slot: !this.isWidthSmall() ? "top-left" : undefined,
138
157
  _parent: this,
@@ -146,12 +165,6 @@ export default class PhotoViewer extends Basic {
146
165
  _parent: this
147
166
  }));
148
167
  this.grid.appendChild(this.legend);
149
-
150
- this.grid.appendChild(createWebComp("pnx-hashtags", {
151
- slot: "top-right",
152
- _parent: this,
153
- class: "pnx-only-psv pnx-print-hidden",
154
- }));
155
168
  }
156
169
  else {
157
170
  this.legend = createWebComp("pnx-picture-legend", { _parent: this });
@@ -56,7 +56,6 @@ pnx-viewer pnx-mini {
56
56
  pnx-viewer pnx-mini {
57
57
  min-width: unset;
58
58
  min-height: unset;
59
- margin-bottom: 40px;
60
59
  }
61
60
  }
62
61
 
@@ -3,10 +3,9 @@
3
3
  import "./Viewer.css";
4
4
  import { linkMapAndPhoto, saveMapParamsToLocalStorage, getMapParamsFromLocalStorage } from "../../utils/map";
5
5
  import PhotoViewer, {KEYBOARD_SKIP_FOCUS_WIDGETS} from "./PhotoViewer";
6
- import Basic from "./Basic";
7
6
  import MapMore from "../ui/MapMore";
8
7
  import { initMapKeyboardHandler } from "../../utils/map";
9
- import { isNullId } from "../../utils/utils";
8
+ import { isNullId, isInIframe } from "../../utils/utils";
10
9
  import { createWebComp } from "../../utils/widgets";
11
10
  import { fa } from "../../utils/widgets";
12
11
  import { faPanorama } from "@fortawesome/free-solid-svg-icons/faPanorama";
@@ -16,7 +15,6 @@ import { default as InitParameters, alterMapState, alterViewerState } from "../.
16
15
 
17
16
 
18
17
  export const PSV_ZOOM_DELTA = 20;
19
- const PSV_MOVE_DELTA = Math.PI / 6;
20
18
  const MAP_MOVE_DELTA = 100;
21
19
 
22
20
 
@@ -150,20 +148,24 @@ export default class Viewer extends PhotoViewer {
150
148
  _parent: this
151
149
  }));
152
150
 
153
- if(!this.isWidthSmall()) {
151
+ if(isInIframe()) {
154
152
  this.legend = createWebComp("pnx-widget-legend", {
155
- slot: this.isWidthSmall() ? "top" : "top-left",
153
+ slot: "bottom-right",
154
+ light: true,
156
155
  _parent: this,
157
156
  focus: this._initParams.getParentPostInit().focus,
158
157
  picture: this._initParams.getParentPostInit().picture,
159
158
  });
160
159
  this.grid.appendChild(this.legend);
161
-
162
- this.grid.appendChild(createWebComp("pnx-hashtags", {
163
- slot: "top-right",
160
+ }
161
+ else if(!this.isWidthSmall()) {
162
+ this.legend = createWebComp("pnx-widget-legend", {
163
+ slot: this.isWidthSmall() ? "top" : "top-left",
164
164
  _parent: this,
165
- class: "pnx-only-psv pnx-print-hidden",
166
- }));
165
+ focus: this._initParams.getParentPostInit().focus,
166
+ picture: this._initParams.getParentPostInit().picture,
167
+ });
168
+ this.grid.appendChild(this.legend);
167
169
  }
168
170
  else {
169
171
  this.legend = createWebComp("pnx-picture-legend", { _parent: this });
@@ -180,27 +182,38 @@ export default class Viewer extends PhotoViewer {
180
182
  });
181
183
  }
182
184
 
183
- this.grid.appendChild(createWebComp("pnx-widget-player", {
184
- slot: "top",
185
- _parent: this,
186
- class: "pnx-only-psv pnx-print-hidden",
187
- size: this.isHeightSmall() ? "md": "xl",
188
- }));
185
+ if(!isInIframe()) {
186
+ this.grid.appendChild(createWebComp("pnx-widget-player", {
187
+ slot: "top",
188
+ _parent: this,
189
+ class: "pnx-only-psv pnx-print-hidden",
190
+ size: this.isHeightSmall() ? "md": "xl",
191
+ }));
192
+
193
+ this.grid.appendChild(createWebComp("pnx-annotations-switch", {
194
+ slot: "top",
195
+ _parent: this,
196
+ class: "pnx-only-psv pnx-print-hidden",
197
+ size: this.isHeightSmall() ? "md": "xl",
198
+ }));
189
199
 
190
- this.grid.appendChild(createWebComp("pnx-widget-geosearch", {
191
- slot: this.isWidthSmall() ? "top-right" : "top-left",
192
- _parent: this,
193
- class: "pnx-only-map pnx-print-hidden",
194
- geocoder: this._initParams.getParentPostInit().geocoder,
195
- }));
196
- this.grid.appendChild(createWebComp("pnx-widget-mapfilters", {
197
- slot: this.isWidthSmall() ? "top-right" : "top-left",
198
- _parent: this,
199
- "user-search": this.api._endpoints.user_search !== null && this.api._endpoints.user_tiles !== null,
200
- "quality-score": this.map?._hasQualityScore?.() || false,
201
- class: "pnx-only-map pnx-print-hidden",
202
- }));
203
- this.grid.appendChild(createWebComp("pnx-widget-maplayers", { slot: "top-right", _parent: this, class: "pnx-only-map pnx-print-hidden" }));
200
+ this.grid.appendChild(createWebComp("pnx-widget-geosearch", {
201
+ slot: this.isWidthSmall() ? "top-right" : "top-left",
202
+ _parent: this,
203
+ class: "pnx-only-map pnx-print-hidden",
204
+ geocoder: this._initParams.getParentPostInit().geocoder,
205
+ }));
206
+
207
+ this.grid.appendChild(createWebComp("pnx-widget-mapfilters", {
208
+ slot: this.isWidthSmall() ? "top-right" : "top-left",
209
+ _parent: this,
210
+ "user-search": this.api._endpoints.user_search !== null && this.api._endpoints.user_tiles !== null,
211
+ "quality-score": this.map?._hasQualityScore?.() || false,
212
+ class: "pnx-only-map pnx-print-hidden",
213
+ }));
214
+
215
+ this.grid.appendChild(createWebComp("pnx-widget-maplayers", { slot: "top-right", _parent: this, class: "pnx-only-map pnx-print-hidden" }));
216
+ }
204
217
  }
205
218
  }
206
219
 
@@ -36,6 +36,7 @@ export default class Tabs extends LitElement {
36
36
  position: sticky;
37
37
  top: 0;
38
38
  background: white;
39
+ z-index: 125;
39
40
  }
40
41
  nav ::slotted(*) {
41
42
  color: var(--grey-dark);
@@ -24,17 +24,34 @@ export default class MapLegend extends LitElement {
24
24
  }
25
25
  `;
26
26
 
27
+ /**
28
+ * Component properties.
29
+ * @memberof Panoramax.components.menus.MapLegend#
30
+ * @type {Object}
31
+ * @property {boolean} [light=false] Lighter version (for iframes)
32
+ */
33
+ static properties = {
34
+ light: {type: Boolean},
35
+ };
36
+
37
+ constructor() {
38
+ super();
39
+ this.light = false;
40
+ }
41
+
27
42
  /** @private */
28
43
  render() {
29
44
  /* eslint-disable indent */
30
45
  const mapAttrib = this._parent?.map?._attribution?._innerContainer;
31
46
  const mapLabelParts = this._parent?._t.map.map_data.split("{m}");
32
47
 
33
- return html`
34
- ${mapAttrib && mapAttrib.innerHTML.length > 0
35
- ? html`${mapLabelParts.shift()}${mapAttrib}${mapLabelParts.shift()}`
36
- : nothing}
37
- `;
48
+ return this.light ?
49
+ (mapAttrib && mapAttrib.innerHTML.length > 0 ? mapAttrib : nothing)
50
+ : html`
51
+ ${mapAttrib && mapAttrib.innerHTML.length > 0
52
+ ? html`${mapLabelParts.shift()}${mapAttrib}${mapLabelParts.shift()}`
53
+ : nothing}
54
+ `;
38
55
  }
39
56
  }
40
57
 
@@ -1,4 +1,5 @@
1
- import { LitElement, html, nothing, css } from "lit";
1
+ import { LitElement, nothing, css } from "lit";
2
+ import { html, unsafeStatic } from "lit/static-html.js";
2
3
  import { classMap } from "lit/directives/class-map.js";
3
4
  import { fa } from "../../utils/widgets";
4
5
  import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
@@ -127,10 +128,22 @@ export default class PictureLegend extends LitElement {
127
128
 
128
129
  /* Editors */
129
130
  #pic-legend-editors { margin: 0 10px; }
131
+
132
+ /* Light version */
133
+ .pnx-picture-legend-light {
134
+ width: max-content;
135
+ font-size: 10px;
136
+ }
130
137
  `];
131
138
 
132
- /** @private */
139
+ /**
140
+ * Component properties.
141
+ * @memberof Panoramax.components.menus.PictureLegend#
142
+ * @type {Object}
143
+ * @property {boolean} [light=false] Lighter version (for iframes)
144
+ */
133
145
  static properties = {
146
+ light: {type: Boolean},
134
147
  _caption: { state: true },
135
148
  _addr: { state: true },
136
149
  _expanded: { state: true },
@@ -142,6 +155,7 @@ export default class PictureLegend extends LitElement {
142
155
  super();
143
156
  this._expanded = true;
144
157
  this.collapsable = false;
158
+ this.light = false;
145
159
  }
146
160
 
147
161
  /** @private */
@@ -209,6 +223,22 @@ export default class PictureLegend extends LitElement {
209
223
  const hiddenExpanded = classMap({"pnx-hidden": this._expanded});
210
224
  const shownExpanded = classMap({"pnx-hidden": !this._expanded});
211
225
 
226
+ if(this.light) {
227
+ return html`<div class="pnx-picture-legend-light">
228
+ ${this._caption.producer?.length > 0 ? html`
229
+ <a
230
+ href=${window.location.href}
231
+ target="_blank"
232
+ title=${this._parent?._t.pnx.share_page}
233
+ >${this._caption.producer[this._caption.producer.length-1]}</a>
234
+ </div>` : nothing}
235
+
236
+ ${this._caption.producer?.length > 0 && this._caption?.license ? "|" : ""}
237
+
238
+ ${this._caption?.license ? html`${unsafeStatic(this._caption.license)}` : nothing}
239
+ `;
240
+ }
241
+
212
242
  return html`
213
243
  <div class="headline">
214
244
  ${this._parent._setFocus ? html`
@@ -14,7 +14,7 @@ import { faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp";
14
14
  import { faTags } from "@fortawesome/free-solid-svg-icons/faTags";
15
15
  import { faSvg, titles, textarea, hidden } from "../styles";
16
16
  import { createWebComp } from "../../utils/widgets";
17
- import { getGPSPrecision } from "../../utils/picture";
17
+ import { getGPSPrecision, getHashTags } from "../../utils/picture";
18
18
  import { PanoramaxMetaCatalogURL } from "../../utils/services";
19
19
  import {
20
20
  getGrade, QUALITYSCORE_GPS_VALUES, QUALITYSCORE_RES_360_VALUES,
@@ -243,6 +243,16 @@ export default class PictureMetadata extends LitElement {
243
243
  );
244
244
  let semanticsData = [];
245
245
  if(hasSemantics) {
246
+ // Hashtags
247
+ const hashtags = getHashTags(this._meta);
248
+ if(hashtags.length > 0) {
249
+ semanticsData.push({
250
+ title: this._parent?._t.pnx.semantics_hashtags,
251
+ style: "width: 100%",
252
+ content: hashtags.join(" ")
253
+ });
254
+ }
255
+
246
256
  // Full list of picture tags
247
257
  semanticsData.push({
248
258
  title: this._parent?._t.pnx.semantics_tags_picture,
@@ -392,7 +402,6 @@ export default class PictureMetadata extends LitElement {
392
402
  </strong>`
393
403
  }
394
404
  ];
395
- console.log("instance", this._meta.origInstance);
396
405
 
397
406
  return html`<pnx-tabs>
398
407
  ${this._toTab( // General
@@ -0,0 +1,124 @@
1
+ import { LitElement, html, css, nothing } from "lit";
2
+ import { fa } from "../../utils/widgets";
3
+ import { faTags } from "@fortawesome/free-solid-svg-icons/faTags";
4
+ import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faTriangleExclamation";
5
+ import { hasAnnotations } from "../../utils/picture";
6
+
7
+ /**
8
+ * AnnotationsSwitch component allows to switch on/off pictures annotations.
9
+ * @class Panoramax.components.ui.AnnotationsSwitch
10
+ * @element pnx-annotations-switch
11
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
12
+ * @example
13
+ * ```html
14
+ * <pnx-annotations-switch ._parent=${viewer} />
15
+ * ```
16
+ */
17
+ export default class AnnotationsSwitch extends LitElement {
18
+ /** @private */
19
+ static styles = css`
20
+ /* Custom button look */
21
+ pnx-button::part(btn) {
22
+ border-radius: 8px;
23
+ height: 26px;
24
+ width: 26px;
25
+ }
26
+
27
+ pnx-button[size="xl"]::part(btn) {
28
+ border-radius: 8px;
29
+ height: 38px;
30
+ width: 38px;
31
+ }
32
+
33
+ /* No-annotations badge */
34
+ .pnx-annotations-switch-empty {
35
+ position: absolute;
36
+ top: 1px;
37
+ right: 1px;
38
+ color: var(--orange);
39
+ height: 8px;
40
+ }
41
+
42
+ pnx-button[size="xl"] .pnx-annotations-switch-empty {
43
+ top: 2px;
44
+ right: 2px;
45
+ height: 12px;
46
+ }
47
+
48
+ pnx-button[active] .pnx-annotations-switch-empty {
49
+ color: var(--yellow);
50
+ }
51
+ `;
52
+
53
+ /**
54
+ * Component properties.
55
+ * @memberof Panoramax.components.ui.AnnotationsSwitch#
56
+ * @type {Object}
57
+ * @property {string} [size=xl] Button size (md, xl)
58
+ */
59
+ /** @private */
60
+ static properties = {
61
+ size: {type: String},
62
+ _annotationsToggled: {state: true},
63
+ _warnNoAnnot: {state: true},
64
+ };
65
+
66
+ constructor() {
67
+ super();
68
+ this._annotationsToggled = false;
69
+ this._warnNoAnnot = false;
70
+ this.size = "xl";
71
+ }
72
+
73
+ /** @private */
74
+ connectedCallback() {
75
+ super.connectedCallback();
76
+
77
+ this._parent.onceReady().then(() => {
78
+ this._parent.psv.addEventListener("annotations-toggled", e => {
79
+ this._annotationsToggled = e.detail.visible;
80
+ });
81
+
82
+ this._warnNoAnnot = !hasAnnotations(this._parent.psv.getPictureMetadata());
83
+ this._parent.psv.addEventListener("picture-loaded", () => {
84
+ this._warnNoAnnot = !hasAnnotations(this._parent.psv.getPictureMetadata());
85
+ });
86
+ });
87
+
88
+ this._parent.onceFirstPicLoaded().then(() => {
89
+ this._annotationsToggled = this._parent.psv.areAnnotationsVisible() || false;
90
+
91
+ if(!this._annotationsToggled) {
92
+ this._parent.psv.toggleAllAnnotations(true);
93
+ this._annotationsToggled = true;
94
+ }
95
+ });
96
+ }
97
+
98
+ _onClick() {
99
+ this._parent.psv.toggleAllAnnotations(!this._annotationsToggled);
100
+ }
101
+
102
+ /** @private */
103
+ render() {
104
+ /* eslint-disable indent */
105
+ return html`
106
+ <pnx-button
107
+ kind="outline"
108
+ size=${this.size}
109
+ style="vertical-align: middle"
110
+ title=${[
111
+ this._annotationsToggled ? this._parent._t?.pnx.semantics_hide_annotations : this._parent._t?.pnx.semantics_show_annotations,
112
+ this._warnNoAnnot ? this._parent._t?.pnx.semantics_zero_annotations : null
113
+ ].filter(v => v).join(" ")}
114
+ active=${this._annotationsToggled ? "" : nothing}
115
+ @click=${this._onClick}
116
+ >
117
+ ${fa(faTags, { styles: { "height": "unset" }})}
118
+ ${this._warnNoAnnot ? fa(faTriangleExclamation, { classes: "pnx-annotations-switch-empty" }) : nothing}
119
+ </pnx-button>
120
+ `;
121
+ }
122
+ }
123
+
124
+ customElements.define("pnx-annotations-switch", AnnotationsSwitch);
@@ -954,7 +954,7 @@ export default class Photo extends PSViewer {
954
954
 
955
955
  if(!visible) { this._myMarkers.clearMarkers(); }
956
956
  else {
957
- let annotations = meta.properties.annotations;
957
+ let annotations = meta.properties.annotations || [];
958
958
  if(annotations?.length === 0) { console.warn("No annotation available on picture", meta.id); }
959
959
 
960
960
  const picBData = this.state.textureData.panoData?.baseData;
@@ -7,7 +7,7 @@ export {default as ButtonGroup} from "./ButtonGroup";
7
7
  export {default as Button} from "./Button";
8
8
  export {default as CopyButton} from "./CopyButton";
9
9
  export {default as Grade} from "./Grade";
10
- export {default as HashTags} from "./HashTags";
10
+ export {default as AnnotationsSwitch} from "./AnnotationsSwitch";
11
11
  export {default as LinkButton} from "./LinkButton";
12
12
  export {default as ListGroup} from "./ListGroup";
13
13
  export {default as ListItem} from "./ListItem";