feat(mapillary): Street Level panel in the right context rail

An ordinary collapsible GEV panel between CCTV and Context, starting
collapsed with the Mapillary mark in its strip. Body: a gated empty state
when no client token is present, plain-English query box (ASK becomes STOP
while running), streamed result chips, imagery filters with a colour
legend, and the embedded viewer whose expanded mode is a focus-trapped
dialog. All wording lives in a pure presentation module.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Fable 5.1 committed 2026-09-23 15:44:32 +01:00
1 parent 791e77fa33
commit 3169d205d9
11 files changed
+1073 -1072

No files matched your search

+26
View File
@@ -14,6 +14,7 @@ import { readShellElements } from './shellElements.js';
import { CockpitCoordinator } from './cockpitCoordinator.js';
import { ContextControls } from './context.js';
import { CctvControls } from './cctv.js';
import { MapillaryControls } from './mapillaryControls.js';
import { RadioControls } from './radio.js';
import { LocationNavigation } from './locationNavigation.js';
import { bindClearLayersControl } from './layers.js';
@@ -536,6 +537,7 @@ export class StyleManager extends ShellFacade {
this._initRightPanelAdaptiveLayout();
this._initRadioPanel();
this._initCctvPanel();
this._initMapillaryPanel();
this._initGlobalContextPanel();
this._initLocationBar();
this._initShareButton();
@@ -876,6 +878,29 @@ export class StyleManager extends ShellFacade {
}
/** Compose camera panel controls from the existing camera port and application actions. */
_initMapillaryPanel() {
const { mapillaryLayer } = this.services;
this._mapillaryControls?.destroy();
this._mapillaryControls = null;
if (!this._mapillaryPanel || !mapillaryLayer) return;
this._mapillaryControls = new MapillaryControls({
root: this._mapillaryPanel,
mapillary: mapillaryLayer,
actions: {
isEnabled: () => this._dataManager?.isEnabled('mapillary') === true,
setEnabled: (enabled) =>
this._dataManager?.setEnabled('mapillary', enabled, {
origin: 'user',
}),
setPanelCollapsed: (collapsed, options) =>
this.setPanelCollapsed('mapillary-panel', collapsed, options),
openKeySetup: () => document.getElementById('key-setup-chip')?.click(),
showToast: (message) => this._showToast(message),
},
});
this._mapillaryControls.connect();
}
_initCctvPanel() {
const { cctvLayer } = this.services;
this._cctvControls?.destroy();
@@ -1471,6 +1496,7 @@ export class StyleManager extends ShellFacade {
this._cameraOrientationControls?.destroy();
this._clearLayersControl?.destroy();
this._cctvControls?.destroy();
this._mapillaryControls?.destroy();
this._radioControls?.destroy();
this._cockpitCoordinator.stop();
this._visualSettings.stop();