@jupytergis/base 0.12.0 → 0.12.2
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/lib/constants.d.ts +3 -2
- package/lib/dialogs/layerBrowserDialog.d.ts +3 -3
- package/lib/dialogs/layerBrowserDialog.js +9 -10
- package/lib/formbuilder/objectform/StoryEditorForm.js +19 -2
- package/lib/mainview/mainView.d.ts +8 -2
- package/lib/mainview/mainView.js +40 -11
- package/lib/mainview/mainviewwidget.js +2 -2
- package/lib/panelview/leftpanel.d.ts +2 -1
- package/lib/panelview/leftpanel.js +46 -29
- package/lib/panelview/rightpanel.d.ts +2 -1
- package/lib/panelview/rightpanel.js +13 -18
- package/lib/panelview/story-maps/MobileSpectaPanel.d.ts +7 -0
- package/lib/panelview/story-maps/MobileSpectaPanel.js +114 -0
- package/lib/panelview/story-maps/StoryNavBar.d.ts +3 -2
- package/lib/panelview/story-maps/StoryNavBar.js +18 -6
- package/lib/panelview/story-maps/StoryViewerPanel.d.ts +10 -0
- package/lib/panelview/story-maps/StoryViewerPanel.js +44 -18
- package/lib/panelview/story-maps/components/StoryImageSection.d.ts +2 -7
- package/lib/panelview/story-maps/components/StoryImageSection.js +2 -4
- package/lib/panelview/story-maps/components/StorySubtitleSection.d.ts +2 -6
- package/lib/panelview/story-maps/components/StorySubtitleSection.js +2 -4
- package/lib/panelview/story-maps/components/StoryTitleSection.d.ts +2 -7
- package/lib/panelview/story-maps/components/StoryTitleSection.js +2 -3
- package/lib/shared/components/Button.js +2 -2
- package/lib/shared/components/Calendar.js +0 -1
- package/lib/shared/components/Checkbox.d.ts +1 -1
- package/lib/shared/components/Checkbox.js +1 -1
- package/lib/shared/components/Dialog.d.ts +1 -1
- package/lib/shared/components/Dialog.js +1 -1
- package/lib/shared/components/Drawer.d.ts +13 -0
- package/lib/shared/components/Drawer.js +59 -0
- package/lib/shared/components/DropdownMenu.d.ts +1 -1
- package/lib/shared/components/DropdownMenu.js +1 -1
- package/lib/shared/components/Popover.d.ts +1 -1
- package/lib/shared/components/Popover.js +1 -1
- package/lib/shared/components/RadioGroup.d.ts +1 -1
- package/lib/shared/components/RadioGroup.js +1 -1
- package/lib/shared/components/Sheet.d.ts +15 -0
- package/lib/shared/components/Sheet.js +64 -0
- package/lib/shared/components/Switch.d.ts +1 -1
- package/lib/shared/components/Switch.js +1 -1
- package/lib/shared/components/Tabs.d.ts +1 -1
- package/lib/shared/components/Tabs.js +1 -1
- package/lib/shared/components/ToggleGroup.d.ts +1 -1
- package/lib/shared/components/ToggleGroup.js +1 -1
- package/lib/shared/hooks/useMediaQuery.d.ts +9 -0
- package/lib/shared/hooks/useMediaQuery.js +32 -0
- package/lib/tools.d.ts +2 -1
- package/lib/tools.js +33 -38
- package/package.json +5 -13
- package/style/base.css +23 -8
- package/style/shared/drawer.css +154 -0
- package/style/shared/sheet.css +258 -0
- package/style/shared/tabs.css +0 -6
- package/style/storyPanel.css +39 -9
package/lib/constants.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProcessingCommandIDs } from '@jupytergis/schema';
|
|
2
2
|
import { LabIcon } from '@jupyterlab/ui-components';
|
|
3
|
+
import * as BaseCommandIDs from './commands/BaseCommandIDs';
|
|
3
4
|
/**
|
|
4
5
|
* The command IDs.
|
|
5
6
|
*/
|
|
6
|
-
export declare const CommandIDs:
|
|
7
|
+
export declare const CommandIDs: typeof BaseCommandIDs & typeof ProcessingCommandIDs;
|
|
7
8
|
interface IRegisteredIcon {
|
|
8
9
|
icon?: LabIcon;
|
|
9
10
|
iconClass?: string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { IJGISFormSchemaRegistry, IJupyterGISModel,
|
|
1
|
+
import { IJGISFormSchemaRegistry, IJupyterGISModel, ILayerGalleryEntry } from '@jupytergis/schema';
|
|
2
2
|
import { Dialog } from '@jupyterlab/apputils';
|
|
3
3
|
import { PromiseDelegate } from '@lumino/coreutils';
|
|
4
4
|
import { Signal } from '@lumino/signaling';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
interface ILayerBrowserDialogProps {
|
|
7
7
|
model: IJupyterGISModel;
|
|
8
|
-
registry:
|
|
8
|
+
registry: ILayerGalleryEntry[];
|
|
9
9
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
10
10
|
okSignalPromise: PromiseDelegate<Signal<Dialog<any>, number>>;
|
|
11
11
|
cancel: () => void;
|
|
@@ -13,7 +13,7 @@ interface ILayerBrowserDialogProps {
|
|
|
13
13
|
export declare const LayerBrowserComponent: React.FC<ILayerBrowserDialogProps>;
|
|
14
14
|
export interface ILayerBrowserOptions {
|
|
15
15
|
model: IJupyterGISModel;
|
|
16
|
-
registry:
|
|
16
|
+
registry: ILayerGalleryEntry[];
|
|
17
17
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
18
18
|
}
|
|
19
19
|
export declare class LayerBrowserWidget extends Dialog<boolean> {
|
|
@@ -5,14 +5,14 @@ import { PromiseDelegate, UUID } from '@lumino/coreutils';
|
|
|
5
5
|
import { Signal } from '@lumino/signaling';
|
|
6
6
|
import React, { useEffect, useState } from 'react';
|
|
7
7
|
import { CreationFormWrapper } from './layerCreationFormDialog';
|
|
8
|
-
import CUSTOM_RASTER_IMAGE from '../../
|
|
8
|
+
import CUSTOM_RASTER_IMAGE from '../../layer_gallery/custom_raster.png';
|
|
9
9
|
export const LayerBrowserComponent = ({ model, registry, formSchemaRegistry, okSignalPromise, cancel, }) => {
|
|
10
10
|
const [searchTerm, setSearchTerm] = useState('');
|
|
11
11
|
const [activeLayers, setActiveLayers] = useState([]);
|
|
12
12
|
const [selectedCategory, setSelectedCategory] = useState();
|
|
13
13
|
const [creatingCustomRaster, setCreatingCustomRaster] = useState(false);
|
|
14
14
|
const [galleryWithCategory, setGalleryWithCategory] = useState(registry);
|
|
15
|
-
const providers = [...new Set(registry.map(item => item.
|
|
15
|
+
const providers = [...new Set(registry.map(item => item.provider))];
|
|
16
16
|
const filteredGallery = galleryWithCategory.filter(item => item.name.toLowerCase().includes(searchTerm));
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
model.sharedModel.layersChanged.connect(handleLayerChange);
|
|
@@ -37,7 +37,7 @@ export const LayerBrowserComponent = ({ model, registry, formSchemaRegistry, okS
|
|
|
37
37
|
selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.classList.remove('jGIS-layer-browser-category-selected');
|
|
38
38
|
const filteredGallery = sameAsOld
|
|
39
39
|
? registry
|
|
40
|
-
: registry.filter(item => { var _a; return (_a = item.
|
|
40
|
+
: registry.filter(item => { var _a; return (_a = item.provider) === null || _a === void 0 ? void 0 : _a.includes(categoryTab.innerText); });
|
|
41
41
|
setGalleryWithCategory(filteredGallery);
|
|
42
42
|
setSearchTerm('');
|
|
43
43
|
setSelectedCategory(sameAsOld ? null : categoryTab);
|
|
@@ -52,15 +52,13 @@ export const LayerBrowserComponent = ({ model, registry, formSchemaRegistry, okS
|
|
|
52
52
|
const handleTileClick = (tile) => {
|
|
53
53
|
const sourceId = UUID.uuid4();
|
|
54
54
|
const sourceModel = {
|
|
55
|
-
type:
|
|
55
|
+
type: tile.sourceType,
|
|
56
56
|
name: tile.name,
|
|
57
|
-
parameters: tile.
|
|
57
|
+
parameters: tile.sourceParameters,
|
|
58
58
|
};
|
|
59
59
|
const layerModel = {
|
|
60
|
-
type:
|
|
61
|
-
parameters: {
|
|
62
|
-
source: sourceId,
|
|
63
|
-
},
|
|
60
|
+
type: tile.layerType,
|
|
61
|
+
parameters: Object.assign(Object.assign({}, tile.layerParameters), { source: sourceId }),
|
|
64
62
|
visible: true,
|
|
65
63
|
name: tile.name + ' Layer',
|
|
66
64
|
};
|
|
@@ -113,7 +111,8 @@ export const LayerBrowserComponent = ({ model, registry, formSchemaRegistry, okS
|
|
|
113
111
|
React.createElement("div", { className: "jGIS-layer-browser-text-container" },
|
|
114
112
|
React.createElement("div", { className: "jGIS-layer-browser-text-info" },
|
|
115
113
|
React.createElement("h3", { className: "jGIS-layer-browser-text-header jGIS-layer-browser-text-general" }, tile.name)),
|
|
116
|
-
React.createElement("
|
|
114
|
+
React.createElement("div", null, tile.sourceType),
|
|
115
|
+
React.createElement("p", { className: "jGIS-layer-browser-text-general jGIS-layer-browser-text-source" }, tile.description))))))));
|
|
117
116
|
};
|
|
118
117
|
export class LayerBrowserWidget extends Dialog {
|
|
119
118
|
constructor(options) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCssVarAsColor } from "../../tools";
|
|
1
2
|
import { BaseForm } from './baseform';
|
|
2
3
|
/**
|
|
3
4
|
* The form to modify story map properties.
|
|
@@ -6,11 +7,27 @@ export class StoryEditorPropertiesForm extends BaseForm {
|
|
|
6
7
|
processSchema(data, schema, uiSchema) {
|
|
7
8
|
super.processSchema(data, schema, uiSchema);
|
|
8
9
|
this.removeFormEntry('storySegments', data, schema, uiSchema);
|
|
9
|
-
uiSchema.
|
|
10
|
+
uiSchema.presentationBgColor = {
|
|
10
11
|
'ui:widget': 'color',
|
|
11
12
|
};
|
|
12
|
-
uiSchema.
|
|
13
|
+
uiSchema.presentationTextColor = {
|
|
13
14
|
'ui:widget': 'color',
|
|
14
15
|
};
|
|
16
|
+
// Set default values from theme CSS variables when not already in data
|
|
17
|
+
const schemaProps = schema.properties;
|
|
18
|
+
if ((schemaProps === null || schemaProps === void 0 ? void 0 : schemaProps.presentationBgColor) &&
|
|
19
|
+
(data === null || data === void 0 ? void 0 : data.presentationBgColor) === undefined) {
|
|
20
|
+
const defaultBg = getCssVarAsColor('--jp-layout-color0');
|
|
21
|
+
if (defaultBg) {
|
|
22
|
+
schemaProps.presentationBgColor.default = defaultBg;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if ((schemaProps === null || schemaProps === void 0 ? void 0 : schemaProps.presentationTextColor) &&
|
|
26
|
+
(data === null || data === void 0 ? void 0 : data.presentationTextColor) === undefined) {
|
|
27
|
+
const defaultText = getCssVarAsColor('--jp-ui-font-color0');
|
|
28
|
+
if (defaultText) {
|
|
29
|
+
schemaProps.presentationTextColor.default = defaultText;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
15
32
|
}
|
|
16
33
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IAnnotation, IAnnotationModel, IDict, IJGISFilterItem, IJGISFormSchemaRegistry, IJGISLayer, IJGISSource } from '@jupytergis/schema';
|
|
1
|
+
import { IAnnotation, IAnnotationModel, IDict, IJGISFilterItem, IJGISFormSchemaRegistry, IJGISLayer, IJGISSource, IJupyterGISSettings } from '@jupytergis/schema';
|
|
2
2
|
import { User } from '@jupyterlab/services';
|
|
3
3
|
import { IStateDB } from '@jupyterlab/statedb';
|
|
4
4
|
import { Layer } from 'ol/layer';
|
|
@@ -10,6 +10,8 @@ interface IProps {
|
|
|
10
10
|
state?: IStateDB;
|
|
11
11
|
formSchemaRegistry?: IJGISFormSchemaRegistry;
|
|
12
12
|
annotationModel?: IAnnotationModel;
|
|
13
|
+
/** True when viewport matches (max-width: 768px). Injected by MainViewWithMediaQuery. */
|
|
14
|
+
isMobile?: boolean;
|
|
13
15
|
}
|
|
14
16
|
interface IStates {
|
|
15
17
|
id: string;
|
|
@@ -31,6 +33,7 @@ interface IStates {
|
|
|
31
33
|
}>;
|
|
32
34
|
displayTemporalController: boolean;
|
|
33
35
|
filterStates: IDict<IJGISFilterItem | undefined>;
|
|
36
|
+
jgisSettings: IJupyterGISSettings;
|
|
34
37
|
isSpectaPresentation: boolean;
|
|
35
38
|
}
|
|
36
39
|
export declare class MainView extends React.Component<IProps, IStates> {
|
|
@@ -136,6 +139,7 @@ export declare class MainView extends React.Component<IProps, IStates> {
|
|
|
136
139
|
removeLayer(id: string): void;
|
|
137
140
|
private _onClientSharedStateChanged;
|
|
138
141
|
private _onSharedOptionsChanged;
|
|
142
|
+
private _syncSettingsFromRegistry;
|
|
139
143
|
private _onSettingsChanged;
|
|
140
144
|
private updateOptions;
|
|
141
145
|
private _onViewChanged;
|
|
@@ -222,4 +226,6 @@ export declare class MainView extends React.Component<IProps, IStates> {
|
|
|
222
226
|
private _isSpectaPresentationInitialized;
|
|
223
227
|
private _storyScrollHandler;
|
|
224
228
|
}
|
|
225
|
-
|
|
229
|
+
/** Thin wrapper that injects isMobile from useMediaQuery so MainView can use it in JSX. */
|
|
230
|
+
declare function MainViewWithMediaQuery(props: IProps): React.JSX.Element;
|
|
231
|
+
export { MainViewWithMediaQuery };
|
package/lib/mainview/mainView.js
CHANGED
|
@@ -39,6 +39,7 @@ import * as React from 'react';
|
|
|
39
39
|
import AnnotationFloater from "../annotations/components/AnnotationFloater";
|
|
40
40
|
import { CommandIDs } from "../constants";
|
|
41
41
|
import { LoadingOverlay } from "../shared/components/loading";
|
|
42
|
+
import useMediaQuery from "../shared/hooks/useMediaQuery";
|
|
42
43
|
import StatusBar from "../statusbar/StatusBar";
|
|
43
44
|
import { debounce, isLightTheme, loadFile, throttle } from "../tools";
|
|
44
45
|
import CollaboratorPointers from './CollaboratorPointers';
|
|
@@ -47,6 +48,7 @@ import TemporalSlider from './TemporalSlider';
|
|
|
47
48
|
import { hexToRgb } from '../dialogs/symbology/colorRampUtils';
|
|
48
49
|
import { markerIcon } from '../icons';
|
|
49
50
|
import { LeftPanel, RightPanel } from '../panelview';
|
|
51
|
+
import { MobileSpectaPanel } from '../panelview/story-maps/MobileSpectaPanel';
|
|
50
52
|
import StoryViewerPanel from '../panelview/story-maps/StoryViewerPanel';
|
|
51
53
|
export class MainView extends React.Component {
|
|
52
54
|
constructor(props) {
|
|
@@ -528,8 +530,8 @@ export class MainView extends React.Component {
|
|
|
528
530
|
return;
|
|
529
531
|
}
|
|
530
532
|
const story = this._model.getSelectedStory().story;
|
|
531
|
-
const bgColor = story === null || story === void 0 ? void 0 : story.
|
|
532
|
-
const textColor = story === null || story === void 0 ? void 0 : story.
|
|
533
|
+
const bgColor = story === null || story === void 0 ? void 0 : story.presentationBgColor;
|
|
534
|
+
const textColor = story === null || story === void 0 ? void 0 : story.presentationTextColor;
|
|
533
535
|
// Set background color
|
|
534
536
|
if (bgColor) {
|
|
535
537
|
const rgb = hexToRgb(bgColor);
|
|
@@ -634,6 +636,9 @@ export class MainView extends React.Component {
|
|
|
634
636
|
this._model.geolocationChanged.connect(this._handleGeolocationChanged, this);
|
|
635
637
|
this._model.flyToGeometrySignal.connect(this.flyToGeometry, this);
|
|
636
638
|
this._model.highlightFeatureSignal.connect(this.highlightFeatureOnMap, this);
|
|
639
|
+
Promise.resolve().then(() => {
|
|
640
|
+
this._syncSettingsFromRegistry();
|
|
641
|
+
});
|
|
637
642
|
// Watch isIdentifying and clear the highlight when Identify Tool is turned off
|
|
638
643
|
this._model.sharedModel.awareness.on('change', () => {
|
|
639
644
|
var _a;
|
|
@@ -653,6 +658,7 @@ export class MainView extends React.Component {
|
|
|
653
658
|
loadingErrors: [],
|
|
654
659
|
displayTemporalController: false,
|
|
655
660
|
filterStates: {},
|
|
661
|
+
jgisSettings: this._model.jgisSettings,
|
|
656
662
|
isSpectaPresentation: false,
|
|
657
663
|
};
|
|
658
664
|
this._sources = [];
|
|
@@ -705,11 +711,11 @@ export class MainView extends React.Component {
|
|
|
705
711
|
const fullScreen = new FullScreen({
|
|
706
712
|
target: this.controlsToolbarRef.current || undefined,
|
|
707
713
|
});
|
|
708
|
-
this._zoomControl = new Zoom({
|
|
709
|
-
target: this.controlsToolbarRef.current || undefined,
|
|
710
|
-
});
|
|
711
714
|
const controls = [scaleLine, fullScreen];
|
|
712
715
|
if (this._model.jgisSettings.zoomButtonsEnabled) {
|
|
716
|
+
this._zoomControl = new Zoom({
|
|
717
|
+
target: this.controlsToolbarRef.current || undefined,
|
|
718
|
+
});
|
|
713
719
|
controls.push(this._zoomControl);
|
|
714
720
|
}
|
|
715
721
|
if (this.divRef.current) {
|
|
@@ -1564,8 +1570,16 @@ export class MainView extends React.Component {
|
|
|
1564
1570
|
this._isPositionInitialized = true;
|
|
1565
1571
|
}
|
|
1566
1572
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1573
|
+
async _syncSettingsFromRegistry() {
|
|
1574
|
+
const composite = this._model.jgisSettings;
|
|
1575
|
+
if (composite) {
|
|
1576
|
+
this.setState({ jgisSettings: composite });
|
|
1577
|
+
this._onSettingsChanged();
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
_onSettingsChanged() {
|
|
1581
|
+
this.setState({ jgisSettings: this._model.jgisSettings });
|
|
1582
|
+
if (!this._Map) {
|
|
1569
1583
|
return;
|
|
1570
1584
|
}
|
|
1571
1585
|
const enabled = this._model.jgisSettings.zoomButtonsEnabled;
|
|
@@ -1795,6 +1809,14 @@ export class MainView extends React.Component {
|
|
|
1795
1809
|
if ((jgisLayer === null || jgisLayer === void 0 ? void 0 : jgisLayer.type) === 'StorySegmentLayer') {
|
|
1796
1810
|
const layerParams = jgisLayer.parameters;
|
|
1797
1811
|
const coords = getCenter(layerParams.extent);
|
|
1812
|
+
// Don't move map if we're already centered on the segment
|
|
1813
|
+
const viewCenter = this._Map.getView().getCenter();
|
|
1814
|
+
const centersEqual = viewCenter !== undefined &&
|
|
1815
|
+
Math.abs(viewCenter[0] - coords[0]) < 1e-9 &&
|
|
1816
|
+
Math.abs(viewCenter[1] - coords[1]) < 1e-9;
|
|
1817
|
+
if (centersEqual) {
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1798
1820
|
this._flyToPosition({ x: coords[0], y: coords[1] }, layerParams.zoom, ((_c = layerParams.transition.time) !== null && _c !== void 0 ? _c : 1) * 1000, // seconds -> ms
|
|
1799
1821
|
layerParams.transition.type);
|
|
1800
1822
|
return;
|
|
@@ -2064,11 +2086,18 @@ export class MainView extends React.Component {
|
|
|
2064
2086
|
height: '100%',
|
|
2065
2087
|
} },
|
|
2066
2088
|
React.createElement("div", { className: "jgis-panels-wrapper" }, !this.state.isSpectaPresentation ? (React.createElement(React.Fragment, null,
|
|
2067
|
-
this._state && (React.createElement(LeftPanel, { model: this._model, commands: this._mainViewModel.commands, state: this._state })),
|
|
2068
|
-
this._formSchemaRegistry && this._annotationModel && (React.createElement(RightPanel, { model: this._model, commands: this._mainViewModel.commands, formSchemaRegistry: this._formSchemaRegistry, annotationModel: this._annotationModel })))) : (React.createElement("div", { className: "jgis-specta-right-panel-container-mod jgis-right-panel-container" },
|
|
2089
|
+
this._state && (React.createElement(LeftPanel, { model: this._model, commands: this._mainViewModel.commands, state: this._state, settings: this.state.jgisSettings })),
|
|
2090
|
+
this._formSchemaRegistry && this._annotationModel && (React.createElement(RightPanel, { model: this._model, commands: this._mainViewModel.commands, formSchemaRegistry: this._formSchemaRegistry, annotationModel: this._annotationModel, settings: this.state.jgisSettings })))) : this.props.isMobile ? (React.createElement(MobileSpectaPanel, { model: this._model })) : (React.createElement("div", { className: "jgis-specta-right-panel-container-mod jgis-right-panel-container" },
|
|
2069
2091
|
React.createElement("div", { ref: this.spectaContainerRef, className: "jgis-specta-story-panel-container" },
|
|
2070
|
-
React.createElement(StoryViewerPanel, { ref: this.storyViewerPanelRef, model: this._model, isSpecta: this.state.isSpectaPresentation }))))),
|
|
2092
|
+
React.createElement(StoryViewerPanel, { ref: this.storyViewerPanelRef, model: this._model, isSpecta: this.state.isSpectaPresentation, className: "jgis-story-viewer-panel-specta-mod" }))))),
|
|
2071
2093
|
React.createElement("div", { ref: this.controlsToolbarRef, className: "jgis-controls-toolbar" }))),
|
|
2072
|
-
React.createElement(StatusBar, { jgisModel: this._model, loading: this.state.loadingLayer, projection: this.state.viewProjection, scale: this.state.scale }))));
|
|
2094
|
+
!this.state.isSpectaPresentation && (React.createElement(StatusBar, { jgisModel: this._model, loading: this.state.loadingLayer, projection: this.state.viewProjection, scale: this.state.scale })))));
|
|
2073
2095
|
}
|
|
2074
2096
|
}
|
|
2097
|
+
// ! TODO make mainview a modern react component instead of a class
|
|
2098
|
+
/** Thin wrapper that injects isMobile from useMediaQuery so MainView can use it in JSX. */
|
|
2099
|
+
function MainViewWithMediaQuery(props) {
|
|
2100
|
+
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
2101
|
+
return React.createElement(MainView, Object.assign({}, props, { isMobile: isMobile }));
|
|
2102
|
+
}
|
|
2103
|
+
export { MainViewWithMediaQuery };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactWidget } from '@jupyterlab/apputils';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { MainViewWithMediaQuery } from './mainView';
|
|
4
4
|
export class JupyterGISMainViewPanel extends ReactWidget {
|
|
5
5
|
/**
|
|
6
6
|
* Construct a `JupyterGISPanel`.
|
|
@@ -12,6 +12,6 @@ export class JupyterGISMainViewPanel extends ReactWidget {
|
|
|
12
12
|
this._options = options;
|
|
13
13
|
}
|
|
14
14
|
render() {
|
|
15
|
-
return (React.createElement(
|
|
15
|
+
return (React.createElement(MainViewWithMediaQuery, { state: this._state, viewModel: this._options.mainViewModel, formSchemaRegistry: this._options.formSchemaRegistry, annotationModel: this._options.annotationModel }));
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IJupyterGISModel, SelectionType } from '@jupytergis/schema';
|
|
1
|
+
import { IJupyterGISModel, SelectionType, IJupyterGISSettings } from '@jupytergis/schema';
|
|
2
2
|
import { IStateDB } from '@jupyterlab/statedb';
|
|
3
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
4
4
|
import { MouseEvent as ReactMouseEvent } from 'react';
|
|
@@ -12,6 +12,7 @@ interface ILeftPanelProps {
|
|
|
12
12
|
model: IJupyterGISModel;
|
|
13
13
|
state: IStateDB;
|
|
14
14
|
commands: CommandRegistry;
|
|
15
|
+
settings: IJupyterGISSettings;
|
|
15
16
|
}
|
|
16
17
|
export declare const LeftPanel: React.FC<ILeftPanelProps>;
|
|
17
18
|
export {};
|
|
@@ -1,34 +1,64 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { CommandIDs } from '../constants';
|
|
2
3
|
import { LayersBodyComponent } from './components/layers';
|
|
3
4
|
import FilterComponent from './filter-panel/Filter';
|
|
4
5
|
import { PanelTabs, TabsContent, TabsList, TabsTrigger, } from '../shared/components/Tabs';
|
|
5
6
|
import StacPanel from '../stacBrowser/components/StacPanel';
|
|
6
7
|
export const LeftPanel = (props) => {
|
|
7
8
|
var _a;
|
|
8
|
-
const [settings, setSettings] = React.useState(props.model.jgisSettings);
|
|
9
9
|
const [options, setOptions] = React.useState(props.model.getOptions());
|
|
10
10
|
const storyMapPresentationMode = (_a = options.storyMapPresentationMode) !== null && _a !== void 0 ? _a : false;
|
|
11
11
|
const [layerTree, setLayerTree] = React.useState(props.model.getLayerTree());
|
|
12
|
+
const hasSyncedInitialSelectionRef = React.useRef(false);
|
|
13
|
+
const tabInfo = [
|
|
14
|
+
!props.settings.layersDisabled
|
|
15
|
+
? { name: 'layers', title: 'Layers' }
|
|
16
|
+
: false,
|
|
17
|
+
!props.settings.stacBrowserDisabled && !storyMapPresentationMode
|
|
18
|
+
? { name: 'stac', title: 'Stac Browser' }
|
|
19
|
+
: false,
|
|
20
|
+
!props.settings.filtersDisabled && !storyMapPresentationMode
|
|
21
|
+
? { name: 'filters', title: 'Filters' }
|
|
22
|
+
: false,
|
|
23
|
+
!props.settings.storyMapsDisabled
|
|
24
|
+
? { name: 'segments', title: 'Segments' }
|
|
25
|
+
: false,
|
|
26
|
+
].filter(Boolean);
|
|
27
|
+
const [curTab, setCurTab] = React.useState(tabInfo.length > 0 ? tabInfo[0].name : undefined);
|
|
12
28
|
React.useEffect(() => {
|
|
13
|
-
const onSettingsChanged = () => {
|
|
14
|
-
setSettings(Object.assign({}, props.model.jgisSettings));
|
|
15
|
-
};
|
|
16
29
|
const onOptionsChanged = () => {
|
|
17
30
|
setOptions(Object.assign({}, props.model.getOptions()));
|
|
18
31
|
};
|
|
19
32
|
const updateLayerTree = () => {
|
|
20
|
-
|
|
33
|
+
const freshTree = props.model.getLayerTree() || [];
|
|
34
|
+
setLayerTree(freshTree);
|
|
35
|
+
// Sync selected to top layer/group only the first time the tree has items
|
|
36
|
+
if (!hasSyncedInitialSelectionRef.current && freshTree.length > 0) {
|
|
37
|
+
hasSyncedInitialSelectionRef.current = true;
|
|
38
|
+
const lastItem = freshTree[freshTree.length - 1];
|
|
39
|
+
const lastId = typeof lastItem === 'string' ? lastItem : lastItem === null || lastItem === void 0 ? void 0 : lastItem.name;
|
|
40
|
+
const lastType = typeof lastItem === 'string' ? 'layer' : 'group';
|
|
41
|
+
if (lastId) {
|
|
42
|
+
props.model.syncSelected({ [lastId]: { type: lastType } }, props.model.getClientId().toString());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Need to let command know when segments get populated
|
|
46
|
+
props.commands.notifyCommandChanged(CommandIDs.toggleStoryPresentationMode);
|
|
47
|
+
};
|
|
48
|
+
const onSegmentAdded = (_sender, payload) => {
|
|
49
|
+
props.model.syncSelected({ [payload.storySegmentId]: { type: 'layer' } }, props.model.getClientId().toString());
|
|
50
|
+
setCurTab('segments');
|
|
21
51
|
};
|
|
22
|
-
props.model.settingsChanged.connect(onSettingsChanged);
|
|
23
52
|
props.model.sharedOptionsChanged.connect(onOptionsChanged);
|
|
24
53
|
props.model.sharedModel.layersChanged.connect(updateLayerTree);
|
|
25
54
|
props.model.sharedModel.layerTreeChanged.connect(updateLayerTree);
|
|
55
|
+
props.model.segmentAdded.connect(onSegmentAdded);
|
|
26
56
|
updateLayerTree();
|
|
27
57
|
return () => {
|
|
28
|
-
props.model.settingsChanged.disconnect(onSettingsChanged);
|
|
29
58
|
props.model.sharedOptionsChanged.disconnect(onOptionsChanged);
|
|
30
59
|
props.model.sharedModel.layersChanged.disconnect(updateLayerTree);
|
|
31
60
|
props.model.sharedModel.layerTreeChanged.disconnect(updateLayerTree);
|
|
61
|
+
props.model.segmentAdded.disconnect(onSegmentAdded);
|
|
32
62
|
};
|
|
33
63
|
}, [props.model]);
|
|
34
64
|
// Since story segments are technically layers they are stored in the layer tree, so we separate them
|
|
@@ -88,24 +118,11 @@ export const LeftPanel = (props) => {
|
|
|
88
118
|
}
|
|
89
119
|
props.model.sharedModel.updateStoryMap(storyId, Object.assign(Object.assign({}, story), { storySegments: storySegmentLayerTree }));
|
|
90
120
|
}, [storySegmentLayerTree]);
|
|
91
|
-
const allLeftTabsDisabled = settings.layersDisabled &&
|
|
92
|
-
settings.stacBrowserDisabled &&
|
|
93
|
-
settings.filtersDisabled &&
|
|
94
|
-
settings.storyMapsDisabled;
|
|
95
|
-
const leftPanelVisible = !settings.leftPanelDisabled && !allLeftTabsDisabled;
|
|
96
|
-
const tabInfo = [
|
|
97
|
-
!settings.layersDisabled ? { name: 'layers', title: 'Layers' } : false,
|
|
98
|
-
!settings.stacBrowserDisabled && !storyMapPresentationMode
|
|
99
|
-
? { name: 'stac', title: 'Stac Browser' }
|
|
100
|
-
: false,
|
|
101
|
-
!settings.filtersDisabled && !storyMapPresentationMode
|
|
102
|
-
? { name: 'filters', title: 'Filters' }
|
|
103
|
-
: false,
|
|
104
|
-
!settings.storyMapsDisabled
|
|
105
|
-
? { name: 'segments', title: 'Segments' }
|
|
106
|
-
: false,
|
|
107
|
-
].filter(Boolean);
|
|
108
|
-
const [curTab, setCurTab] = React.useState(tabInfo.length > 0 ? tabInfo[0].name : undefined);
|
|
121
|
+
const allLeftTabsDisabled = props.settings.layersDisabled &&
|
|
122
|
+
props.settings.stacBrowserDisabled &&
|
|
123
|
+
props.settings.filtersDisabled &&
|
|
124
|
+
props.settings.storyMapsDisabled;
|
|
125
|
+
const leftPanelVisible = !props.settings.leftPanelDisabled && !allLeftTabsDisabled;
|
|
109
126
|
return (React.createElement("div", { className: "jgis-left-panel-container", style: { display: leftPanelVisible ? 'block' : 'none' } },
|
|
110
127
|
React.createElement(PanelTabs, { curTab: curTab, className: "jgis-panel-tabs" },
|
|
111
128
|
React.createElement(TabsList, null, tabInfo.map(tab => (React.createElement(TabsTrigger, { className: "jGIS-layer-browser-category", key: tab.name, value: tab.name, onClick: () => {
|
|
@@ -116,12 +133,12 @@ export const LeftPanel = (props) => {
|
|
|
116
133
|
setCurTab('');
|
|
117
134
|
}
|
|
118
135
|
} }, tab.title)))),
|
|
119
|
-
!settings.layersDisabled && (React.createElement(TabsContent, { value: "layers", className: "jgis-panel-tab-content jp-gis-layerPanel" },
|
|
136
|
+
!props.settings.layersDisabled && (React.createElement(TabsContent, { value: "layers", className: "jgis-panel-tab-content jp-gis-layerPanel" },
|
|
120
137
|
React.createElement(LayersBodyComponent, { model: props.model, commands: props.commands, state: props.state, layerTree: filteredLayerTree }))),
|
|
121
|
-
!settings.stacBrowserDisabled && (React.createElement(TabsContent, { value: "stac", className: "jgis-panel-tab-content jgis-panel-tab-content-stac-panel" },
|
|
138
|
+
!props.settings.stacBrowserDisabled && (React.createElement(TabsContent, { value: "stac", className: "jgis-panel-tab-content jgis-panel-tab-content-stac-panel" },
|
|
122
139
|
React.createElement(StacPanel, { model: props.model }))),
|
|
123
|
-
!settings.filtersDisabled && (React.createElement(TabsContent, { value: "filters", className: "jgis-panel-tab-content" },
|
|
140
|
+
!props.settings.filtersDisabled && (React.createElement(TabsContent, { value: "filters", className: "jgis-panel-tab-content" },
|
|
124
141
|
React.createElement(FilterComponent, { model: props.model }))),
|
|
125
|
-
!settings.storyMapsDisabled && (React.createElement(TabsContent, { value: "segments", className: "jgis-panel-tab-content" },
|
|
142
|
+
!props.settings.storyMapsDisabled && (React.createElement(TabsContent, { value: "segments", className: "jgis-panel-tab-content" },
|
|
126
143
|
React.createElement(LayersBodyComponent, { model: props.model, commands: props.commands, state: props.state, layerTree: storySegmentLayerTree }))))));
|
|
127
144
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IAnnotationModel, IJGISFormSchemaRegistry, IJupyterGISModel } from '@jupytergis/schema';
|
|
1
|
+
import { IAnnotationModel, IJGISFormSchemaRegistry, IJupyterGISModel, IJupyterGISSettings } from '@jupytergis/schema';
|
|
2
2
|
import { CommandRegistry } from '@lumino/commands';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
interface IRightPanelProps {
|
|
@@ -6,6 +6,7 @@ interface IRightPanelProps {
|
|
|
6
6
|
annotationModel: IAnnotationModel;
|
|
7
7
|
model: IJupyterGISModel;
|
|
8
8
|
commands: CommandRegistry;
|
|
9
|
+
settings: IJupyterGISSettings;
|
|
9
10
|
}
|
|
10
11
|
export declare const RightPanel: React.FC<IRightPanelProps>;
|
|
11
12
|
export {};
|
|
@@ -9,7 +9,6 @@ import { PanelTabs, TabsContent, TabsList, TabsTrigger, } from '../shared/compon
|
|
|
9
9
|
export const RightPanel = props => {
|
|
10
10
|
var _a;
|
|
11
11
|
const [editorMode, setEditorMode] = React.useState(true);
|
|
12
|
-
const [settings, setSettings] = React.useState(props.model.jgisSettings);
|
|
13
12
|
const [storyMapPresentationMode, setStoryMapPresentationMode] = React.useState((_a = props.model.getOptions().storyMapPresentationMode) !== null && _a !== void 0 ? _a : false);
|
|
14
13
|
// Only show editor when not in presentation mode and editorMode is true
|
|
15
14
|
const showEditor = !storyMapPresentationMode && editorMode;
|
|
@@ -20,19 +19,19 @@ export const RightPanel = props => {
|
|
|
20
19
|
? 'Story Editor'
|
|
21
20
|
: 'Story Map';
|
|
22
21
|
const tabInfo = [
|
|
23
|
-
!settings.objectPropertiesDisabled && !storyMapPresentationMode
|
|
22
|
+
!props.settings.objectPropertiesDisabled && !storyMapPresentationMode
|
|
24
23
|
? { name: 'objectProperties', title: 'Object Properties' }
|
|
25
24
|
: false,
|
|
26
|
-
!settings.storyMapsDisabled
|
|
25
|
+
!props.settings.storyMapsDisabled
|
|
27
26
|
? {
|
|
28
27
|
name: 'storyPanel',
|
|
29
28
|
title: storyPanelTitle,
|
|
30
29
|
}
|
|
31
30
|
: false,
|
|
32
|
-
!settings.annotationsDisabled
|
|
31
|
+
!props.settings.annotationsDisabled
|
|
33
32
|
? { name: 'annotations', title: 'Annotations' }
|
|
34
33
|
: false,
|
|
35
|
-
!settings.identifyDisabled
|
|
34
|
+
!props.settings.identifyDisabled
|
|
36
35
|
? { name: 'identifyPanel', title: 'Identified Features' }
|
|
37
36
|
: false,
|
|
38
37
|
].filter(Boolean);
|
|
@@ -43,12 +42,10 @@ export const RightPanel = props => {
|
|
|
43
42
|
return tabInfo.length > 0 ? tabInfo[0].name : '';
|
|
44
43
|
});
|
|
45
44
|
React.useEffect(() => {
|
|
46
|
-
const onSettingsChanged = () => {
|
|
47
|
-
setSettings(Object.assign({}, props.model.jgisSettings));
|
|
48
|
-
};
|
|
49
45
|
const onOptionsChanged = () => {
|
|
50
46
|
const { storyMapPresentationMode } = props.model.getOptions();
|
|
51
47
|
setStoryMapPresentationMode(storyMapPresentationMode !== null && storyMapPresentationMode !== void 0 ? storyMapPresentationMode : false);
|
|
48
|
+
storyMapPresentationMode && setCurTab('storyPanel');
|
|
52
49
|
};
|
|
53
50
|
let currentlyIdentifiedFeatures = undefined;
|
|
54
51
|
const onAwerenessChanged = (_, clients) => {
|
|
@@ -62,19 +59,17 @@ export const RightPanel = props => {
|
|
|
62
59
|
setCurTab('identifyPanel');
|
|
63
60
|
}
|
|
64
61
|
};
|
|
65
|
-
props.model.settingsChanged.connect(onSettingsChanged);
|
|
66
62
|
props.model.sharedOptionsChanged.connect(onOptionsChanged);
|
|
67
63
|
props.model.clientStateChanged.connect(onAwerenessChanged);
|
|
68
64
|
return () => {
|
|
69
|
-
props.model.settingsChanged.disconnect(onSettingsChanged);
|
|
70
65
|
props.model.sharedOptionsChanged.disconnect(onOptionsChanged);
|
|
71
66
|
props.model.clientStateChanged.disconnect(onAwerenessChanged);
|
|
72
67
|
};
|
|
73
68
|
}, [props.model]);
|
|
74
|
-
const allRightTabsDisabled = settings.objectPropertiesDisabled &&
|
|
75
|
-
settings.annotationsDisabled &&
|
|
76
|
-
settings.identifyDisabled;
|
|
77
|
-
const rightPanelVisible = !settings.rightPanelDisabled && !allRightTabsDisabled;
|
|
69
|
+
const allRightTabsDisabled = props.settings.objectPropertiesDisabled &&
|
|
70
|
+
props.settings.annotationsDisabled &&
|
|
71
|
+
props.settings.identifyDisabled;
|
|
72
|
+
const rightPanelVisible = !props.settings.rightPanelDisabled && !allRightTabsDisabled;
|
|
78
73
|
const [selectedObjectProperties, setSelectedObjectProperties] = React.useState(undefined);
|
|
79
74
|
const toggleEditor = () => {
|
|
80
75
|
setEditorMode(!editorMode);
|
|
@@ -89,13 +84,13 @@ export const RightPanel = props => {
|
|
|
89
84
|
setCurTab('');
|
|
90
85
|
}
|
|
91
86
|
} }, tab.title)))),
|
|
92
|
-
!settings.objectPropertiesDisabled && (React.createElement(TabsContent, { value: "objectProperties", className: "jgis-panel-tab-content" },
|
|
87
|
+
!props.settings.objectPropertiesDisabled && (React.createElement(TabsContent, { value: "objectProperties", className: "jgis-panel-tab-content" },
|
|
93
88
|
React.createElement(ObjectPropertiesReact, { setSelectedObject: setSelectedObjectProperties, selectedObject: selectedObjectProperties, formSchemaRegistry: props.formSchemaRegistry, model: props.model }))),
|
|
94
|
-
!settings.storyMapsDisabled && (React.createElement(TabsContent, { value: "storyPanel", className: "jgis-panel-tab-content", style: { paddingTop: 0 } },
|
|
89
|
+
!props.settings.storyMapsDisabled && (React.createElement(TabsContent, { value: "storyPanel", className: "jgis-panel-tab-content", style: { paddingTop: 0 } },
|
|
95
90
|
!storyMapPresentationMode && (React.createElement(PreviewModeSwitch, { checked: !editorMode, onCheckedChange: toggleEditor })),
|
|
96
91
|
showEditor ? (React.createElement(StoryEditorPanel, { model: props.model, commands: props.commands })) : (React.createElement(StoryViewerPanel, { model: props.model, isSpecta: false })))),
|
|
97
|
-
!settings.annotationsDisabled && (React.createElement(TabsContent, { value: "annotations", className: "jgis-panel-tab-content" },
|
|
92
|
+
!props.settings.annotationsDisabled && (React.createElement(TabsContent, { value: "annotations", className: "jgis-panel-tab-content" },
|
|
98
93
|
React.createElement(AnnotationsPanel, { annotationModel: props.annotationModel, jgisModel: props.model }))),
|
|
99
|
-
!settings.identifyDisabled && (React.createElement(TabsContent, { value: "identifyPanel", className: "jgis-panel-tab-content" },
|
|
94
|
+
!props.settings.identifyDisabled && (React.createElement(TabsContent, { value: "identifyPanel", className: "jgis-panel-tab-content" },
|
|
100
95
|
React.createElement(IdentifyPanelComponent, { model: props.model }))))));
|
|
101
96
|
};
|