ogm-viewer 0.4.0 → 0.5.1
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/dist/cjs/{lerc-CT61sKYw.js → lerc-IU-tWkVO.js} +6 -6
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-DKxSOrMP.js → ogm-alerts.ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-preview.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-BAGJpqMB.js} +465 -98
- package/dist/cjs/ogm-alerts_11.cjs.entry.js +18 -0
- package/dist/cjs/ogm-viewer.cjs.js +1 -1
- package/dist/collection/assets/icons/exclamation-triangle-fill.svg +3 -0
- package/dist/collection/collection-manifest.json +2 -0
- package/dist/collection/components/ogm-alerts/ogm-alerts.css +51 -0
- package/dist/collection/components/ogm-alerts/ogm-alerts.js +71 -0
- package/dist/collection/components/ogm-alerts/ogm-alerts.test.js +26 -0
- package/dist/collection/components/ogm-image/ogm-image.js +57 -5
- package/dist/collection/components/ogm-map/ogm-map.css +34 -40
- package/dist/collection/components/ogm-map/ogm-map.js +86 -22
- package/dist/collection/components/ogm-menubar/ogm-menubar.js +23 -2
- package/dist/collection/components/ogm-menubar/ogm-menubar.test.js +55 -0
- package/dist/collection/components/ogm-preview/ogm-preview.css +16 -0
- package/dist/collection/components/ogm-preview/ogm-preview.js +144 -0
- package/dist/collection/components/ogm-preview/ogm-preview.test.js +37 -0
- package/dist/collection/components/ogm-previews/ogm-previews.css +3 -2
- package/dist/collection/components/ogm-previews/ogm-previews.js +7 -18
- package/dist/collection/components/ogm-previews/ogm-previews.test.js +83 -0
- package/dist/collection/components/ogm-settings/ogm-settings.js +1 -1
- package/dist/collection/components/ogm-sidebar/ogm-sidebar.js +2 -2
- package/dist/collection/components/ogm-viewer/ogm-viewer.css +6 -2
- package/dist/collection/components/ogm-viewer/ogm-viewer.js +61 -29
- package/dist/collection/lib/errors.js +137 -0
- package/dist/collection/lib/errors.test.js +96 -0
- package/dist/collection/lib/sources/geojson.js +2 -1
- package/dist/collection/lib/sources/iiif-manifest.js +2 -3
- package/dist/collection/lib/sources/iiif-manifest.test.js +4 -4
- package/dist/esm/{lerc-Bz409klg.js → lerc-yC3LNu-h.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-C9zV3wMe.js → ogm-alerts.ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-preview.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-BpVupgSB.js} +465 -100
- package/dist/esm/ogm-alerts_11.entry.js +2 -0
- package/dist/esm/ogm-viewer.js +1 -1
- package/dist/ogm-viewer/assets/icons/exclamation-triangle-fill.svg +3 -0
- package/dist/ogm-viewer/ogm-viewer.esm.js +1 -1
- package/dist/ogm-viewer/p-11cf948e.entry.js +1 -0
- package/dist/ogm-viewer/p-DPOGJxir.js +2822 -0
- package/dist/ogm-viewer/{p-BrovdLv6.js → p-_eTjrSO2.js} +1 -1
- package/dist/types/components/ogm-alerts/ogm-alerts.d.ts +6 -0
- package/dist/types/components/ogm-alerts/ogm-alerts.test.d.ts +1 -0
- package/dist/types/components/ogm-image/ogm-image.d.ts +5 -0
- package/dist/types/components/ogm-map/ogm-map.d.ts +7 -0
- package/dist/types/components/ogm-menubar/ogm-menubar.d.ts +2 -1
- package/dist/types/components/ogm-preview/ogm-preview.d.ts +13 -0
- package/dist/types/components/ogm-preview/ogm-preview.test.d.ts +1 -0
- package/dist/types/components/ogm-previews/ogm-previews.d.ts +1 -5
- package/dist/types/components/ogm-previews/ogm-previews.test.d.ts +1 -0
- package/dist/types/components/ogm-viewer/ogm-viewer.d.ts +8 -2
- package/dist/types/components.d.ts +70 -0
- package/dist/types/lib/errors.d.ts +13 -0
- package/dist/types/lib/errors.test.d.ts +1 -0
- package/dist/types/lib/sources/source.d.ts +1 -1
- package/package.json +1 -1
- package/readme.md +1 -0
- package/dist/cjs/ogm-attributes_9.cjs.entry.js +0 -16
- package/dist/esm/ogm-attributes_9.entry.js +0 -2
- package/dist/ogm-viewer/p-86b8fafc.entry.js +0 -1
- package/dist/ogm-viewer/p-CpCT3zlD.js +0 -2750
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry = require('./ogm-alerts.ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-preview.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-BAGJpqMB.js');
|
|
4
|
+
require('./index-mu9UK_Fb.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.ogm_alerts = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmAlerts;
|
|
9
|
+
exports.ogm_attributes = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmAttributes;
|
|
10
|
+
exports.ogm_image = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmImage;
|
|
11
|
+
exports.ogm_map = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmMap;
|
|
12
|
+
exports.ogm_menubar = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmMenubar;
|
|
13
|
+
exports.ogm_metadata = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmMetadata;
|
|
14
|
+
exports.ogm_preview = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmPreview;
|
|
15
|
+
exports.ogm_previews = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmPreviews;
|
|
16
|
+
exports.ogm_settings = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmSettings;
|
|
17
|
+
exports.ogm_sidebar = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmSidebar;
|
|
18
|
+
exports.ogm_viewer = ogmAlerts_ogmAttributes_ogmImage_ogmMap_ogmMenubar_ogmMetadata_ogmPreview_ogmPreviews_ogmSettings_ogmSidebar_ogmViewer_entry.OgmViewer;
|
|
@@ -19,7 +19,7 @@ var patchBrowser = () => {
|
|
|
19
19
|
|
|
20
20
|
patchBrowser().then(async (options) => {
|
|
21
21
|
await appGlobals.globalScripts();
|
|
22
|
-
return index.bootstrapLazy([["ogm-
|
|
22
|
+
return index.bootstrapLazy([["ogm-alerts_11.cjs",[[513,"ogm-viewer",{"recordUrl":[1,"record-url"],"theme":[1],"hideTitle":[4,"hide-title"],"record":[32],"error":[32],"previewOpacity":[32],"sidebarOpen":[32],"loading":[32],"loadRecord":[64]},[[0,"sidebarToggled","toggleSidebar"],[0,"opacityChange","adjustPreviewOpacity"],[0,"mapLoading","setLoadingStarted"],[0,"imageLoading","setLoadingStarted"],[0,"mapIdle","setLoadingFinished"],[0,"imageLoaded","setLoadingFinished"]],{"recordUrl":[{"updateRecord":0}],"record":[{"resetLoading":0}]}],[513,"ogm-previews",{"theme":[1],"record":[16],"previewOpacity":[2,"preview-opacity"],"sidebarPadding":[2,"sidebar-padding"],"sources":[32]},null,{"record":[{"getSources":0}]}],[513,"ogm-sidebar",{"record":[16],"theme":[1],"open":[4]}],[513,"ogm-menubar",{"record":[16],"theme":[1],"loading":[4],"hideTitle":[4,"hide-title"]}],[513,"ogm-preview",{"theme":[1],"source":[16],"previewOpacity":[2,"preview-opacity"],"sidebarPadding":[2,"sidebar-padding"],"error":[32]},[[0,"previewError","handlePreviewError"]],{"source":[{"resetError":0}]}],[513,"ogm-metadata",{"record":[16],"theme":[1],"fieldNames":[16],"filteredRecord":[32]}],[513,"ogm-settings",{"record":[16]},[[0,"input","handleOpacityChange"]]],[513,"ogm-map",{"source":[16],"theme":[1],"padding":[2],"easeMapTo":[64]},[[16,"featureSelected","handleFeatureSelected"]],{"source":[{"previewSource":0}],"theme":[{"onThemeChange":0}],"padding":[{"onPaddingChange":0}]}],[513,"ogm-alerts",{"theme":[1],"error":[16]}],[513,"ogm-image",{"source":[16],"theme":[1],"padding":[2]},null,{"source":[{"onSourceChange":0}],"padding":[{"onPaddingChange":0}]}],[513,"ogm-attributes",{"features":[16],"currentIndex":[32]},null,{"features":[{"onFeaturesChange":0}],"currentIndex":[{"onCurrentIndexChange":0}]}]]]], options);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
exports.setNonce = index.setNonce;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle-fill" viewBox="0 0 16 16">
|
|
2
|
+
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5m.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2"/>
|
|
3
|
+
</svg>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"entries": [
|
|
3
|
+
"components/ogm-alerts/ogm-alerts.js",
|
|
3
4
|
"components/ogm-attributes/ogm-attributes.js",
|
|
4
5
|
"components/ogm-image/ogm-image.js",
|
|
5
6
|
"components/ogm-map/ogm-map.js",
|
|
6
7
|
"components/ogm-menubar/ogm-menubar.js",
|
|
7
8
|
"components/ogm-metadata/ogm-metadata.js",
|
|
9
|
+
"components/ogm-preview/ogm-preview.js",
|
|
8
10
|
"components/ogm-previews/ogm-previews.js",
|
|
9
11
|
"components/ogm-settings/ogm-settings.js",
|
|
10
12
|
"components/ogm-sidebar/ogm-sidebar.js",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* Fill the space left by the preview it replaces and center the error within it */
|
|
2
|
+
:host {
|
|
3
|
+
display: flex;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
place-items: center;
|
|
7
|
+
place-content: center;
|
|
8
|
+
background: var(--wa-color-surface-default);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.alerts {
|
|
12
|
+
padding: var(--wa-space-m);
|
|
13
|
+
max-width: 40rem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.alert {
|
|
17
|
+
box-shadow: var(--wa-shadow-m);
|
|
18
|
+
align-items: start;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.alert::part(message) {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: start;
|
|
24
|
+
gap: var(--wa-space-s);
|
|
25
|
+
width: 100%;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.content {
|
|
29
|
+
flex: auto;
|
|
30
|
+
min-width: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.title {
|
|
34
|
+
display: block;
|
|
35
|
+
font-weight: var(--wa-font-weight-bold);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.message {
|
|
39
|
+
margin-top: var(--wa-space-3xs);
|
|
40
|
+
font-size: var(--wa-font-size-s);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.url {
|
|
44
|
+
margin-top: var(--wa-space-2xs);
|
|
45
|
+
font-family: var(--wa-font-family-code);
|
|
46
|
+
font-size: var(--wa-font-size-xs);
|
|
47
|
+
color: var(--wa-color-text-quiet);
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
text-overflow: ellipsis;
|
|
50
|
+
white-space: nowrap;
|
|
51
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
|
+
// Renders a single preview error, centered and filling its container. Used in place of a failed
|
|
3
|
+
// preview (inside <ogm-preview>) or in place of the previews entirely (when the record fails to load).
|
|
4
|
+
export class OgmAlerts {
|
|
5
|
+
theme;
|
|
6
|
+
error;
|
|
7
|
+
render() {
|
|
8
|
+
if (!this.error)
|
|
9
|
+
return null;
|
|
10
|
+
return (h(Host, { class: this.theme && `wa-${this.theme}` }, h("div", { class: "alerts", role: "alert", "aria-live": "assertive" }, h("wa-callout", { variant: "danger", appearance: "filled-outlined", class: "alert" }, h("wa-icon", { slot: "icon", name: "exclamation-triangle-fill", canvas: "auto" }), h("div", { class: "content" }, h("strong", { class: "title" }, this.error.title), h("div", { class: "message" }, this.error.message), this.error.url && (h("div", { class: "url", title: this.error.url }, this.error.url)))))));
|
|
11
|
+
}
|
|
12
|
+
static get is() { return "ogm-alerts"; }
|
|
13
|
+
static get encapsulation() { return "shadow"; }
|
|
14
|
+
static get originalStyleUrls() {
|
|
15
|
+
return {
|
|
16
|
+
"$": ["ogm-alerts.css"]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
static get styleUrls() {
|
|
20
|
+
return {
|
|
21
|
+
"$": ["ogm-alerts.css"]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
static get properties() {
|
|
25
|
+
return {
|
|
26
|
+
"theme": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"mutable": false,
|
|
29
|
+
"complexType": {
|
|
30
|
+
"original": "'light' | 'dark'",
|
|
31
|
+
"resolved": "\"dark\" | \"light\"",
|
|
32
|
+
"references": {}
|
|
33
|
+
},
|
|
34
|
+
"required": false,
|
|
35
|
+
"optional": false,
|
|
36
|
+
"docs": {
|
|
37
|
+
"tags": [],
|
|
38
|
+
"text": ""
|
|
39
|
+
},
|
|
40
|
+
"getter": false,
|
|
41
|
+
"setter": false,
|
|
42
|
+
"reflect": false,
|
|
43
|
+
"attribute": "theme"
|
|
44
|
+
},
|
|
45
|
+
"error": {
|
|
46
|
+
"type": "unknown",
|
|
47
|
+
"mutable": false,
|
|
48
|
+
"complexType": {
|
|
49
|
+
"original": "PreviewError",
|
|
50
|
+
"resolved": "PreviewError",
|
|
51
|
+
"references": {
|
|
52
|
+
"PreviewError": {
|
|
53
|
+
"location": "import",
|
|
54
|
+
"path": "../../lib/errors",
|
|
55
|
+
"id": "src/lib/errors.ts::PreviewError",
|
|
56
|
+
"referenceLocation": "PreviewError"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"required": false,
|
|
61
|
+
"optional": true,
|
|
62
|
+
"docs": {
|
|
63
|
+
"tags": [],
|
|
64
|
+
"text": ""
|
|
65
|
+
},
|
|
66
|
+
"getter": false,
|
|
67
|
+
"setter": false
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { render, describe, it, expect, h } from "@stencil/vitest";
|
|
2
|
+
import { referenceError } from "../../lib/errors";
|
|
3
|
+
// Mock a network failure on load
|
|
4
|
+
const makeError = (url) => referenceError(new TypeError('Failed to fetch'), 'GeoJSON', url);
|
|
5
|
+
describe('ogm-alerts', () => {
|
|
6
|
+
it('renders nothing when there is no error', async () => {
|
|
7
|
+
const { root } = await render(h("ogm-alerts", null));
|
|
8
|
+
const shadowRoot = root.shadowRoot;
|
|
9
|
+
expect(shadowRoot.querySelector('.alerts')).toBeNull();
|
|
10
|
+
});
|
|
11
|
+
it('renders a danger callout with the error title, message, and url', async () => {
|
|
12
|
+
const { root } = await render(h("ogm-alerts", { error: makeError('http://example.com/data.json') }));
|
|
13
|
+
const shadowRoot = root.shadowRoot;
|
|
14
|
+
const callout = shadowRoot.querySelector('wa-callout');
|
|
15
|
+
expect(callout).not.toBeNull();
|
|
16
|
+
expect(callout.getAttribute('variant')).toBe('danger');
|
|
17
|
+
expect(callout.textContent).toContain('GeoJSON');
|
|
18
|
+
expect(callout.textContent).toContain('CORS');
|
|
19
|
+
expect(callout.textContent).toContain('http://example.com/data.json');
|
|
20
|
+
});
|
|
21
|
+
it('omits the url line when the error has no url', async () => {
|
|
22
|
+
const { root } = await render(h("ogm-alerts", { error: makeError() }));
|
|
23
|
+
const shadowRoot = root.shadowRoot;
|
|
24
|
+
expect(shadowRoot.querySelector('.url')).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
2
|
import { Viewer } from "openseadragon";
|
|
3
3
|
import { getElement, findElement } from "../../lib/elements";
|
|
4
|
+
import { referenceError } from "../../lib/errors";
|
|
4
5
|
export class OgmImage {
|
|
5
6
|
el;
|
|
6
7
|
source;
|
|
@@ -8,8 +9,11 @@ export class OgmImage {
|
|
|
8
9
|
padding = 0;
|
|
9
10
|
imageLoaded;
|
|
10
11
|
imageLoading;
|
|
12
|
+
previewError;
|
|
11
13
|
// OpenSeadragon viewer instance
|
|
12
14
|
viewer;
|
|
15
|
+
// Guards against reporting more than one error per load attempt
|
|
16
|
+
errorReported = false;
|
|
13
17
|
// Set up OpenSeadragon viewer on load
|
|
14
18
|
async componentDidLoad() {
|
|
15
19
|
this.viewer = new Viewer({
|
|
@@ -26,10 +30,21 @@ export class OgmImage {
|
|
|
26
30
|
nextButton: getElement(this.el, '.next'),
|
|
27
31
|
previousButton: getElement(this.el, '.prev'),
|
|
28
32
|
});
|
|
33
|
+
// Clear loading state whether we succeeded or failed
|
|
29
34
|
this.viewer.addHandler('open', () => this.imageLoaded.emit());
|
|
35
|
+
// Surface OpenSeaDragon decode errors here
|
|
36
|
+
this.viewer.addHandler('open-failed', event => {
|
|
37
|
+
this.imageLoaded.emit();
|
|
38
|
+
this.reportError(new Error(event.message));
|
|
39
|
+
});
|
|
40
|
+
// If we do have a source, load the images
|
|
30
41
|
if (this.source)
|
|
31
42
|
await this.loadImages();
|
|
32
43
|
}
|
|
44
|
+
// Destroy the viewer when we are removed from the DOM
|
|
45
|
+
disconnectedCallback() {
|
|
46
|
+
this.viewer?.destroy();
|
|
47
|
+
}
|
|
33
48
|
// Update preview when source changes
|
|
34
49
|
async onSourceChange() {
|
|
35
50
|
if (this.source)
|
|
@@ -46,14 +61,29 @@ export class OgmImage {
|
|
|
46
61
|
// Get all of the IIIF image URLs and send them to OpenSeadragon
|
|
47
62
|
// This makes a request to fetch and cache the manifest
|
|
48
63
|
async loadImages() {
|
|
64
|
+
this.errorReported = false;
|
|
49
65
|
this.imageLoading.emit();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
try {
|
|
67
|
+
const images = await this.source.getIIIFImageUrls();
|
|
68
|
+
if (!images)
|
|
69
|
+
throw new Error('No IIIF images found for source');
|
|
70
|
+
this.viewer.open(images);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error(`Error loading IIIF images for ${this.source.url}:`, error);
|
|
74
|
+
this.imageLoaded.emit();
|
|
75
|
+
this.reportError(error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Emit a single preview error per load attempt
|
|
79
|
+
reportError(error) {
|
|
80
|
+
if (this.errorReported || !this.source)
|
|
81
|
+
return;
|
|
82
|
+
this.errorReported = true;
|
|
83
|
+
this.previewError.emit(referenceError(error, this.source.label(), this.source.url));
|
|
54
84
|
}
|
|
55
85
|
render() {
|
|
56
|
-
return (h(Host, { key: '
|
|
86
|
+
return (h(Host, { key: 'ebbebaddac72024a3b311e0e0e501267a83d1e95' }, h("div", { key: '4f171256535cfd11430e2269fda389ffae3cedae', id: "openseadragon" }, h("div", { key: 'c308186a13fd6b8e0b1fadbf1fd1e6924631f9d6', class: "controls" }, h("wa-button", { key: '1f9e0c4c6d881bf09d7ceb160f470992d71ebe07', class: "zoom-in", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: 'cbacb0a388de2c7f349e25172027874a0224a678', name: "zoom-in", label: "Zoom In", canvas: "auto" })), h("wa-button", { key: 'dd8d7e9c5584b124ae105b2187100964f5e3a02a', class: "zoom-out", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: '2b5acf2e07c99df9556692bf534bb3847506e4d4', name: "zoom-out", label: "Zoom Out", canvas: "auto" })), h("wa-button", { key: '5534a5c77ea20a1f77544e5acd99d4247dd3d287', class: "home", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: 'faadb8ea57bf1b831b292eaf66bcea39b7e215d1', name: "house", label: "Reset View", canvas: "auto" })), h("wa-button", { key: '8979cf58a94da89e0e2d132a92fe45323f07de01', class: "full-page", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: '12cb3224e7f14258376c1c0bf6ffc5abda5c2252', name: "arrows-fullscreen", label: "Full Screen", canvas: "auto" })), h("wa-button", { key: 'e79c37f27ff14d5c4991ff30ff88aada467214ec', class: "next", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: 'ee10870ace583257393c53ba12b73ab3b015371b', name: "arrow-right", label: "Next", canvas: "auto" })), h("wa-button", { key: '9d8999e199b7b6338261eb16a655d2199520cf22', class: "prev", size: "s", appearance: "filled-outlined", pill: true }, h("wa-icon", { key: 'fde1a9022b9e5f90e269c75ce87943808031e021', name: "arrow-left", label: "Previous", canvas: "auto" }))))));
|
|
57
87
|
}
|
|
58
88
|
static get is() { return "ogm-image"; }
|
|
59
89
|
static get encapsulation() { return "shadow"; }
|
|
@@ -163,6 +193,28 @@ export class OgmImage {
|
|
|
163
193
|
"resolved": "void",
|
|
164
194
|
"references": {}
|
|
165
195
|
}
|
|
196
|
+
}, {
|
|
197
|
+
"method": "previewError",
|
|
198
|
+
"name": "previewError",
|
|
199
|
+
"bubbles": true,
|
|
200
|
+
"cancelable": true,
|
|
201
|
+
"composed": true,
|
|
202
|
+
"docs": {
|
|
203
|
+
"tags": [],
|
|
204
|
+
"text": ""
|
|
205
|
+
},
|
|
206
|
+
"complexType": {
|
|
207
|
+
"original": "PreviewError",
|
|
208
|
+
"resolved": "PreviewError",
|
|
209
|
+
"references": {
|
|
210
|
+
"PreviewError": {
|
|
211
|
+
"location": "import",
|
|
212
|
+
"path": "../../lib/errors",
|
|
213
|
+
"id": "src/lib/errors.ts::PreviewError",
|
|
214
|
+
"referenceLocation": "PreviewError"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
166
218
|
}];
|
|
167
219
|
}
|
|
168
220
|
static get elementRef() { return "el"; }
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
position: relative;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/* Color of the map background ("space" around the globe) */
|
|
10
|
+
.maplibregl-canvas {
|
|
11
|
+
background-color: var(--wa-color-surface-default);
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
/* Inspection popups. Vertical scrolling (when content is too tall) is handled by the
|
|
10
15
|
<wa-scroller> inside ogm-attributes, not here - that's what gives it the fading shadow cue. */
|
|
11
16
|
.maplibregl-popup-content {
|
|
@@ -14,6 +19,34 @@
|
|
|
14
19
|
padding: 0;
|
|
15
20
|
box-shadow: var(--wa-shadow-l);
|
|
16
21
|
border: var(--wa-panel-border-width) solid var(--wa-color-surface-border);
|
|
22
|
+
color: var(--wa-color-text-normal);
|
|
23
|
+
background-color: var(--wa-color-surface-default);
|
|
24
|
+
|
|
25
|
+
.maplibregl-popup-close-button {
|
|
26
|
+
background-color: var(--wa-color-surface-default);
|
|
27
|
+
border-radius: 10px;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Popup tip (the little triangle) */
|
|
32
|
+
.maplibregl-popup-anchor-right .maplibregl-popup-tip {
|
|
33
|
+
border-left-color: var(--wa-color-surface-border);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.maplibregl-popup-anchor-left .maplibregl-popup-tip {
|
|
37
|
+
border-right-color: var(--wa-color-surface-border);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
|
|
41
|
+
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip,
|
|
42
|
+
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip {
|
|
43
|
+
border-top-color: var(--wa-color-surface-border);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.maplibregl-popup-anchor-top .maplibregl-popup-tip,
|
|
47
|
+
.maplibregl-popup-anchor-top-right .maplibregl-popup-tip,
|
|
48
|
+
.maplibregl-popup-anchor-top-left .maplibregl-popup-tip {
|
|
49
|
+
border-bottom-color: var(--wa-color-surface-border);
|
|
17
50
|
}
|
|
18
51
|
|
|
19
52
|
/* Dark mode map adjustments */
|
|
@@ -22,10 +55,6 @@
|
|
|
22
55
|
stroke: white;
|
|
23
56
|
}
|
|
24
57
|
|
|
25
|
-
.maplibregl-canvas {
|
|
26
|
-
background-color: black;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
58
|
.maplibregl-ctrl.maplibregl-ctrl-group {
|
|
30
59
|
filter: invert(1);
|
|
31
60
|
}
|
|
@@ -34,43 +63,8 @@
|
|
|
34
63
|
.maplibregl-ctrl-group button:focus:focus-visible {
|
|
35
64
|
box-shadow: 0 0 2px 2px #ff6900;
|
|
36
65
|
}
|
|
66
|
+
|
|
37
67
|
.maplibregl-ctrl button.maplibregl-ctrl-globe-enabled .maplibregl-ctrl-icon {
|
|
38
68
|
filter: invert(1);
|
|
39
69
|
}
|
|
40
|
-
|
|
41
|
-
details.maplibregl-ctrl.maplibregl-ctrl-attrib {
|
|
42
|
-
background-color: black;
|
|
43
|
-
color: #999;
|
|
44
|
-
}
|
|
45
|
-
details.maplibregl-ctrl.maplibregl-ctrl-attrib a {
|
|
46
|
-
color: #999;
|
|
47
|
-
}
|
|
48
|
-
details.maplibregl-ctrl.maplibregl-ctrl-attrib.maplibregl-compact-show .maplibregl-ctrl-attrib-button {
|
|
49
|
-
background-color: #999;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
div.maplibregl-popup-content {
|
|
53
|
-
background-color: black;
|
|
54
|
-
color: #ccc;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
div.maplibregl-popup-anchor-right div.maplibregl-popup-tip {
|
|
58
|
-
border-left-color: black;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
div.maplibregl-popup-anchor-left div.maplibregl-popup-tip {
|
|
62
|
-
border-right-color: black;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
div.maplibregl-popup-anchor-bottom div.maplibregl-popup-tip,
|
|
66
|
-
div.maplibregl-popup-anchor-bottom-right div.maplibregl-popup-tip,
|
|
67
|
-
div.maplibregl-popup-anchor-bottom-left div.maplibregl-popup-tip {
|
|
68
|
-
border-top-color: black;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
div.maplibregl-popup-anchor-top div.maplibregl-popup-tip,
|
|
72
|
-
div.maplibregl-popup-anchor-top-right div.maplibregl-popup-tip,
|
|
73
|
-
div.maplibregl-popup-anchor-top-left div.maplibregl-popup-tip {
|
|
74
|
-
border-bottom-color: black;
|
|
75
|
-
}
|
|
76
70
|
}
|
|
@@ -8,6 +8,7 @@ import PMTilesSource from "../../lib/sources/pmtiles";
|
|
|
8
8
|
import RasterSource from "../../lib/sources/raster";
|
|
9
9
|
import WmsSource from "../../lib/sources/wms";
|
|
10
10
|
import { getElement } from "../../lib/elements";
|
|
11
|
+
import { referenceError } from "../../lib/errors";
|
|
11
12
|
import CogPreviewer from "../../lib/previewers/cog";
|
|
12
13
|
import GeoJSONPreviewer from "../../lib/previewers/geojson";
|
|
13
14
|
import OpenIndexMapPreviewer from "../../lib/previewers/openindexmap";
|
|
@@ -26,6 +27,9 @@ export class OgmMap {
|
|
|
26
27
|
padding = 0;
|
|
27
28
|
mapIdle;
|
|
28
29
|
mapLoading;
|
|
30
|
+
previewError;
|
|
31
|
+
// Guards against reporting more than one error per load attempt
|
|
32
|
+
errorReported = false;
|
|
29
33
|
// MapLibre map instance and popup instance for feature info display
|
|
30
34
|
map;
|
|
31
35
|
mapTheme;
|
|
@@ -50,10 +54,10 @@ export class OgmMap {
|
|
|
50
54
|
});
|
|
51
55
|
this.getContainer();
|
|
52
56
|
this.addControls();
|
|
53
|
-
this.map.on('idle', () => this.mapIdle.emit());
|
|
54
57
|
this.map.on('load', () => this.previewSource(this.source));
|
|
55
58
|
this.map.on('mousemove', this.handleHover.bind(this));
|
|
56
59
|
this.map.on('click', this.handleClick.bind(this));
|
|
60
|
+
this.map.on('error', this.handleMapError.bind(this));
|
|
57
61
|
// View as a globe with atmosphere effects
|
|
58
62
|
this.map.on('style.load', () => {
|
|
59
63
|
this.map.setProjection({ type: 'globe' });
|
|
@@ -118,30 +122,64 @@ export class OgmMap {
|
|
|
118
122
|
// Do nothing if we didn't get passed a source
|
|
119
123
|
if (!source)
|
|
120
124
|
return;
|
|
125
|
+
// Fresh load attempt: allow one error to be reported again for this source
|
|
126
|
+
this.errorReported = false;
|
|
121
127
|
// Indicate loading state so we can show the spinner
|
|
122
128
|
this.mapLoading.emit();
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
try {
|
|
130
|
+
// Close popup if one is open
|
|
131
|
+
this.clearFeatureSelection();
|
|
132
|
+
this.destroyPopup();
|
|
133
|
+
// Clear existing preview
|
|
134
|
+
if (this.previewer) {
|
|
135
|
+
await this.previewer.clearPreview();
|
|
136
|
+
this.previewer = undefined;
|
|
137
|
+
}
|
|
138
|
+
// Get the appropriate previewer for our source and preview it
|
|
139
|
+
this.previewer = await this.getMapPreviewer(this.map);
|
|
140
|
+
if (!this.previewer)
|
|
141
|
+
throw new Error(`No previewer found for source: ${source.constructor.name}`);
|
|
142
|
+
await this.previewer.preview();
|
|
143
|
+
// Fit to bounds from the record; the spinner stays up until the map finishes moving
|
|
144
|
+
const bounds = await this.source.getBounds();
|
|
145
|
+
if (bounds)
|
|
146
|
+
await this.fitMapBounds(bounds);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error(`Error previewing source ${source.url}:`, error);
|
|
150
|
+
if (!this.errorReported) {
|
|
151
|
+
this.errorReported = true;
|
|
152
|
+
this.previewError.emit(referenceError(error, source.label(), source.url));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
this.mapIdle.emit();
|
|
130
157
|
}
|
|
131
|
-
// Get the appropriate previewer for our source and preview it
|
|
132
|
-
this.previewer = await this.getMapPreviewer(this.map);
|
|
133
|
-
if (!this.previewer)
|
|
134
|
-
throw new Error(`No previewer found for source: ${source.constructor.name}`);
|
|
135
|
-
await this.previewer.preview();
|
|
136
|
-
// Fit to bounds from the record
|
|
137
|
-
const bounds = await this.source.getBounds();
|
|
138
|
-
if (bounds)
|
|
139
|
-
await this.fitMapBounds(bounds);
|
|
140
|
-
// Emit map idle event to signal that the map is ready
|
|
141
|
-
this.mapIdle.emit();
|
|
142
158
|
}
|
|
143
|
-
//
|
|
159
|
+
// When the theme changes, swap the basemap to match.
|
|
160
|
+
onThemeChange() {
|
|
161
|
+
if (!this.map)
|
|
162
|
+
return;
|
|
163
|
+
this.map.setStyle(this.mapTheme.getBaseMapStyle());
|
|
164
|
+
this.map.once('style.load', async () => await this.previewSource(this.source));
|
|
165
|
+
}
|
|
166
|
+
// Surface MapLibre errors tied to the current preview source, skipping the
|
|
167
|
+
// noise from basemap/glyph/sprite loads, and deduped to a single alert per load attempt.
|
|
168
|
+
handleMapError(event) {
|
|
169
|
+
if (this.errorReported || !this.source || !this.previewer)
|
|
170
|
+
return;
|
|
171
|
+
if (event.sourceId !== this.previewer.sourceId)
|
|
172
|
+
return;
|
|
173
|
+
this.errorReported = true;
|
|
174
|
+
this.previewError.emit(referenceError(event.error, this.source.label(), this.source.url));
|
|
175
|
+
}
|
|
176
|
+
// Fit the map to the given bounds; resolve once the move finishes. Guard the case where the bounds
|
|
177
|
+
// can't produce a camera - e.g. sidebar padding wider than the viewport, or a hidden, zero-size
|
|
178
|
+
// inactive tab panel - because then fitBounds won't move, 'moveend' never fires, and awaiting this
|
|
179
|
+
// promise (and the loading state that depends on it) would hang forever.
|
|
144
180
|
async fitMapBounds(bounds) {
|
|
181
|
+
if (!this.map.cameraForBounds(bounds))
|
|
182
|
+
return;
|
|
145
183
|
return new Promise(resolve => {
|
|
146
184
|
this.map.once('moveend', () => resolve());
|
|
147
185
|
this.map.fitBounds(bounds);
|
|
@@ -213,7 +251,8 @@ export class OgmMap {
|
|
|
213
251
|
}
|
|
214
252
|
// Create a new popup and set its content and location
|
|
215
253
|
createPopup(location) {
|
|
216
|
-
this.popup = new maplibregl.Popup({ maxWidth: 'none'
|
|
254
|
+
this.popup = new maplibregl.Popup({ maxWidth: 'none' }).setDOMContent(this.attributesEl).setLngLat(location).addTo(this.map);
|
|
255
|
+
this.popup.on('close', this.clearFeatureSelection.bind(this));
|
|
217
256
|
}
|
|
218
257
|
// Remove popup from the map and clear the reference
|
|
219
258
|
destroyPopup() {
|
|
@@ -227,7 +266,7 @@ export class OgmMap {
|
|
|
227
266
|
return this.previewer?.layerIds || [];
|
|
228
267
|
}
|
|
229
268
|
render() {
|
|
230
|
-
return h("div", { key: '
|
|
269
|
+
return h("div", { key: 'c683bc9d81e84caa58d4575d0812c5fcdb096e28', id: "map", class: `wa-${this.theme}` });
|
|
231
270
|
}
|
|
232
271
|
static get is() { return "ogm-map"; }
|
|
233
272
|
static get encapsulation() { return "shadow"; }
|
|
@@ -337,6 +376,28 @@ export class OgmMap {
|
|
|
337
376
|
"resolved": "void",
|
|
338
377
|
"references": {}
|
|
339
378
|
}
|
|
379
|
+
}, {
|
|
380
|
+
"method": "previewError",
|
|
381
|
+
"name": "previewError",
|
|
382
|
+
"bubbles": true,
|
|
383
|
+
"cancelable": true,
|
|
384
|
+
"composed": true,
|
|
385
|
+
"docs": {
|
|
386
|
+
"tags": [],
|
|
387
|
+
"text": ""
|
|
388
|
+
},
|
|
389
|
+
"complexType": {
|
|
390
|
+
"original": "PreviewError",
|
|
391
|
+
"resolved": "PreviewError",
|
|
392
|
+
"references": {
|
|
393
|
+
"PreviewError": {
|
|
394
|
+
"location": "import",
|
|
395
|
+
"path": "../../lib/errors",
|
|
396
|
+
"id": "src/lib/errors.ts::PreviewError",
|
|
397
|
+
"referenceLocation": "PreviewError"
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
340
401
|
}];
|
|
341
402
|
}
|
|
342
403
|
static get methods() {
|
|
@@ -373,6 +434,9 @@ export class OgmMap {
|
|
|
373
434
|
return [{
|
|
374
435
|
"propName": "source",
|
|
375
436
|
"methodName": "previewSource"
|
|
437
|
+
}, {
|
|
438
|
+
"propName": "theme",
|
|
439
|
+
"methodName": "onThemeChange"
|
|
376
440
|
}, {
|
|
377
441
|
"propName": "padding",
|
|
378
442
|
"methodName": "onPaddingChange"
|
|
@@ -2,10 +2,11 @@ import { h } from "@stencil/core";
|
|
|
2
2
|
export class OgmMenubar {
|
|
3
3
|
record;
|
|
4
4
|
theme;
|
|
5
|
-
sidebarToggled;
|
|
6
5
|
loading = false;
|
|
6
|
+
hideTitle = false;
|
|
7
|
+
sidebarToggled;
|
|
7
8
|
render() {
|
|
8
|
-
return (h("div", { key: '
|
|
9
|
+
return (h("div", { key: '470fcb6d5d31cc9a53142372e82c6b15563863d3', class: `menubar ${this.theme && `wa-${this.theme}`}` }, h("wa-button", { key: '22dec0e10b5b12a1481355d97cc61b6c85b7e612', appearance: "plain", class: "menu-button", onclick: this.sidebarToggled.emit }, h("wa-icon", { key: '48f29ad88af2d982392d946cf11fdc7e605b7aa6', name: "list", label: "Open sidebar", canvas: "auto" })), this.record?.restricted && (h(h.Fragment, null, h("wa-tooltip", { key: 'fa26b6d78dc07d0a009a941e6c2587342a8d6fe4', for: "restricted-icon" }, "Restricted access"), h("wa-icon", { key: '0aaece23cb54401ed62634c079cbfdca63926d69', id: "restricted-icon", name: "lock-fill", label: "Restricted access", class: "restricted-icon", canvas: "auto" }))), !this.hideTitle && h("div", { key: '89d30f43c7d84478dae1777a5be57136342d72f0', class: "title" }, this.record?.title), this.loading && h("wa-spinner", { key: '69a12e09d0b807e85000d63ee3fba8fb98c4ec33', class: "loading-spinner" })));
|
|
9
10
|
}
|
|
10
11
|
static get is() { return "ogm-menubar"; }
|
|
11
12
|
static get encapsulation() { return "shadow"; }
|
|
@@ -81,6 +82,26 @@ export class OgmMenubar {
|
|
|
81
82
|
"reflect": false,
|
|
82
83
|
"attribute": "loading",
|
|
83
84
|
"defaultValue": "false"
|
|
85
|
+
},
|
|
86
|
+
"hideTitle": {
|
|
87
|
+
"type": "boolean",
|
|
88
|
+
"mutable": false,
|
|
89
|
+
"complexType": {
|
|
90
|
+
"original": "boolean",
|
|
91
|
+
"resolved": "boolean",
|
|
92
|
+
"references": {}
|
|
93
|
+
},
|
|
94
|
+
"required": false,
|
|
95
|
+
"optional": false,
|
|
96
|
+
"docs": {
|
|
97
|
+
"tags": [],
|
|
98
|
+
"text": ""
|
|
99
|
+
},
|
|
100
|
+
"getter": false,
|
|
101
|
+
"setter": false,
|
|
102
|
+
"reflect": false,
|
|
103
|
+
"attribute": "hide-title",
|
|
104
|
+
"defaultValue": "false"
|
|
84
105
|
}
|
|
85
106
|
};
|
|
86
107
|
}
|