@jupytergis/base 0.6.1 → 0.7.0
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/annotations/components/Annotation.d.ts +2 -3
- package/lib/annotations/components/Annotation.js +2 -9
- package/lib/commands/BaseCommandIDs.d.ts +1 -0
- package/lib/commands/BaseCommandIDs.js +1 -0
- package/lib/commands/index.js +15 -0
- package/lib/constants.js +1 -0
- package/lib/dialogs/symbology/components/color_ramp/ColorRamp.js +1 -1
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +2 -2
- package/lib/formbuilder/formselectors.js +3 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/keybindings.json +2 -2
- package/lib/mainview/mainView.d.ts +8 -1
- package/lib/mainview/mainView.js +24 -1
- package/lib/mainview/mainviewwidget.d.ts +11 -4
- package/lib/mainview/mainviewwidget.js +3 -2
- package/lib/menus.js +4 -0
- package/lib/panelview/annotationPanel.d.ts +3 -17
- package/lib/panelview/annotationPanel.js +5 -22
- package/lib/panelview/components/filter-panel/Filter.d.ts +2 -19
- package/lib/panelview/components/filter-panel/Filter.js +26 -59
- package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +6 -14
- package/lib/panelview/components/identify-panel/IdentifyPanel.js +14 -52
- package/lib/panelview/components/layers.d.ts +10 -12
- package/lib/panelview/components/layers.js +109 -79
- package/lib/panelview/index.d.ts +0 -1
- package/lib/panelview/index.js +0 -1
- package/lib/panelview/leftpanel.d.ts +8 -47
- package/lib/panelview/leftpanel.js +32 -154
- package/lib/panelview/objectproperties.d.ts +20 -15
- package/lib/panelview/objectproperties.js +12 -34
- package/lib/panelview/rightpanel.d.ts +8 -22
- package/lib/panelview/rightpanel.js +32 -77
- package/lib/processing/index.js +4 -3
- package/lib/shared/components/Tabs.d.ts +7 -1
- package/lib/shared/components/Tabs.js +6 -1
- package/lib/stacBrowser/components/{StacPanelView.d.ts → StacPanel.d.ts} +2 -2
- package/lib/stacBrowser/components/{StacPanelView.js → StacPanel.js} +3 -3
- package/lib/stacBrowser/index.d.ts +1 -1
- package/lib/stacBrowser/index.js +1 -1
- package/lib/tools.js +26 -0
- package/lib/types.d.ts +1 -9
- package/lib/widget.d.ts +8 -3
- package/lib/widget.js +8 -4
- package/package.json +7 -5
- package/style/base.css +18 -2
- package/style/shared/tabs.css +16 -2
- package/style/stacBrowser.css +0 -6
- package/style/tabPanel.css +91 -0
- package/style/temporalSlider.css +1 -0
- package/lib/panelview/model.d.ts +0 -19
- package/lib/panelview/model.js +0 -30
- package/lib/stacBrowser/StacBrowser.d.ts +0 -7
- package/lib/stacBrowser/StacBrowser.js +0 -16
- package/lib/stacBrowser/StacPanel.d.ts +0 -14
- package/lib/stacBrowser/StacPanel.js +0 -16
|
@@ -1,61 +1,23 @@
|
|
|
1
1
|
import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';
|
|
2
2
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
3
|
-
import { LabIcon,
|
|
4
|
-
import { Panel } from '@lumino/widgets';
|
|
3
|
+
import { LabIcon, caretDownIcon } from '@jupyterlab/ui-components';
|
|
5
4
|
import React, { useEffect, useRef, useState } from 'react';
|
|
6
|
-
export
|
|
7
|
-
constructor(options) {
|
|
8
|
-
super();
|
|
9
|
-
this._model = options.model;
|
|
10
|
-
this._tracker = options.tracker;
|
|
11
|
-
this.id = 'jupytergis::identifyPanel';
|
|
12
|
-
this.title.caption = 'Identify';
|
|
13
|
-
this.title.label = 'Identify';
|
|
14
|
-
this.addClass('jgis-scrollable');
|
|
15
|
-
this.addWidget(ReactWidget.create(React.createElement(IdentifyPanelComponent, { controlPanelModel: this._model, tracker: this._tracker })));
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
const IdentifyPanelComponent = ({ controlPanelModel, tracker, }) => {
|
|
5
|
+
export const IdentifyPanelComponent = ({ model, }) => {
|
|
19
6
|
var _a;
|
|
20
|
-
const [widgetId, setWidgetId] = useState('');
|
|
21
7
|
const [features, setFeatures] = useState();
|
|
22
8
|
const [visibleFeatures, setVisibleFeatures] = useState({
|
|
23
9
|
0: true,
|
|
24
10
|
});
|
|
25
11
|
const [remoteUser, setRemoteUser] = useState(null);
|
|
26
|
-
const [jgisModel, setJgisModel] = useState(controlPanelModel === null || controlPanelModel === void 0 ? void 0 : controlPanelModel.jGISModel);
|
|
27
12
|
const featuresRef = useRef(features);
|
|
28
|
-
/**
|
|
29
|
-
* Update the model when it changes.
|
|
30
|
-
*/
|
|
31
|
-
controlPanelModel === null || controlPanelModel === void 0 ? void 0 : controlPanelModel.documentChanged.connect((_, widget) => {
|
|
32
|
-
setJgisModel(widget === null || widget === void 0 ? void 0 : widget.model);
|
|
33
|
-
});
|
|
34
13
|
// Reset state values when current widget changes
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
const handleCurrentChanged = () => {
|
|
37
|
-
var _a;
|
|
38
|
-
if (((_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.id) === widgetId) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
if (tracker.currentWidget) {
|
|
42
|
-
setWidgetId(tracker.currentWidget.id);
|
|
43
|
-
}
|
|
44
|
-
setFeatures({});
|
|
45
|
-
setVisibleFeatures({ 0: true });
|
|
46
|
-
};
|
|
47
|
-
tracker.currentChanged.connect(handleCurrentChanged);
|
|
48
|
-
return () => {
|
|
49
|
-
tracker.currentChanged.disconnect(handleCurrentChanged);
|
|
50
|
-
};
|
|
51
|
-
}, []);
|
|
52
14
|
useEffect(() => {
|
|
53
15
|
featuresRef.current = features;
|
|
54
16
|
}, [features]);
|
|
55
17
|
useEffect(() => {
|
|
56
18
|
const handleClientStateChanged = (sender, clients) => {
|
|
57
19
|
var _a, _b, _c, _d, _e, _f;
|
|
58
|
-
const remoteUserId = (_a =
|
|
20
|
+
const remoteUserId = (_a = model === null || model === void 0 ? void 0 : model.localState) === null || _a === void 0 ? void 0 : _a.remoteUser;
|
|
59
21
|
// If following a collaborator
|
|
60
22
|
if (remoteUserId) {
|
|
61
23
|
const remoteState = clients.get(remoteUserId);
|
|
@@ -68,32 +30,31 @@ const IdentifyPanelComponent = ({ controlPanelModel, tracker, }) => {
|
|
|
68
30
|
return;
|
|
69
31
|
}
|
|
70
32
|
// If not following a collaborator
|
|
71
|
-
const identifiedFeatures = (_f = (_e =
|
|
33
|
+
const identifiedFeatures = (_f = (_e = model === null || model === void 0 ? void 0 : model.localState) === null || _e === void 0 ? void 0 : _e.identifiedFeatures) === null || _f === void 0 ? void 0 : _f.value;
|
|
72
34
|
if (!identifiedFeatures) {
|
|
73
35
|
setFeatures({});
|
|
74
36
|
return;
|
|
75
37
|
}
|
|
76
|
-
if (
|
|
77
|
-
featuresRef.current !== identifiedFeatures) {
|
|
38
|
+
if (model.isIdentifying && featuresRef.current !== identifiedFeatures) {
|
|
78
39
|
setFeatures(identifiedFeatures);
|
|
79
40
|
}
|
|
80
41
|
};
|
|
81
|
-
|
|
42
|
+
model === null || model === void 0 ? void 0 : model.clientStateChanged.connect(handleClientStateChanged);
|
|
82
43
|
return () => {
|
|
83
|
-
|
|
44
|
+
model === null || model === void 0 ? void 0 : model.clientStateChanged.disconnect(handleClientStateChanged);
|
|
84
45
|
};
|
|
85
|
-
}, [
|
|
46
|
+
}, [model]);
|
|
86
47
|
const highlightFeatureOnMap = (feature) => {
|
|
87
48
|
var _a, _b;
|
|
88
|
-
(_a =
|
|
49
|
+
(_a = model === null || model === void 0 ? void 0 : model.highlightFeatureSignal) === null || _a === void 0 ? void 0 : _a.emit(feature);
|
|
89
50
|
const geometry = feature.geometry || feature._geometry;
|
|
90
|
-
(_b =
|
|
51
|
+
(_b = model === null || model === void 0 ? void 0 : model.flyToGeometrySignal) === null || _b === void 0 ? void 0 : _b.emit(geometry);
|
|
91
52
|
};
|
|
92
53
|
const toggleFeatureVisibility = (index) => {
|
|
93
54
|
setVisibleFeatures(prev => (Object.assign(Object.assign({}, prev), { [index]: !prev[index] })));
|
|
94
55
|
};
|
|
95
56
|
return (React.createElement("div", { className: "jgis-identify-wrapper", style: {
|
|
96
|
-
border: ((_a =
|
|
57
|
+
border: ((_a = model === null || model === void 0 ? void 0 : model.localState) === null || _a === void 0 ? void 0 : _a.remoteUser)
|
|
97
58
|
? `solid 3px ${remoteUser === null || remoteUser === void 0 ? void 0 : remoteUser.color}`
|
|
98
59
|
: 'unset',
|
|
99
60
|
} }, features &&
|
|
@@ -125,6 +86,7 @@ const IdentifyPanelComponent = ({ controlPanelModel, tracker, }) => {
|
|
|
125
86
|
key,
|
|
126
87
|
":"),
|
|
127
88
|
typeof value === 'string' &&
|
|
128
|
-
/<\/?[a-z][\s\S]*>/i.test(value) ? (React.createElement("span", { dangerouslySetInnerHTML: {
|
|
89
|
+
/<\/?[a-z][\s\S]*>/i.test(value) ? (React.createElement("span", { dangerouslySetInnerHTML: {
|
|
90
|
+
__html: `${value}`,
|
|
91
|
+
} })) : (React.createElement("span", null, String(value)))))))))))));
|
|
129
92
|
};
|
|
130
|
-
export default IdentifyPanel;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
private _onDrop;
|
|
10
|
-
private _model;
|
|
11
|
-
private _state;
|
|
12
|
-
private _onSelect;
|
|
1
|
+
import { IJupyterGISModel } from '@jupytergis/schema';
|
|
2
|
+
import { IStateDB } from '@jupyterlab/statedb';
|
|
3
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
interface IBodyProps {
|
|
6
|
+
model: IJupyterGISModel;
|
|
7
|
+
commands: CommandRegistry;
|
|
8
|
+
state: IStateDB;
|
|
13
9
|
}
|
|
10
|
+
export declare const LayersBodyComponent: React.FC<IBodyProps>;
|
|
11
|
+
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { DOMUtils } from '@jupyterlab/apputils';
|
|
2
|
-
import { Button, LabIcon,
|
|
3
|
-
import {
|
|
2
|
+
import { Button, LabIcon, caretDownIcon } from '@jupyterlab/ui-components';
|
|
3
|
+
import { UUID } from '@lumino/coreutils';
|
|
4
4
|
import React, { useEffect, useState, } from 'react';
|
|
5
|
-
import { icons } from "../../constants";
|
|
5
|
+
import { CommandIDs, icons } from "../../constants";
|
|
6
6
|
import { nonVisibilityIcon, visibilityIcon } from "../../icons";
|
|
7
|
-
const LAYERS_PANEL_CLASS = 'jp-gis-layerPanel';
|
|
8
7
|
const LAYER_GROUP_CLASS = 'jp-gis-layerGroup';
|
|
9
8
|
const LAYER_GROUP_HEADER_CLASS = 'jp-gis-layerGroupHeader';
|
|
10
9
|
const LAYER_GROUP_COLLAPSER_CLASS = 'jp-gis-layerGroupCollapser';
|
|
@@ -13,77 +12,111 @@ const LAYER_CLASS = 'jp-gis-layer';
|
|
|
13
12
|
const LAYER_TITLE_CLASS = 'jp-gis-layerTitle';
|
|
14
13
|
const LAYER_ICON_CLASS = 'jp-gis-layerIcon';
|
|
15
14
|
const LAYER_TEXT_CLASS = 'jp-gis-layerText data-jgis-keybinding';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
15
|
+
export const LayersBodyComponent = props => {
|
|
16
|
+
const model = props.model;
|
|
17
|
+
const id = UUID.uuid4();
|
|
18
|
+
const [layerTree, setLayerTree] = useState((model === null || model === void 0 ? void 0 : model.getLayerTree()) || []);
|
|
19
|
+
const notifyCommands = () => {
|
|
20
|
+
// Notify commands that need updating
|
|
21
|
+
props.commands.notifyCommandChanged(CommandIDs.identify);
|
|
22
|
+
props.commands.notifyCommandChanged(CommandIDs.temporalController);
|
|
23
|
+
};
|
|
24
|
+
const _onDragOver = (e) => {
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
Private.dragInfo.dragOverElement = null;
|
|
28
|
+
Private.dragInfo.dragOverPosition = null;
|
|
29
|
+
};
|
|
30
|
+
const _onDrop = (e) => {
|
|
31
|
+
Private.dragIndicator.style.display = 'none';
|
|
32
|
+
if (model === undefined) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const { draggedElement, dragOverElement, dragOverPosition } = Private.dragInfo;
|
|
36
|
+
if (dragOverElement === 'error') {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!draggedElement) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const draggedId = draggedElement.dataset.id;
|
|
43
|
+
if (!draggedId) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Element has been dropped in the empty zone below the tree.
|
|
47
|
+
if (dragOverElement === null) {
|
|
48
|
+
model === null || model === void 0 ? void 0 : model.moveItemsToGroup([draggedId], '', 0);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const dragOverId = dragOverElement.dataset.id;
|
|
52
|
+
if (!dragOverId) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Handle the special case where we want to drop the element on top of the first
|
|
56
|
+
// element of a group.
|
|
57
|
+
if (dragOverElement.classList.contains(LAYER_GROUP_HEADER_CLASS) &&
|
|
58
|
+
dragOverPosition === 'below') {
|
|
59
|
+
model === null || model === void 0 ? void 0 : model.moveItemsToGroup([draggedId], dragOverId);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
model === null || model === void 0 ? void 0 : model.moveItemRelatedTo(draggedId, dragOverId, dragOverPosition === 'above');
|
|
63
|
+
};
|
|
64
|
+
const onSelect = ({ type, item, nodeId, event, }) => {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if (!props.model || !nodeId) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const selectedValue = (_b = (_a = props.model.localState) === null || _a === void 0 ? void 0 : _a.selected) === null || _b === void 0 ? void 0 : _b.value;
|
|
70
|
+
const node = document.getElementById(nodeId);
|
|
71
|
+
if (!node) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
node.tabIndex = 0;
|
|
75
|
+
node.focus();
|
|
76
|
+
// Early return if no selection exists
|
|
77
|
+
if (!selectedValue) {
|
|
78
|
+
resetSelected(type, nodeId, item);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Don't want to reset selected if right clicking a selected item
|
|
82
|
+
if (!event.ctrlKey && event.button === 2 && item in selectedValue) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Reset selection for normal left click
|
|
86
|
+
if (!event.ctrlKey) {
|
|
87
|
+
resetSelected(type, nodeId, item);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (nodeId) {
|
|
91
|
+
// Check if new selection is the same type as previous selections
|
|
92
|
+
const isSelectedSameType = Object.values(selectedValue).some(selection => selection.type === type);
|
|
93
|
+
if (!isSelectedSameType) {
|
|
94
|
+
// Selecting a new type, so reset selected
|
|
95
|
+
resetSelected(type, nodeId, item);
|
|
61
96
|
return;
|
|
62
97
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const [model, setModel] = useState((_a = props.model) === null || _a === void 0 ? void 0 : _a.jGISModel);
|
|
81
|
-
const [layerTree, setLayerTree] = useState((model === null || model === void 0 ? void 0 : model.getLayerTree()) || []);
|
|
98
|
+
// If types are the same add the selection
|
|
99
|
+
const updatedSelectedValue = Object.assign(Object.assign({}, selectedValue), { [item]: { type, selectedNodeId: nodeId } });
|
|
100
|
+
props.model.syncSelected(updatedSelectedValue, id);
|
|
101
|
+
notifyCommands();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const resetSelected = (type, nodeId, item) => {
|
|
105
|
+
const selection = {};
|
|
106
|
+
if (item && nodeId) {
|
|
107
|
+
selection[item] = {
|
|
108
|
+
type,
|
|
109
|
+
selectedNodeId: nodeId,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
props.model.syncSelected(selection, id);
|
|
113
|
+
notifyCommands();
|
|
114
|
+
};
|
|
82
115
|
/**
|
|
83
116
|
* Propagate the layer selection.
|
|
84
117
|
*/
|
|
85
118
|
const onItemClick = ({ type, item, nodeId, event, }) => {
|
|
86
|
-
|
|
119
|
+
onSelect({ type, item, nodeId, event });
|
|
87
120
|
};
|
|
88
121
|
/**
|
|
89
122
|
* Listen to the layers and layer tree changes.
|
|
@@ -100,15 +133,7 @@ const LayersBodyComponent = props => {
|
|
|
100
133
|
model === null || model === void 0 ? void 0 : model.sharedModel.layerTreeChanged.disconnect(updateLayers);
|
|
101
134
|
};
|
|
102
135
|
}, [model]);
|
|
103
|
-
|
|
104
|
-
* Update the model when it changes.
|
|
105
|
-
*/
|
|
106
|
-
(_b = props.model) === null || _b === void 0 ? void 0 : _b.documentChanged.connect((_, widget) => {
|
|
107
|
-
var _a;
|
|
108
|
-
setModel(widget === null || widget === void 0 ? void 0 : widget.model);
|
|
109
|
-
setLayerTree(((_a = widget === null || widget === void 0 ? void 0 : widget.model) === null || _a === void 0 ? void 0 : _a.getLayerTree()) || []);
|
|
110
|
-
});
|
|
111
|
-
return (React.createElement("div", { id: "jp-gis-layer-tree" }, layerTree
|
|
136
|
+
return (React.createElement("div", { id: "jp-gis-layer-tree", onDrop: _onDrop, onDragOver: _onDragOver }, layerTree
|
|
112
137
|
.slice()
|
|
113
138
|
.reverse()
|
|
114
139
|
.map(layer => typeof layer === 'string' ? (React.createElement(LayerComponent, { key: layer, gisModel: model, layerId: layer, onClick: onItemClick })) : (React.createElement(LayerGroupComponent, { key: layer.name, gisModel: model, group: layer, onClick: onItemClick, state: props.state })))));
|
|
@@ -216,7 +241,12 @@ const LayerComponent = props => {
|
|
|
216
241
|
const setSelection = (event) => {
|
|
217
242
|
var _a;
|
|
218
243
|
const childId = (_a = event.currentTarget.children.namedItem(id)) === null || _a === void 0 ? void 0 : _a.id;
|
|
219
|
-
onClick({
|
|
244
|
+
onClick({
|
|
245
|
+
type: 'layer',
|
|
246
|
+
item: layerId,
|
|
247
|
+
nodeId: childId,
|
|
248
|
+
event,
|
|
249
|
+
});
|
|
220
250
|
};
|
|
221
251
|
return (React.createElement("div", { className: `${LAYER_ITEM_CLASS} ${LAYER_CLASS}${selected ? ' jp-mod-selected' : ''}`, draggable: true, onDragStart: Private.onDragStart, onDragOver: Private.onDragOver, onDragEnd: Private.onDragEnd, "data-id": layerId },
|
|
222
252
|
React.createElement("div", { className: LAYER_TITLE_CLASS, onClick: setSelection, onContextMenu: setSelection },
|
package/lib/panelview/index.d.ts
CHANGED
package/lib/panelview/index.js
CHANGED
|
@@ -1,57 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IJupyterGISModel, SelectionType } from '@jupytergis/schema';
|
|
2
2
|
import { IStateDB } from '@jupyterlab/statedb';
|
|
3
|
-
import { SidePanel } from '@jupyterlab/ui-components';
|
|
4
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
5
|
-
import { Message } from '@lumino/messaging';
|
|
6
4
|
import { MouseEvent as ReactMouseEvent } from 'react';
|
|
7
|
-
import
|
|
8
|
-
/**
|
|
9
|
-
* Options of the left panel widget.
|
|
10
|
-
*/
|
|
11
|
-
export interface ILeftPanelOptions {
|
|
12
|
-
model: IControlPanelModel;
|
|
13
|
-
onSelect: ({ type, item, nodeId }: ILeftPanelClickHandlerParams) => void;
|
|
14
|
-
}
|
|
15
|
-
export interface ILayerPanelOptions extends ILeftPanelOptions {
|
|
16
|
-
state: IStateDB;
|
|
17
|
-
}
|
|
5
|
+
import * as React from 'react';
|
|
18
6
|
export interface ILeftPanelClickHandlerParams {
|
|
19
7
|
type: SelectionType;
|
|
20
8
|
item: string;
|
|
21
9
|
nodeId?: string;
|
|
22
10
|
event: ReactMouseEvent;
|
|
23
11
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
protected onBeforeDetach(msg: Message): void;
|
|
29
|
-
handleEvent(event: Event): void;
|
|
30
|
-
private _mouseUpEvent;
|
|
31
|
-
/**
|
|
32
|
-
* Function to call when a layer is selected from a component of the panel.
|
|
33
|
-
*
|
|
34
|
-
* @param item - the selected layer or group.
|
|
35
|
-
*/
|
|
36
|
-
private _onSelect;
|
|
37
|
-
resetSelected(type: SelectionType, nodeId?: string, item?: string): void;
|
|
38
|
-
private _notifyCommands;
|
|
39
|
-
private _handleFileChange;
|
|
40
|
-
private _currentModel;
|
|
41
|
-
private _lastSelectedNodeId;
|
|
42
|
-
private _model;
|
|
43
|
-
private _state;
|
|
44
|
-
private _commands;
|
|
45
|
-
}
|
|
46
|
-
export declare namespace LeftPanelWidget {
|
|
47
|
-
interface IOptions {
|
|
48
|
-
model: IControlPanelModel;
|
|
49
|
-
tracker: IJupyterGISTracker;
|
|
50
|
-
state: IStateDB;
|
|
51
|
-
commands: CommandRegistry;
|
|
52
|
-
}
|
|
53
|
-
interface IProps {
|
|
54
|
-
filePath?: string;
|
|
55
|
-
sharedModel?: JupyterGISDoc;
|
|
56
|
-
}
|
|
12
|
+
interface ILeftPanelProps {
|
|
13
|
+
model: IJupyterGISModel;
|
|
14
|
+
state: IStateDB;
|
|
15
|
+
commands: CommandRegistry;
|
|
57
16
|
}
|
|
17
|
+
export declare const LeftPanel: React.FC<ILeftPanelProps>;
|
|
18
|
+
export {};
|
|
@@ -1,154 +1,32 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Don't want to reset selected if right clicking a selected item
|
|
34
|
-
if (!event.ctrlKey && event.button === 2 && item in selectedValue) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
// Reset selection for normal left click
|
|
38
|
-
if (!event.ctrlKey) {
|
|
39
|
-
this.resetSelected(type, nodeId, item);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (nodeId) {
|
|
43
|
-
// Check if new selection is the same type as previous selections
|
|
44
|
-
const isSelectedSameType = Object.values(selectedValue).some(selection => selection.type === type);
|
|
45
|
-
if (!isSelectedSameType) {
|
|
46
|
-
// Selecting a new type, so reset selected
|
|
47
|
-
this.resetSelected(type, nodeId, item);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
// If types are the same add the selection
|
|
51
|
-
const updatedSelectedValue = Object.assign(Object.assign({}, selectedValue), { [item]: { type, selectedNodeId: nodeId } });
|
|
52
|
-
this._lastSelectedNodeId = nodeId;
|
|
53
|
-
jGISModel.syncSelected(updatedSelectedValue, this.id);
|
|
54
|
-
this._notifyCommands();
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
this.addClass('jGIS-sidepanel-widget');
|
|
58
|
-
this.addClass('data-jgis-keybinding');
|
|
59
|
-
this.node.tabIndex = 0;
|
|
60
|
-
this._model = options.model;
|
|
61
|
-
this._state = options.state;
|
|
62
|
-
this._commands = options.commands;
|
|
63
|
-
const header = new ControlPanelHeader();
|
|
64
|
-
this.header.addWidget(header);
|
|
65
|
-
const layerTree = new LayersPanel({
|
|
66
|
-
model: this._model,
|
|
67
|
-
state: this._state,
|
|
68
|
-
onSelect: this._onSelect,
|
|
69
|
-
});
|
|
70
|
-
layerTree.title.caption = 'Layer tree';
|
|
71
|
-
layerTree.title.label = 'Layers';
|
|
72
|
-
this.addWidget(layerTree);
|
|
73
|
-
const stacPanel = new StacPanel({
|
|
74
|
-
model: this._model,
|
|
75
|
-
tracker: options.tracker,
|
|
76
|
-
});
|
|
77
|
-
stacPanel.title.caption = 'STAC';
|
|
78
|
-
stacPanel.title.label = 'STAC';
|
|
79
|
-
this.addWidget(stacPanel);
|
|
80
|
-
const filterPanel = new FilterPanel({
|
|
81
|
-
model: this._model,
|
|
82
|
-
tracker: options.tracker,
|
|
83
|
-
});
|
|
84
|
-
filterPanel.title.caption = 'Filters';
|
|
85
|
-
filterPanel.title.label = 'Filters';
|
|
86
|
-
this.addWidget(filterPanel);
|
|
87
|
-
this._handleFileChange = () => {
|
|
88
|
-
var _a;
|
|
89
|
-
header.title.label = ((_a = this._currentModel) === null || _a === void 0 ? void 0 : _a.filePath) || '-';
|
|
90
|
-
};
|
|
91
|
-
options.tracker.currentChanged.connect((_, changed) => {
|
|
92
|
-
if (changed) {
|
|
93
|
-
if (this._currentModel) {
|
|
94
|
-
this._currentModel.pathChanged.disconnect(this._handleFileChange);
|
|
95
|
-
}
|
|
96
|
-
this._currentModel = changed.model;
|
|
97
|
-
header.title.label = changed.model.filePath;
|
|
98
|
-
this._currentModel.pathChanged.connect(this._handleFileChange);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
header.title.label = '-';
|
|
102
|
-
this._currentModel = null;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
dispose() {
|
|
107
|
-
super.dispose();
|
|
108
|
-
}
|
|
109
|
-
onAfterAttach(msg) {
|
|
110
|
-
super.onAfterAttach(msg);
|
|
111
|
-
const node = this.node;
|
|
112
|
-
node.addEventListener('mouseup', this);
|
|
113
|
-
}
|
|
114
|
-
onBeforeDetach(msg) {
|
|
115
|
-
super.onBeforeDetach(msg);
|
|
116
|
-
const node = this.node;
|
|
117
|
-
node.removeEventListener('mouseup', this);
|
|
118
|
-
}
|
|
119
|
-
handleEvent(event) {
|
|
120
|
-
switch (event.type) {
|
|
121
|
-
case 'mouseup':
|
|
122
|
-
this._mouseUpEvent(event);
|
|
123
|
-
break;
|
|
124
|
-
default:
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
_mouseUpEvent(event) {
|
|
129
|
-
// If we click on empty space in the layer panel, keep the focus on the last selected element
|
|
130
|
-
const node = document.getElementById(this._lastSelectedNodeId);
|
|
131
|
-
if (!node) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
node.focus();
|
|
135
|
-
}
|
|
136
|
-
resetSelected(type, nodeId, item) {
|
|
137
|
-
var _a, _b;
|
|
138
|
-
const selection = {};
|
|
139
|
-
if (item && nodeId) {
|
|
140
|
-
selection[item] = {
|
|
141
|
-
type,
|
|
142
|
-
selectedNodeId: nodeId,
|
|
143
|
-
};
|
|
144
|
-
this._lastSelectedNodeId = nodeId;
|
|
145
|
-
}
|
|
146
|
-
(_b = (_a = this._model) === null || _a === void 0 ? void 0 : _a.jGISModel) === null || _b === void 0 ? void 0 : _b.syncSelected(selection, this.id);
|
|
147
|
-
this._notifyCommands();
|
|
148
|
-
}
|
|
149
|
-
_notifyCommands() {
|
|
150
|
-
// Notify commands that need updating
|
|
151
|
-
this._commands.notifyCommandChanged(CommandIDs.identify);
|
|
152
|
-
this._commands.notifyCommandChanged(CommandIDs.temporalController);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { LayersBodyComponent } from './components/layers';
|
|
3
|
+
import { PanelTabs, TabsContent, TabsList, TabsTrigger, } from '../shared/components/Tabs';
|
|
4
|
+
import StacPanel from '../stacBrowser/components/StacPanel';
|
|
5
|
+
import FilterComponent from './components/filter-panel/Filter';
|
|
6
|
+
export const LeftPanel = (props) => {
|
|
7
|
+
const tabInfo = [
|
|
8
|
+
{ name: 'layers', title: 'Layers' },
|
|
9
|
+
{ name: 'stac', title: 'Stac Browser' },
|
|
10
|
+
{ name: 'filters', title: 'Filters' },
|
|
11
|
+
];
|
|
12
|
+
const [curTab, setCurTab] = React.useState(tabInfo[0].name);
|
|
13
|
+
return (React.createElement("div", { className: "jgis-left-panel-container" },
|
|
14
|
+
React.createElement(PanelTabs, { curTab: curTab, className: "jgis-panel-tabs" },
|
|
15
|
+
React.createElement(TabsList, null, tabInfo.map(e => {
|
|
16
|
+
return (React.createElement(TabsTrigger, { className: "jGIS-layer-browser-category", value: e.name, onClick: () => {
|
|
17
|
+
if (curTab !== e.name) {
|
|
18
|
+
setCurTab(e.name);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
setCurTab('');
|
|
22
|
+
}
|
|
23
|
+
} }, e.title));
|
|
24
|
+
})),
|
|
25
|
+
React.createElement(TabsContent, { value: "layers", className: "jgis-panel-tab-content jp-gis-layerPanel" },
|
|
26
|
+
React.createElement(LayersBodyComponent, { model: props.model, commands: props.commands, state: props.state })),
|
|
27
|
+
React.createElement(TabsContent, { value: "stac" },
|
|
28
|
+
React.createElement(StacPanel, { model: props.model })),
|
|
29
|
+
React.createElement(TabsContent, { value: "filters", className: "jgis-panel-tab-content" },
|
|
30
|
+
React.createElement(FilterComponent, { model: props.model }),
|
|
31
|
+
","))));
|
|
32
|
+
};
|