@panoramax/web-viewer 3.2.3-develop-6e69906d → 3.2.3-develop-8b82a4e5
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/build/index.css +2 -2
- package/build/index.css.map +1 -1
- package/build/index.js +535 -216
- package/build/index.js.map +1 -1
- package/build/widgets.html +1 -1
- package/docs/reference/components/core/PhotoViewer.md +2 -0
- package/docs/reference/components/core/Viewer.md +2 -0
- package/docs/reference/components/layout/BottomDrawer.md +35 -0
- package/docs/reference/components/layout/Tabs.md +45 -0
- package/docs/reference/components/menus/PictureLegend.md +1 -0
- package/docs/reference/components/ui/Button.md +3 -2
- package/docs/reference/components/ui/CopyButton.md +7 -4
- package/docs/reference/components/ui/LinkButton.md +1 -0
- package/docs/reference/components/ui/ListGroup.md +22 -0
- package/docs/reference/components/ui/widgets/Legend.md +11 -0
- package/docs/reference/components/ui/widgets/OSMEditors.md +15 -0
- package/docs/reference/components/ui/widgets/PictureLegendActions.md +32 -0
- package/docs/reference.md +6 -2
- package/mkdocs.yml +5 -1
- package/package.json +1 -1
- package/public/widgets.html +45 -9
- package/src/components/core/Basic.css +1 -0
- package/src/components/core/PhotoViewer.css +0 -23
- package/src/components/core/PhotoViewer.js +41 -22
- package/src/components/core/Viewer.css +6 -31
- package/src/components/core/Viewer.js +40 -11
- package/src/components/layout/BottomDrawer.js +204 -0
- package/src/components/layout/CorneredGrid.js +3 -0
- package/src/components/layout/Tabs.js +133 -0
- package/src/components/layout/index.js +2 -0
- package/src/components/menus/PictureLegend.js +162 -23
- package/src/components/menus/PictureMetadata.js +220 -110
- package/src/components/menus/Share.js +2 -142
- package/src/components/styles.js +47 -47
- package/src/components/ui/Button.js +4 -2
- package/src/components/ui/CopyButton.js +34 -5
- package/src/components/ui/LinkButton.js +6 -7
- package/src/components/ui/ListGroup.js +66 -0
- package/src/components/ui/Map.js +4 -1
- package/src/components/ui/QualityScore.js +19 -24
- package/src/components/ui/TogglableGroup.js +47 -53
- package/src/components/ui/index.js +1 -0
- package/src/components/ui/widgets/Legend.js +29 -6
- package/src/components/ui/widgets/OSMEditors.js +153 -0
- package/src/components/ui/widgets/PictureLegendActions.js +131 -0
- package/src/components/ui/widgets/index.js +5 -4
- package/src/translations/en.json +14 -8
- package/src/translations/fr.json +14 -8
- package/src/utils/InitParameters.js +2 -1
- package/src/utils/geocoder.js +3 -1
- package/src/utils/picture.js +1 -2
- package/src/utils/widgets.js +5 -43
- package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +12 -32
- package/tests/components/core/__snapshots__/Viewer.test.js.snap +5 -25
- package/tests/components/ui/__snapshots__/Photo.test.js.snap +6 -2
- package/tests/utils/InitParameters.test.js +7 -9
- package/tests/utils/__snapshots__/picture.test.js.snap +13 -4
- package/tests/utils/picture.test.js +2 -2
- package/tests/utils/widgets.test.js +0 -59
- package/docs/reference/components/ui/widgets/Share.md +0 -15
- package/src/components/ui/widgets/Share.js +0 -30
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { panel } from "../styles";
|
|
3
3
|
import { listenForMenuClosure } from "../../utils/widgets";
|
|
4
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Togglable Group element allows to make a menu appear/disappear based on button click.
|
|
@@ -27,9 +28,8 @@ export default class TogglableGroup extends LitElement {
|
|
|
27
28
|
height: 100%;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
.pnx-panel {
|
|
31
|
-
|
|
32
|
-
}
|
|
31
|
+
.pnx-panel { z-index: 130; }
|
|
32
|
+
.pnx-panel-fixed { position: fixed; }
|
|
33
33
|
` ];
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -88,71 +88,65 @@ export default class TogglableGroup extends LitElement {
|
|
|
88
88
|
|
|
89
89
|
/** @private */
|
|
90
90
|
adjustMenuPosition(btn) {
|
|
91
|
-
const
|
|
92
|
-
const
|
|
91
|
+
const btnMenuMargin = 5;
|
|
92
|
+
const borderMargin = 10;
|
|
93
|
+
|
|
94
|
+
// Reset menu position
|
|
95
|
+
const menu = this.shadowRoot.querySelector("div[part='menu']");
|
|
96
|
+
menu.style.top = null;
|
|
97
|
+
menu.style.bottom = null;
|
|
98
|
+
menu.style.right = null;
|
|
99
|
+
menu.style.left = null;
|
|
100
|
+
menu.style.overflowY = null;
|
|
101
|
+
|
|
102
|
+
// Get positions on screen
|
|
93
103
|
const btnRect = btn.getBoundingClientRect();
|
|
94
104
|
let menuRect = menu.getBoundingClientRect();
|
|
105
|
+
const fitsWidth = menuRect.right <= window.innerWidth - borderMargin;
|
|
106
|
+
const fitsHeight = menuRect.bottom <= window.innerHeight - borderMargin;
|
|
95
107
|
|
|
96
|
-
|
|
97
|
-
if(
|
|
98
|
-
menu.style.
|
|
99
|
-
menu.style.overflowY = "scroll";
|
|
100
|
-
menuRect = menu.getBoundingClientRect();
|
|
108
|
+
// No overflow = space a bit under button
|
|
109
|
+
if(fitsWidth && fitsHeight) {
|
|
110
|
+
menu.style.top = `${btnRect.bottom+btnMenuMargin}px`;
|
|
101
111
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
menu.style.
|
|
105
|
-
menu.style.
|
|
112
|
+
// Overflows width+height = put at button's top+left
|
|
113
|
+
else if(!fitsWidth && !fitsHeight) {
|
|
114
|
+
menu.style.right = `${window.innerWidth - btnRect.left + btnMenuMargin}px`;
|
|
115
|
+
menu.style.bottom = `${window.innerHeight - btnRect.bottom}px`;
|
|
116
|
+
|
|
117
|
+
// Check if it doesn't overflow on top
|
|
106
118
|
menuRect = menu.getBoundingClientRect();
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
menu.style.
|
|
111
|
-
menu.style.overflowY = "scroll";
|
|
112
|
-
menuRect = menu.getBoundingClientRect();
|
|
119
|
+
if(menuRect.top - borderMargin < 0) {
|
|
120
|
+
menu.style.bottom = `${borderMargin}px`;
|
|
121
|
+
menu.style.top = `${btnRect.top}px`;
|
|
122
|
+
menu.style.overflowY = "auto";
|
|
113
123
|
}
|
|
114
124
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if(overflowRight && overflowBottom && overflowTop) {
|
|
121
|
-
menu.style.top = smallWidth ? "0px" : `${btnRect.height + 5}px`;
|
|
122
|
-
menu.style.bottom = null;
|
|
123
|
-
menu.style.right = `${btnRect.width + 5}px`;
|
|
124
|
-
menu.style.left = null;
|
|
125
|
+
// Overflows height = limit height
|
|
126
|
+
else if(!fitsHeight) {
|
|
127
|
+
menu.style.bottom = `${borderMargin}px`;
|
|
128
|
+
menu.style.top = `${btnRect.bottom+btnMenuMargin}px`;
|
|
129
|
+
menu.style.overflowY = "auto";
|
|
125
130
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
menu.style.
|
|
129
|
-
menu.style.right = `${
|
|
130
|
-
menu.style.left = null;
|
|
131
|
-
}
|
|
132
|
-
else if(overflowRight) {
|
|
133
|
-
menu.style.top = smallWidth ? "0px" : `${btnRect.height + 5}px`;
|
|
134
|
-
menu.style.bottom = null;
|
|
135
|
-
menu.style.right = smallWidth ? `${btnRect.width + 5}px` : "0px";
|
|
136
|
-
menu.style.left = null;
|
|
137
|
-
}
|
|
138
|
-
else if(overflowBottom && !overflowTop) {
|
|
139
|
-
menu.style.top = null;
|
|
140
|
-
menu.style.bottom = "0px";
|
|
141
|
-
menu.style.left = `${btnRect.width + 5}px`;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
menu.style.top = `${btnRect.height + 5}px`;
|
|
145
|
-
menu.style.right = null;
|
|
146
|
-
menu.style.left = "0px";
|
|
147
|
-
menu.style.bottom = null;
|
|
131
|
+
// Overflows width = move to left
|
|
132
|
+
else if(!fitsWidth) {
|
|
133
|
+
menu.style.top = `${btnRect.bottom+btnMenuMargin}px`;
|
|
134
|
+
menu.style.right = `${window.innerWidth - btnRect.right}px`;
|
|
148
135
|
}
|
|
149
136
|
}
|
|
150
137
|
|
|
151
138
|
/** @private */
|
|
152
139
|
render() {
|
|
140
|
+
const panelClasses = {
|
|
141
|
+
"pnx-panel": true,
|
|
142
|
+
"pnx-panel-fixed": true,
|
|
143
|
+
"pnx-hidden": !this._opened,
|
|
144
|
+
"pnx-padded": this.padded !== "false",
|
|
145
|
+
};
|
|
146
|
+
|
|
153
147
|
return html`<div class="container">
|
|
154
148
|
<slot name="button" @slotchange=${this.handleButtonSlotChange}></slot>
|
|
155
|
-
<div class
|
|
149
|
+
<div class=${classMap(panelClasses)} part="menu">
|
|
156
150
|
<slot></slot>
|
|
157
151
|
</div>
|
|
158
152
|
</div>`;
|
|
@@ -8,6 +8,7 @@ export {default as Button} from "./Button";
|
|
|
8
8
|
export {default as CopyButton} from "./CopyButton";
|
|
9
9
|
export {default as Grade} from "./Grade";
|
|
10
10
|
export {default as LinkButton} from "./LinkButton";
|
|
11
|
+
export {default as ListGroup} from "./ListGroup";
|
|
11
12
|
export {default as Loader} from "./Loader";
|
|
12
13
|
export {default as Map} from "./Map";
|
|
13
14
|
export {default as MapMore} from "./MapMore";
|
|
@@ -3,6 +3,7 @@ import { panel } from "../../styles";
|
|
|
3
3
|
import { fa } from "../../../utils/widgets";
|
|
4
4
|
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
|
|
5
5
|
import PanoramaxImg from "../../../img/panoramax.svg";
|
|
6
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Legend widget, handling switch between map and photo components.
|
|
@@ -10,25 +11,39 @@ import PanoramaxImg from "../../../img/panoramax.svg";
|
|
|
10
11
|
* @class Panoramax.components.ui.widgets.Legend
|
|
11
12
|
* @element pnx-widget-legend
|
|
12
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).
|
|
13
15
|
* @example
|
|
14
16
|
* ```html
|
|
17
|
+
* <!-- Default legend -->
|
|
15
18
|
* <pnx-widget-legend
|
|
16
19
|
* _parent=${viewer}
|
|
17
20
|
* focus="map"
|
|
18
21
|
* picture="PICTURE-ID-IF-ANY"
|
|
19
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>
|
|
20
32
|
* ```
|
|
21
33
|
*/
|
|
22
34
|
export default class Legend extends LitElement {
|
|
23
35
|
/** @private */
|
|
24
36
|
static styles = [panel, css`
|
|
25
|
-
.pnx-panel
|
|
37
|
+
.pnx-panel[part="panel"] {
|
|
26
38
|
border-radius: 10px;
|
|
27
|
-
padding: 10px;
|
|
28
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;
|
|
29
46
|
width: 250px;
|
|
30
|
-
max-width: 80vh;
|
|
31
|
-
z-index: 120;
|
|
32
47
|
}
|
|
33
48
|
.presentation {
|
|
34
49
|
font-size: 0.9em;
|
|
@@ -54,7 +69,12 @@ export default class Legend extends LitElement {
|
|
|
54
69
|
};
|
|
55
70
|
|
|
56
71
|
render() {
|
|
57
|
-
|
|
72
|
+
const classes = {
|
|
73
|
+
"pnx-panel": true,
|
|
74
|
+
"pnx-padded": this.focus == "map",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return html`<div class=${classMap(classes)} part="panel">
|
|
58
78
|
<div
|
|
59
79
|
class="presentation"
|
|
60
80
|
style=${this.focus != "map" && this.picture ? "display: none": ""}
|
|
@@ -70,7 +90,10 @@ export default class Legend extends LitElement {
|
|
|
70
90
|
<pnx-picture-legend
|
|
71
91
|
._parent=${this._parent}
|
|
72
92
|
style=${this.focus == "map" ? "display: none": ""}
|
|
73
|
-
|
|
93
|
+
collapsable
|
|
94
|
+
>
|
|
95
|
+
<slot slot="editors" name="editors"></slot>
|
|
96
|
+
</pnx-picture-legend>
|
|
74
97
|
<pnx-map-legend
|
|
75
98
|
._parent=${this._parent}
|
|
76
99
|
style=${this.focus != "map" ? "display: none": ""}
|
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
// Mobile -> Geo URI
|
|
110
|
+
if(this._parent?.isWidthSmall()) {
|
|
111
|
+
return html`
|
|
112
|
+
<pnx-link-button
|
|
113
|
+
size="sm"
|
|
114
|
+
href="geo:${this._pic.gps[1]},${this._pic.gps[0]};u=3"
|
|
115
|
+
>
|
|
116
|
+
${fa(faExternalLinkAlt)} ${this._parent?._t.pnx.geo_uri}
|
|
117
|
+
</pnx-link-button>
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const idOpts = this._pic && {
|
|
122
|
+
"map": `19/${this._pic.gps[1]}/${this._pic.gps[0]}`,
|
|
123
|
+
"source": "Panoramax",
|
|
124
|
+
"photo_overlay": "panoramax",
|
|
125
|
+
"photo": `panoramax/${this._pic.id}`,
|
|
126
|
+
};
|
|
127
|
+
const idUrl = idOpts && `${ID_URL}#${new URLSearchParams(idOpts).toString()}`;
|
|
128
|
+
|
|
129
|
+
return html`
|
|
130
|
+
<pnx-link-button
|
|
131
|
+
size="sm"
|
|
132
|
+
href=${idUrl}
|
|
133
|
+
target="_blank"
|
|
134
|
+
title="${this._parent?._t.pnx.contribute_id}"
|
|
135
|
+
>
|
|
136
|
+
${fa(faLocationDot)} ${this._parent?._t.pnx.id}
|
|
137
|
+
</pnx-link-button>
|
|
138
|
+
|
|
139
|
+
<pnx-button
|
|
140
|
+
id="pnx-edit-josm"
|
|
141
|
+
size="sm"
|
|
142
|
+
active=${this._josm ? "" : nothing}
|
|
143
|
+
@click=${this._toggleJOSMLive}
|
|
144
|
+
title="${this._parent?._t.pnx.josm_live}"
|
|
145
|
+
>
|
|
146
|
+
${fa(faSatelliteDish)} ${this._parent?._t.pnx.josm}
|
|
147
|
+
</pnx-button>
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
customElements.define("pnx-widget-osmeditors", OSMEditors);
|
|
@@ -0,0 +1,131 @@
|
|
|
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
|
+
_baseUrl: {state: true},
|
|
34
|
+
_meta: { state: true },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
constructor() {
|
|
38
|
+
super();
|
|
39
|
+
this.full = false;
|
|
40
|
+
this._onUrlChange();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @private */
|
|
44
|
+
connectedCallback() {
|
|
45
|
+
super.connectedCallback();
|
|
46
|
+
|
|
47
|
+
this._parent?.onceReady().then(() => {
|
|
48
|
+
this._onUrlChange();
|
|
49
|
+
this._meta = this._parent.psv.getPictureMetadata();
|
|
50
|
+
this._parent.urlHandler.addEventListener("url-changed", this._onUrlChange.bind(this));
|
|
51
|
+
this._parent.psv.addEventListener("picture-loaded", () => {
|
|
52
|
+
this._meta = this._parent.psv.getPictureMetadata();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @private */
|
|
58
|
+
_onUrlChange() {
|
|
59
|
+
this._baseUrl = window.location.href.replace(/\/$/, "");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @private */
|
|
63
|
+
_onPrint() {
|
|
64
|
+
this._closeGroup();
|
|
65
|
+
window.print();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @private */
|
|
69
|
+
_closeGroup() {
|
|
70
|
+
this.renderRoot.querySelector("pnx-togglable-group").close();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @private */
|
|
74
|
+
_onShareClick() {
|
|
75
|
+
this._closeGroup();
|
|
76
|
+
this._parent._showShareOptions();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @private */
|
|
80
|
+
_onReportClick() {
|
|
81
|
+
this._closeGroup();
|
|
82
|
+
this._parent._showReportForm();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** @private */
|
|
86
|
+
render() {
|
|
87
|
+
const shareUrl = this._parent?.urlHandler?.nextShortLink(this._baseUrl) || this._baseUrl;
|
|
88
|
+
|
|
89
|
+
return html`<pnx-togglable-group padded="false" id="pic-legend-headline-menu" ._parent=${this._parent}>
|
|
90
|
+
<pnx-button slot="button" kind="inline">${fa(faEllipsisV)}</pnx-button>
|
|
91
|
+
<pnx-list-group class="pnx-print-hidden" @click=${this._closeMenu}>
|
|
92
|
+
${this.full ? html`
|
|
93
|
+
<a
|
|
94
|
+
download
|
|
95
|
+
target="_blank"
|
|
96
|
+
href=${this._meta?.panorama?.hdUrl}
|
|
97
|
+
@click=${this._closeGroup}
|
|
98
|
+
>${this._parent?._t.pnx.share_image}</a>
|
|
99
|
+
<pnx-copy-button ._t=${this._parent?._t} text=${shareUrl} unstyled>
|
|
100
|
+
${this._parent?._t.pnx.share_page}
|
|
101
|
+
</pnx-copy-button>
|
|
102
|
+
${this._parent.isWidthSmall() ? nothing : html`<button @click=${this._onPrint}>
|
|
103
|
+
${this._parent?._t.pnx.share_print}
|
|
104
|
+
</button>`}
|
|
105
|
+
${this._parent?.api?.getRSSURL() && html`
|
|
106
|
+
<a
|
|
107
|
+
target="_blank"
|
|
108
|
+
href=${this._parent?.api.getRSSURL(this._parent?.map?.getBounds?.())}
|
|
109
|
+
title=${this._parent?._t.pnx.share_rss_title}
|
|
110
|
+
@click=${this._closeGroup}
|
|
111
|
+
>
|
|
112
|
+
${this._parent?._t.pnx.share_rss}
|
|
113
|
+
</a>
|
|
114
|
+
`}
|
|
115
|
+
` : html`
|
|
116
|
+
<button @click=${this._onReportClick}>
|
|
117
|
+
${this._parent?._t.pnx.report}
|
|
118
|
+
</button>
|
|
119
|
+
<button @click=${this._onShareClick}>
|
|
120
|
+
${this._parent?._t.pnx.share}
|
|
121
|
+
</button>
|
|
122
|
+
${this._meta ? html`<pnx-copy-button ._t=${this._parent?._t} text=${this._meta.id} unstyled>
|
|
123
|
+
${this._parent?._t.pnx.metadata_general_copy_picid}
|
|
124
|
+
</pnx-copy-button>` : nothing}
|
|
125
|
+
` }
|
|
126
|
+
</pnx-list-group>
|
|
127
|
+
</pnx-togglable-group>`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
customElements.define("pnx-picture-legend-actions", PictureLegendActions);
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* @module Panoramax:components:ui:widgets
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export {default as Zoom} from "./Zoom";
|
|
7
|
-
export {default as Player} from "./Player";
|
|
8
|
-
export {default as Share} from "./Share";
|
|
9
6
|
export {default as GeoSearch} from "./GeoSearch";
|
|
7
|
+
export {default as Legend} from "./Legend";
|
|
10
8
|
export {default as MapFiltersButton} from "./MapFiltersButton";
|
|
11
9
|
export {default as MapLayersButton} from "./MapLayersButton";
|
|
12
|
-
export {default as
|
|
10
|
+
export {default as OSMEditors} from "./OSMEditors";
|
|
11
|
+
export {default as PictureLegendActions} from "./PictureLegendActions";
|
|
12
|
+
export {default as Player} from "./Player";
|
|
13
|
+
export {default as Zoom} from "./Zoom";
|
package/src/translations/en.json
CHANGED
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
"sequence_speed": "Player speed",
|
|
53
53
|
"legend_license": "License: {l}",
|
|
54
54
|
"legend_title": "Show details of picture",
|
|
55
|
-
"edit_osm": "Edit OSM",
|
|
56
55
|
"id": "iD",
|
|
56
|
+
"contribute_id": "Contribute to OpenStreetMap with iD editor",
|
|
57
|
+
"geo_uri": "External app",
|
|
57
58
|
"josm": "JOSM",
|
|
58
59
|
"josm_live": "Enable JOSM automatic sync on picture loading",
|
|
59
60
|
"loading_labels_serious": [
|
|
@@ -102,6 +103,8 @@
|
|
|
102
103
|
"filter_zoom_in": "Zoom-in to see this filter",
|
|
103
104
|
"picture_flat": "Classic",
|
|
104
105
|
"picture_360": "360°",
|
|
106
|
+
"picture_flat_long": "Classic picture",
|
|
107
|
+
"picture_360_long": "Panoramic picture",
|
|
105
108
|
"filter_qualityscore": "Quality score",
|
|
106
109
|
"filter_qualityscore_help": "Click to enable or disable",
|
|
107
110
|
"qualityscore_title": "About the quality score",
|
|
@@ -123,8 +126,11 @@
|
|
|
123
126
|
"map_theme_score": "Quality score",
|
|
124
127
|
"contrast": "Enable higher image contrast",
|
|
125
128
|
"metadata": "Picture metadata",
|
|
126
|
-
"
|
|
127
|
-
"
|
|
129
|
+
"metadata_summary": "Summary",
|
|
130
|
+
"metadata_general_copy_id": "Copy ID",
|
|
131
|
+
"metadata_general_copy_picid": "Copy picture ID",
|
|
132
|
+
"metadata_general_picid": "Picture",
|
|
133
|
+
"metadata_general_seqid": "Sequence",
|
|
128
134
|
"metadata_general_picid_link": "Go to JSON description of the picture",
|
|
129
135
|
"metadata_general_seqid_link": "Go to JSON description of the sequence",
|
|
130
136
|
"metadata_general_author": "Author",
|
|
@@ -137,21 +143,21 @@
|
|
|
137
143
|
"metadata_camera_type": "Type",
|
|
138
144
|
"metadata_camera_resolution": "Resolution",
|
|
139
145
|
"metadata_camera_focal_length": "Focal length",
|
|
140
|
-
"metadata_location": "
|
|
146
|
+
"metadata_location": "Position",
|
|
141
147
|
"metadata_location_longitude": "Longitude",
|
|
142
148
|
"metadata_location_latitude": "Latitude",
|
|
143
|
-
"metadata_location_orientation": "
|
|
149
|
+
"metadata_location_orientation": "Direction",
|
|
144
150
|
"metadata_location_precision": "Positioning precision",
|
|
145
|
-
"metadata_quality": "Quality
|
|
151
|
+
"metadata_quality": "Quality",
|
|
146
152
|
"metadata_quality_help": "Know more about Quality Score",
|
|
147
153
|
"metadata_quality_score": "Global score",
|
|
148
154
|
"metadata_quality_gps_score": "Positioning score",
|
|
149
155
|
"metadata_quality_resolution_score": "Resolution score",
|
|
150
156
|
"metadata_quality_missing": "no value set in picture",
|
|
151
|
-
"metadata_exif": "EXIF
|
|
157
|
+
"metadata_exif": "EXIF",
|
|
152
158
|
"metadata_exif_name": "Tag",
|
|
153
159
|
"metadata_exif_value": "Value",
|
|
154
|
-
"report": "Report
|
|
160
|
+
"report": "Report",
|
|
155
161
|
"report_auth": "This report will be sent using your account \"{a}\"",
|
|
156
162
|
"report_nature_label": "Nature of the issue",
|
|
157
163
|
"report_nature": {
|
package/src/translations/fr.json
CHANGED
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
"sequence_speed": "Vitesse de lecture",
|
|
53
53
|
"legend_license": "Licence : {l}",
|
|
54
54
|
"legend_title": "Afficher les détails de l'image",
|
|
55
|
-
"edit_osm": "Contribuer sur OSM",
|
|
56
55
|
"id": "iD",
|
|
56
|
+
"contribute_id": "Contribuez à OpenStreetMap avec l'éditeur iD",
|
|
57
|
+
"geo_uri": "App externe",
|
|
57
58
|
"josm": "JOSM",
|
|
58
59
|
"josm_live": "Active la synchronisation automatique de JOSM lors du chargement d'une photo",
|
|
59
60
|
"loading_labels_serious": [
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"filter_picture": "Type d'image",
|
|
102
103
|
"picture_flat": "Classique",
|
|
103
104
|
"picture_360": "360°",
|
|
105
|
+
"picture_flat_long": "Photo classique",
|
|
106
|
+
"picture_360_long": "Photo panoramique",
|
|
104
107
|
"filter_qualityscore": "Score de qualité",
|
|
105
108
|
"filter_qualityscore_help": "Cliquez pour activer ou désactiver",
|
|
106
109
|
"qualityscore_title": "À propos du score qualité",
|
|
@@ -123,8 +126,11 @@
|
|
|
123
126
|
"map_theme_score": "Score de qualité",
|
|
124
127
|
"contrast": "Augmenter le contraste de l'image",
|
|
125
128
|
"metadata": "Métadonnées de la photo",
|
|
126
|
-
"
|
|
127
|
-
"
|
|
129
|
+
"metadata_summary": "Résumé",
|
|
130
|
+
"metadata_general_copy_id": "Copier l'ID",
|
|
131
|
+
"metadata_general_copy_picid": "Copier l'ID de photo",
|
|
132
|
+
"metadata_general_picid": "Photo",
|
|
133
|
+
"metadata_general_seqid": "Séquence",
|
|
128
134
|
"metadata_general_picid_link": "Aller au descriptif JSON de la photo",
|
|
129
135
|
"metadata_general_seqid_link": "Aller au descriptif JSON de la séquence",
|
|
130
136
|
"metadata_general_author": "Auteur",
|
|
@@ -137,21 +143,21 @@
|
|
|
137
143
|
"metadata_camera_type": "Type",
|
|
138
144
|
"metadata_camera_resolution": "Résolution",
|
|
139
145
|
"metadata_camera_focal_length": "Longueur focale",
|
|
140
|
-
"metadata_location": "
|
|
146
|
+
"metadata_location": "Position",
|
|
141
147
|
"metadata_location_longitude": "Longitude",
|
|
142
148
|
"metadata_location_latitude": "Latitude",
|
|
143
|
-
"metadata_location_orientation": "Direction
|
|
149
|
+
"metadata_location_orientation": "Direction",
|
|
144
150
|
"metadata_location_precision": "Précision du positionnement",
|
|
145
|
-
"metadata_quality": "
|
|
151
|
+
"metadata_quality": "Qualité",
|
|
146
152
|
"metadata_quality_help": "En savoir plus sur le score de qualité",
|
|
147
153
|
"metadata_quality_score": "Note globale",
|
|
148
154
|
"metadata_quality_gps_score": "Note du positionnement",
|
|
149
155
|
"metadata_quality_resolution_score": "Note de la résolution",
|
|
150
156
|
"metadata_quality_missing": "pas d'info dans l'image",
|
|
151
|
-
"metadata_exif": "EXIF
|
|
157
|
+
"metadata_exif": "EXIF",
|
|
152
158
|
"metadata_exif_name": "Balise",
|
|
153
159
|
"metadata_exif_value": "Valeur",
|
|
154
|
-
"report": "Signaler
|
|
160
|
+
"report": "Signaler",
|
|
155
161
|
"report_auth": "Ce signalement sera envoyé en utilisant votre compte \"{a}\"",
|
|
156
162
|
"report_nature_label": "Nature du problème",
|
|
157
163
|
"report_nature": {
|
|
@@ -376,7 +376,8 @@ export function alterViewerState(viewer, params) {
|
|
|
376
376
|
// Restore selected picture
|
|
377
377
|
let pic = params.picture || params.pic;
|
|
378
378
|
if(pic && params.focus && params.focus == "meta") {
|
|
379
|
-
|
|
379
|
+
// TODO open expanded legend
|
|
380
|
+
//viewer.psv.addEventListener("picture-loaded", () => viewer._showPictureMetadata(), { once: true });
|
|
380
381
|
}
|
|
381
382
|
|
|
382
383
|
// Change focus
|
package/src/utils/geocoder.js
CHANGED
|
@@ -57,7 +57,9 @@ function nominatimAddressToPlaceName(addr) {
|
|
|
57
57
|
// Zone Indus-like
|
|
58
58
|
"farm", "farmyard", "industrial", "commercial", "retail", "city_block", "residential",
|
|
59
59
|
// Quarter-like
|
|
60
|
-
"neighbourhood", "allotments", "quarter"
|
|
60
|
+
"neighbourhood", "allotments", "quarter",
|
|
61
|
+
// Fallback to road if nothing else found
|
|
62
|
+
"road"
|
|
61
63
|
];
|
|
62
64
|
for(let pn of potentialNames) {
|
|
63
65
|
if(addr[pn]) {
|