@panoramax/web-viewer 4.0.3 → 4.1.0-develop-55fdf56c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -1
- package/build/index.css +9 -9
- package/build/index.css.map +1 -1
- package/build/index.js +640 -456
- package/build/index.js.map +1 -1
- package/build/map.html +1 -1
- package/build/photo.html +1 -1
- package/build/viewer.html +3 -3
- package/build/widgets.html +1 -1
- package/config/jest/mocks.js +9 -1
- package/docs/03_URL_settings.md +21 -0
- package/docs/09_Develop.md +6 -0
- package/docs/images/comparative_3drender.jpg +0 -0
- package/docs/index.md +13 -0
- package/docs/reference/components/core/Editor.md +18 -0
- package/docs/reference/components/core/PhotoViewer.md +1 -0
- package/docs/reference/components/core/Viewer.md +1 -0
- package/docs/reference/components/menus/MapLegend.md +17 -0
- package/docs/reference/components/menus/MiniPictureLegend.md +15 -0
- package/docs/reference/components/menus/PictureLegend.md +17 -0
- package/docs/reference/components/ui/AnnotationsSwitch.md +15 -0
- package/docs/reference/components/ui/Button.md +1 -1
- package/docs/reference/components/ui/CopyButton.md +1 -1
- package/docs/reference/components/ui/LinkButton.md +1 -1
- package/docs/reference/components/ui/Map.md +18 -2
- package/docs/reference/components/ui/MapMore.md +6 -2
- package/docs/reference/components/ui/SemanticsEditor.md +87 -0
- package/docs/reference/components/ui/widgets/Legend.md +5 -4
- package/docs/reference/utils/URLHandler.md +7 -0
- package/docs/reference.md +3 -1
- package/docs/tutorials/aerial_imagery.md +13 -11
- package/mkdocs.yml +3 -1
- package/package.json +7 -7
- package/public/map.html +3 -3
- package/public/photo.html +1 -1
- package/public/viewer.html +3 -3
- package/public/widgets.html +32 -0
- package/src/components/core/Basic.css +2 -0
- package/src/components/core/Basic.js +3 -1
- package/src/components/core/CoverageMap.css +1 -0
- package/src/components/core/CoverageMap.js +6 -0
- package/src/components/core/Editor.css +2 -0
- package/src/components/core/Editor.js +56 -7
- package/src/components/core/PhotoViewer.css +10 -10
- package/src/components/core/PhotoViewer.js +56 -23
- package/src/components/core/Viewer.css +16 -4
- package/src/components/core/Viewer.js +62 -33
- package/src/components/layout/BottomDrawer.js +2 -1
- package/src/components/layout/Tabs.js +4 -0
- package/src/components/menus/AnnotationsList.js +13 -9
- package/src/components/menus/MapBackground.js +8 -3
- package/src/components/menus/MapFilters.js +11 -2
- package/src/components/menus/MapLayers.js +3 -2
- package/src/components/menus/MapLegend.js +35 -4
- package/src/components/menus/MiniPictureLegend.js +74 -0
- package/src/components/menus/PictureLegend.js +89 -33
- package/src/components/menus/PictureMetadata.js +49 -17
- package/src/components/menus/PlayerOptions.js +3 -3
- package/src/components/menus/Share.js +3 -3
- package/src/components/menus/index.js +5 -4
- package/src/components/styles.js +11 -0
- package/src/components/ui/AnnotationsSwitch.js +171 -0
- package/src/components/ui/Button.js +1 -1
- package/src/components/ui/CopyButton.js +1 -1
- package/src/components/ui/LinkButton.js +1 -1
- package/src/components/ui/Map.css +4 -0
- package/src/components/ui/Map.js +17 -5
- package/src/components/ui/MapMore.js +61 -25
- package/src/components/ui/Photo.css +11 -2
- package/src/components/ui/Photo.js +6 -3
- package/src/components/ui/SemanticsEditor.js +157 -0
- package/src/components/ui/index.js +2 -1
- package/src/components/ui/widgets/GeoSearch.js +3 -2
- package/src/components/ui/widgets/Legend.js +76 -15
- package/src/components/ui/widgets/MapFiltersButton.js +3 -3
- package/src/components/ui/widgets/MapLayersButton.js +3 -3
- package/src/components/ui/widgets/OSMEditors.js +2 -2
- package/src/components/ui/widgets/PictureLegendActions.js +24 -42
- package/src/components/ui/widgets/Player.js +3 -3
- package/src/components/ui/widgets/Zoom.js +4 -2
- package/src/translations/ar.json +1 -0
- package/src/translations/da.json +3 -2
- package/src/translations/de.json +64 -13
- package/src/translations/en.json +5 -1
- package/src/translations/eo.json +32 -2
- package/src/translations/fr.json +7 -1
- package/src/translations/it.json +33 -2
- package/src/translations/nl.json +53 -11
- package/src/translations/zh_Hant.json +29 -2
- package/src/utils/API.js +17 -1
- package/src/utils/InitParameters.js +46 -4
- package/src/utils/URLHandler.js +9 -1
- package/src/utils/map.js +24 -1
- package/src/utils/semantics.js +53 -1
- package/src/utils/services.js +16 -0
- package/src/utils/widgets.js +38 -0
- package/tests/components/core/Editor.test.js +1 -1
- package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +18 -6
- package/tests/components/core/__snapshots__/Viewer.test.js.snap +15 -3
- package/tests/components/ui/Photo.test.js +1 -0
- package/tests/components/ui/__snapshots__/Map.test.js.snap +164 -0
- package/tests/utils/InitParameters.test.js +27 -0
- package/tests/utils/map.test.js +12 -0
- package/tests/utils/semantics.test.js +34 -5
- package/docs/reference/components/ui/HashTags.md +0 -15
- package/src/components/ui/HashTags.js +0 -98
|
@@ -66,6 +66,7 @@ describe("InitParameters", () => {
|
|
|
66
66
|
geocoder: true,
|
|
67
67
|
widgets: true,
|
|
68
68
|
forceFocus: true,
|
|
69
|
+
keyboardShortcuts: true,
|
|
69
70
|
});
|
|
70
71
|
expect(initParams._psvInit).toEqual({});
|
|
71
72
|
expect(initParams._psvAny).toEqual({
|
|
@@ -111,11 +112,13 @@ describe("InitParameters", () => {
|
|
|
111
112
|
geocoder: true,
|
|
112
113
|
widgets: true,
|
|
113
114
|
forceFocus: true,
|
|
115
|
+
keyboardShortcuts: true,
|
|
114
116
|
});
|
|
115
117
|
});
|
|
116
118
|
|
|
117
119
|
it("uses browserStorage parameters if no URL parameter is available", () => {
|
|
118
120
|
componentAttrs.map.raster = {};
|
|
121
|
+
componentAttrs.picture = undefined;
|
|
119
122
|
const initParams = new InitParameters(componentAttrs, undefined, browserStorage);
|
|
120
123
|
expect(initParams._mapAny).toEqual({
|
|
121
124
|
theme: "qualityscore",
|
|
@@ -128,6 +131,20 @@ describe("InitParameters", () => {
|
|
|
128
131
|
});
|
|
129
132
|
});
|
|
130
133
|
|
|
134
|
+
it("uses browserStorage parameters if no URL parameter is available, except map coords if picture is set", () => {
|
|
135
|
+
componentAttrs.map.raster = {};
|
|
136
|
+
const initParams = new InitParameters(componentAttrs, undefined, browserStorage);
|
|
137
|
+
expect(initParams._mapAny).toEqual({
|
|
138
|
+
theme: "qualityscore",
|
|
139
|
+
background: "aerial",
|
|
140
|
+
center: [0,0],
|
|
141
|
+
zoom: 19,
|
|
142
|
+
pitch: undefined,
|
|
143
|
+
bearing: undefined,
|
|
144
|
+
users: "user1,user2",
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
131
148
|
it("should sanitize objects correctly", () => {
|
|
132
149
|
const initParams = new InitParameters(componentAttrs, urlParams);
|
|
133
150
|
const obj = { a: 1, b: undefined, c: 3 };
|
|
@@ -161,6 +178,7 @@ describe("InitParameters", () => {
|
|
|
161
178
|
geocoder: true,
|
|
162
179
|
widgets: true,
|
|
163
180
|
forceFocus: true,
|
|
181
|
+
keyboardShortcuts: true,
|
|
164
182
|
});
|
|
165
183
|
});
|
|
166
184
|
|
|
@@ -243,6 +261,15 @@ describe("InitParameters", () => {
|
|
|
243
261
|
expect(initParams._mapAny.background).toBe("streets");
|
|
244
262
|
expect(console.warn).toHaveBeenCalledWith("Parameter background can't be 'aerial' as no aerial imagery is available");
|
|
245
263
|
});
|
|
264
|
+
|
|
265
|
+
it("should handle keyboardShortcuts=false", () => {
|
|
266
|
+
componentAttrs["keyboard-shortcuts"] = "false";
|
|
267
|
+
const initParams = new InitParameters(componentAttrs, urlParams);
|
|
268
|
+
expect(initParams._mapInit.keyboard).toBe(false);
|
|
269
|
+
expect(initParams._parentPostInit.keyboardShortcuts).toBe(false);
|
|
270
|
+
expect(initParams._psvInit.keyboard).toBe(false);
|
|
271
|
+
expect(initParams._psvInit.keyboardActions).toEqual({});
|
|
272
|
+
});
|
|
246
273
|
});
|
|
247
274
|
|
|
248
275
|
describe("getMapPositionFromString", () => {
|
package/tests/utils/map.test.js
CHANGED
|
@@ -11,6 +11,18 @@ describe("getThumbGif", () => {
|
|
|
11
11
|
});
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
describe("isNullCoordinates", () => {
|
|
15
|
+
it.each([
|
|
16
|
+
[undefined, true],
|
|
17
|
+
[null, true],
|
|
18
|
+
[[0,0], true],
|
|
19
|
+
[[48.7, -1.5], false],
|
|
20
|
+
[[], true],
|
|
21
|
+
])("works with %s", (input, expected) => {
|
|
22
|
+
expect(map.isNullCoordinates(input)).toBe(expected);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
14
26
|
describe("isLabelLayer", () => {
|
|
15
27
|
it("works with just text-field", () => {
|
|
16
28
|
const layer = { type: "symbol", layout: { "text-field": "Label" } };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
decodeKey, decodeBasicTag, computeDiffTags, groupByPrefix
|
|
3
|
+
} from "../../src/utils/semantics";
|
|
2
4
|
|
|
3
5
|
describe("decodeBasicTag", () => {
|
|
4
6
|
test("should return null if no equal sign is present", () => {
|
|
@@ -7,14 +9,14 @@ describe("decodeBasicTag", () => {
|
|
|
7
9
|
|
|
8
10
|
test("should correctly decode a tag with an equal sign", () => {
|
|
9
11
|
expect(decodeBasicTag("key=value")).toEqual({
|
|
10
|
-
key: { prefix: "", subkey: "key", qualifies: null },
|
|
12
|
+
key: { key: "key", prefix: "", subkey: "key", qualifies: null },
|
|
11
13
|
value: "value"
|
|
12
14
|
});
|
|
13
15
|
});
|
|
14
16
|
|
|
15
17
|
test("should correctly decode a tag with a prefix", () => {
|
|
16
18
|
expect(decodeBasicTag("osm|key=value")).toEqual({
|
|
17
|
-
key: { prefix: "osm", subkey: "key", qualifies: null },
|
|
19
|
+
key: { key: "osm|key", prefix: "osm", subkey: "key", qualifies: null },
|
|
18
20
|
value: "value"
|
|
19
21
|
});
|
|
20
22
|
});
|
|
@@ -23,6 +25,7 @@ describe("decodeBasicTag", () => {
|
|
|
23
25
|
describe("decodeKey", () => {
|
|
24
26
|
test("should return default structure if key does not match regex", () => {
|
|
25
27
|
expect(decodeKey("panoKey")).toEqual({
|
|
28
|
+
key: "panoKey",
|
|
26
29
|
prefix: "",
|
|
27
30
|
subkey: "panoKey",
|
|
28
31
|
qualifies: null
|
|
@@ -31,6 +34,7 @@ describe("decodeKey", () => {
|
|
|
31
34
|
|
|
32
35
|
test("should correctly decode a key with a prefix", () => {
|
|
33
36
|
expect(decodeKey("osm|traffic_sign")).toEqual({
|
|
37
|
+
key: "osm|traffic_sign",
|
|
34
38
|
prefix: "osm",
|
|
35
39
|
subkey: "traffic_sign",
|
|
36
40
|
qualifies: null
|
|
@@ -39,21 +43,46 @@ describe("decodeKey", () => {
|
|
|
39
43
|
|
|
40
44
|
test("should correctly decode a key with qualifiers", () => {
|
|
41
45
|
expect(decodeKey("detection_model[camera_mount=pole]")).toEqual({
|
|
46
|
+
key: "detection_model[camera_mount=pole]",
|
|
42
47
|
prefix: "",
|
|
43
48
|
subkey: "detection_model",
|
|
44
|
-
qualifies: { key: { prefix: "", subkey: "camera_mount", qualifies: null }, value: "pole" }
|
|
49
|
+
qualifies: { key: { key: "camera_mount", prefix: "", subkey: "camera_mount", qualifies: null }, value: "pole" }
|
|
45
50
|
});
|
|
46
51
|
});
|
|
47
52
|
|
|
48
53
|
test("should correctly decode a key with a prefix and qualifiers", () => {
|
|
49
54
|
expect(decodeKey("osm|source[osm|traffic_sign=stop]")).toEqual({
|
|
55
|
+
key: "osm|source[osm|traffic_sign=stop]",
|
|
50
56
|
prefix: "osm",
|
|
51
57
|
subkey: "source",
|
|
52
|
-
qualifies: { key: { prefix: "osm", subkey: "traffic_sign", qualifies: null }, value: "stop" }
|
|
58
|
+
qualifies: { key: { key: "osm|traffic_sign", prefix: "osm", subkey: "traffic_sign", qualifies: null }, value: "stop" }
|
|
53
59
|
});
|
|
54
60
|
});
|
|
55
61
|
});
|
|
56
62
|
|
|
63
|
+
describe("computeDiffTags", () => {
|
|
64
|
+
it("should return new set of tags when no tag is missing in next", () => {
|
|
65
|
+
const prev = [{key: "tag1", value: "value1"}, {key: "tag2", value: "value2"}];
|
|
66
|
+
const next = [{key: "tag1", value: "value1"}, {key: "tag2", value: "value2"}, {key: "tag3", value: "value3"}];
|
|
67
|
+
|
|
68
|
+
expect(computeDiffTags(prev, next)).toEqual([{key: "tag3", value: "value3", action: "add"}]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should return new set of tags with missing tags marked as delete when some tag is missing in next", () => {
|
|
72
|
+
const prev = [{key: "tag1", value: "value1"}, {key: "tag2", value: "value2"}];
|
|
73
|
+
const next = [{key: "tag1", value: "value1"}];
|
|
74
|
+
|
|
75
|
+
expect(computeDiffTags(prev, next)).toEqual([{key: "tag2", value: "value2", action: "delete"}]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should return new set of tags with all tags marked as delete when all tags are missing in next", () => {
|
|
79
|
+
const prev = [{key: "tag1", value: "value1"}, {key: "tag2", value: "value2"}];
|
|
80
|
+
const next = [];
|
|
81
|
+
|
|
82
|
+
expect(computeDiffTags(prev, next)).toEqual([{key: "tag1", value: "value1", action: "delete"}, {key: "tag2", value: "value2", action: "delete"}]);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
57
86
|
describe("groupByPrefix", () => {
|
|
58
87
|
test("should group tags by prefix", () => {
|
|
59
88
|
const tags = [
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<a name="Panoramax.components.ui.HashTags"></a>
|
|
2
|
-
|
|
3
|
-
## Panoramax.components.ui.HashTags ⇐ <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-hashtags
|
|
7
|
-
<a name="new_Panoramax.components.ui.HashTags_new"></a>
|
|
8
|
-
|
|
9
|
-
### new HashTags()
|
|
10
|
-
HashTags component shows the list of hashtags associated to a picture.
|
|
11
|
-
|
|
12
|
-
**Example**
|
|
13
|
-
```html
|
|
14
|
-
<pnx-hashtags ._parent=${viewer} />
|
|
15
|
-
```
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css, nothing } from "lit";
|
|
2
|
-
import { getHashTags, hasAnnotations } from "../../utils/picture";
|
|
3
|
-
import { fa } from "../../utils/widgets";
|
|
4
|
-
import { faDrawPolygon } from "@fortawesome/free-solid-svg-icons/faDrawPolygon";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* HashTags component shows the list of hashtags associated to a picture.
|
|
8
|
-
* @class Panoramax.components.ui.HashTags
|
|
9
|
-
* @element pnx-hashtags
|
|
10
|
-
* @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
|
|
11
|
-
* @example
|
|
12
|
-
* ```html
|
|
13
|
-
* <pnx-hashtags ._parent=${viewer} />
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export default class HashTags extends LitElement {
|
|
17
|
-
/** @private */
|
|
18
|
-
static styles = css`
|
|
19
|
-
div {
|
|
20
|
-
background: linear-gradient(to bottom left, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.2));
|
|
21
|
-
margin-top: -10px;
|
|
22
|
-
margin-right: -10px;
|
|
23
|
-
padding: 5px 10px;
|
|
24
|
-
border-bottom-left-radius: 10px;
|
|
25
|
-
font-family: var(--font-family);
|
|
26
|
-
color: white;
|
|
27
|
-
font-size: 0.8em;
|
|
28
|
-
}
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
/** @private */
|
|
32
|
-
static properties = {
|
|
33
|
-
_tags: {state: true},
|
|
34
|
-
_visible: {state: true},
|
|
35
|
-
_annotationsToggled: {state: true},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
constructor() {
|
|
39
|
-
super();
|
|
40
|
-
this._tags = [];
|
|
41
|
-
this._visible = false;
|
|
42
|
-
this._annotationsToggled = false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** @private */
|
|
46
|
-
connectedCallback() {
|
|
47
|
-
super.connectedCallback();
|
|
48
|
-
|
|
49
|
-
this._parent.onceReady().then(() => {
|
|
50
|
-
this._tags = getHashTags(this._parent?.psv?.getPictureMetadata?.());
|
|
51
|
-
|
|
52
|
-
// Component visibility : only if seen at least one pic with semantics
|
|
53
|
-
if(
|
|
54
|
-
!this._visible && (
|
|
55
|
-
this._tags.length > 0
|
|
56
|
-
|| hasAnnotations(this._parent?.psv?.getPictureMetadata?.())
|
|
57
|
-
)
|
|
58
|
-
) {
|
|
59
|
-
this._visible = true;
|
|
60
|
-
this._parent.psv.toggleAllAnnotations(true);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this._parent.psv.addEventListener("picture-loaded", () => {
|
|
64
|
-
this._tags = getHashTags(this._parent.psv.getPictureMetadata());
|
|
65
|
-
if(
|
|
66
|
-
!this._visible && (
|
|
67
|
-
this._tags.length > 0 ||
|
|
68
|
-
hasAnnotations(this._parent.psv.getPictureMetadata())
|
|
69
|
-
)
|
|
70
|
-
) {
|
|
71
|
-
this._visible = true;
|
|
72
|
-
this._parent.psv.toggleAllAnnotations(true);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
this._annotationsToggled = this._parent.psv.areAnnotationsVisible() || false;
|
|
77
|
-
this._parent.psv.addEventListener("annotations-toggled", e => {
|
|
78
|
-
this._annotationsToggled = e.detail.visible;
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** @private */
|
|
84
|
-
render() {
|
|
85
|
-
return this._visible ? html`<div>
|
|
86
|
-
${this._tags.join(" ")}
|
|
87
|
-
<pnx-button
|
|
88
|
-
kind="outline"
|
|
89
|
-
style="vertical-align: middle"
|
|
90
|
-
title=${this._annotationsToggled ? this._parent._t?.pnx.semantics_hide_annotations : this._parent._t?.pnx.semantics_show_annotations}
|
|
91
|
-
active=${this._annotationsToggled ? "" : nothing}
|
|
92
|
-
@click=${() => this._parent.psv.toggleAllAnnotations(!this._annotationsToggled)}
|
|
93
|
-
>${fa(faDrawPolygon)}</pnx-button>
|
|
94
|
-
</div>` : nothing;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
customElements.define("pnx-hashtags", HashTags);
|