@jupytergis/base 0.2.1 → 0.4.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.js +2 -2
- package/lib/annotations/model.d.ts +6 -7
- package/lib/annotations/model.js +15 -15
- package/lib/commands.d.ts +2 -3
- package/lib/commands.js +146 -62
- package/lib/constants.d.ts +3 -0
- package/lib/constants.js +5 -1
- package/lib/dialogs/formdialog.d.ts +5 -0
- package/lib/dialogs/formdialog.js +2 -2
- package/lib/dialogs/layerBrowserDialog.d.ts +4 -5
- package/lib/dialogs/layerBrowserDialog.js +9 -9
- package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.js +2 -1
- package/lib/dialogs/symbology/hooks/useGetBandInfo.d.ts +26 -0
- package/lib/dialogs/symbology/hooks/useGetBandInfo.js +64 -0
- package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +1 -1
- package/lib/dialogs/symbology/hooks/useGetProperties.js +12 -9
- package/lib/dialogs/symbology/symbologyDialog.d.ts +2 -3
- package/lib/dialogs/symbology/symbologyDialog.js +10 -9
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +1 -1
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +16 -3
- package/lib/dialogs/symbology/tiff_layer/components/BandRow.d.ts +16 -3
- package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +21 -7
- package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.d.ts +4 -0
- package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +85 -0
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.d.ts +1 -20
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +25 -65
- package/lib/dialogs/symbology/vector_layer/VectorRendering.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/VectorRendering.js +18 -13
- package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/Categorized.js +30 -19
- package/lib/dialogs/symbology/vector_layer/types/Graduated.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +16 -13
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.d.ts +4 -0
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +77 -0
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +4 -3
- package/lib/formbuilder/creationform.d.ts +6 -2
- package/lib/formbuilder/creationform.js +6 -6
- package/lib/formbuilder/editform.d.ts +2 -2
- package/lib/formbuilder/editform.js +14 -9
- package/lib/formbuilder/formselectors.js +11 -1
- package/lib/formbuilder/objectform/baseform.d.ts +12 -3
- package/lib/formbuilder/objectform/baseform.js +39 -0
- package/lib/formbuilder/objectform/fileselectorwidget.d.ts +2 -0
- package/lib/formbuilder/objectform/fileselectorwidget.js +88 -0
- package/lib/formbuilder/objectform/geojsonsource.d.ts +5 -7
- package/lib/formbuilder/objectform/geojsonsource.js +8 -24
- package/lib/formbuilder/objectform/geotiffsource.d.ts +5 -1
- package/lib/formbuilder/objectform/geotiffsource.js +64 -18
- package/lib/formbuilder/objectform/heatmapLayerForm.d.ts +11 -0
- package/lib/formbuilder/objectform/heatmapLayerForm.js +60 -0
- package/lib/formbuilder/objectform/layerform.d.ts +2 -0
- package/lib/formbuilder/objectform/layerform.js +6 -0
- package/lib/formbuilder/objectform/pathbasedsource.d.ts +19 -0
- package/lib/formbuilder/objectform/pathbasedsource.js +98 -0
- package/lib/formbuilder/objectform/vectorlayerform.d.ts +0 -2
- package/lib/formbuilder/objectform/vectorlayerform.js +0 -59
- package/lib/icons.d.ts +1 -0
- package/lib/icons.js +5 -0
- package/lib/keybindings.json +62 -0
- package/lib/mainview/TemporalSlider.d.ts +8 -0
- package/lib/mainview/TemporalSlider.js +303 -0
- package/lib/mainview/mainView.d.ts +46 -8
- package/lib/mainview/mainView.js +431 -144
- package/lib/mainview/mainviewmodel.d.ts +4 -0
- package/lib/mainview/mainviewmodel.js +4 -0
- package/lib/mainview/mainviewwidget.d.ts +0 -2
- package/lib/mainview/mainviewwidget.js +0 -2
- package/lib/panelview/annotationPanel.js +5 -5
- package/lib/panelview/components/filter-panel/Filter.js +8 -24
- package/lib/panelview/components/identify-panel/IdentifyPanel.js +1 -1
- package/lib/panelview/components/layers.js +2 -2
- package/lib/panelview/components/sources.js +1 -1
- package/lib/panelview/leftpanel.d.ts +3 -0
- package/lib/panelview/leftpanel.js +5 -1
- package/lib/panelview/model.js +8 -8
- package/lib/panelview/objectproperties.js +10 -10
- package/lib/panelview/rightpanel.d.ts +1 -1
- package/lib/panelview/rightpanel.js +10 -10
- package/lib/statusbar/StatusBar.d.ts +13 -0
- package/lib/statusbar/StatusBar.js +52 -0
- package/lib/toolbar/widget.d.ts +1 -1
- package/lib/toolbar/widget.js +44 -37
- package/lib/tools.d.ts +50 -7
- package/lib/tools.js +394 -12
- package/lib/types.d.ts +2 -0
- package/lib/widget.d.ts +29 -5
- package/lib/widget.js +41 -7
- package/package.json +17 -5
- package/style/base.css +11 -0
- package/style/icons/logo_mini_qgz.svg +31 -0
- package/style/leftPanel.css +8 -0
- package/style/statusBar.css +16 -0
- package/style/symbologyDialog.css +7 -1
- package/style/temporalSlider.css +47 -0
|
@@ -1,36 +1,35 @@
|
|
|
1
1
|
import { Button } from '@jupyterlab/ui-components';
|
|
2
2
|
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { Spinner } from '../../../../mainview/spinner';
|
|
4
4
|
import { GlobalStateDbManager } from '../../../../store';
|
|
5
|
-
import
|
|
5
|
+
import { GeoTiffClassifications } from '../../classificationModes';
|
|
6
6
|
import ColorRamp from '../../components/color_ramp/ColorRamp';
|
|
7
7
|
import StopRow from '../../components/color_stops/StopRow';
|
|
8
|
+
import useGetBandInfo from '../../hooks/useGetBandInfo';
|
|
8
9
|
import { Utils } from '../../symbologyUtils';
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) => {
|
|
12
|
-
const functions = ['discrete', 'linear', 'exact'];
|
|
13
|
-
const modeOptions = ['continuous', 'equal interval', 'quantile'];
|
|
14
|
-
const stopRowsRef = useRef();
|
|
15
|
-
const bandRowsRef = useRef([]);
|
|
16
|
-
const selectedFunctionRef = useRef();
|
|
17
|
-
const colorRampOptionsRef = useRef();
|
|
18
|
-
const layerStateRef = useRef();
|
|
19
|
-
const selectedBandRef = useRef();
|
|
20
|
-
const [layerState, setLayerState] = useState();
|
|
21
|
-
const [selectedBand, setSelectedBand] = useState(1);
|
|
22
|
-
const [stopRows, setStopRows] = useState([]);
|
|
23
|
-
const [bandRows, setBandRows] = useState([]);
|
|
24
|
-
const [selectedFunction, setSelectedFunction] = useState('linear');
|
|
25
|
-
const [colorRampOptions, setColorRampOptions] = useState();
|
|
10
|
+
import BandRow from '../components/BandRow';
|
|
11
|
+
const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId }) => {
|
|
26
12
|
if (!layerId) {
|
|
27
13
|
return;
|
|
28
14
|
}
|
|
29
|
-
const layer =
|
|
15
|
+
const layer = model.getLayer(layerId);
|
|
30
16
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
31
17
|
return;
|
|
32
18
|
}
|
|
19
|
+
const functions = ['discrete', 'linear', 'exact'];
|
|
20
|
+
const modeOptions = ['continuous', 'equal interval', 'quantile'];
|
|
33
21
|
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
|
|
22
|
+
const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer);
|
|
23
|
+
const [layerState, setLayerState] = useState();
|
|
24
|
+
const [selectedBand, setSelectedBand] = useState(1);
|
|
25
|
+
const [stopRows, setStopRows] = useState([]);
|
|
26
|
+
const [selectedFunction, setSelectedFunction] = useState('linear');
|
|
27
|
+
const [colorRampOptions, setColorRampOptions] = useState();
|
|
28
|
+
const stopRowsRef = useRef();
|
|
29
|
+
const bandRowsRef = useRef([]);
|
|
30
|
+
const selectedFunctionRef = useRef();
|
|
31
|
+
const colorRampOptionsRef = useRef();
|
|
32
|
+
const selectedBandRef = useRef();
|
|
34
33
|
useEffect(() => {
|
|
35
34
|
populateOptions();
|
|
36
35
|
okSignalPromise.promise.then(okSignal => {
|
|
@@ -42,10 +41,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
42
41
|
});
|
|
43
42
|
};
|
|
44
43
|
}, []);
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
layerStateRef.current = layerState;
|
|
47
|
-
getBandInfo();
|
|
48
|
-
}, [layerState]);
|
|
49
44
|
useEffect(() => {
|
|
50
45
|
bandRowsRef.current = bandRows;
|
|
51
46
|
buildColorInfo();
|
|
@@ -55,7 +50,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
55
50
|
selectedFunctionRef.current = selectedFunction;
|
|
56
51
|
colorRampOptionsRef.current = colorRampOptions;
|
|
57
52
|
selectedBandRef.current = selectedBand;
|
|
58
|
-
layerStateRef.current = layerState;
|
|
59
53
|
}, [stopRows, selectedFunction, colorRampOptions, selectedBand, layerState]);
|
|
60
54
|
const populateOptions = async () => {
|
|
61
55
|
var _a, _b, _c, _d;
|
|
@@ -67,39 +61,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
67
61
|
setSelectedBand(band);
|
|
68
62
|
setSelectedFunction(interpolation);
|
|
69
63
|
};
|
|
70
|
-
const preloadGeoTiffFile = async (sourceInfo) => {
|
|
71
|
-
return await loadGeoTIFFWithCache(sourceInfo);
|
|
72
|
-
};
|
|
73
|
-
const getBandInfo = async () => {
|
|
74
|
-
var _a, _b;
|
|
75
|
-
const bandsArr = [];
|
|
76
|
-
const source = context.model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
|
|
77
|
-
const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
|
|
78
|
-
if (!(sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url)) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
// Preload the file only once
|
|
82
|
-
const preloadedFile = await preloadGeoTiffFile(sourceInfo);
|
|
83
|
-
const { file, metadata, sourceUrl } = Object.assign({}, preloadedFile);
|
|
84
|
-
if (file && metadata && sourceUrl === sourceInfo.url) {
|
|
85
|
-
metadata['bands'].forEach((bandData) => {
|
|
86
|
-
var _a, _b;
|
|
87
|
-
bandsArr.push({
|
|
88
|
-
band: bandData.band,
|
|
89
|
-
colorInterpretation: bandData.colorInterpretation,
|
|
90
|
-
stats: {
|
|
91
|
-
minimum: (_a = sourceInfo.min) !== null && _a !== void 0 ? _a : bandData.minimum,
|
|
92
|
-
maximum: (_b = sourceInfo.max) !== null && _b !== void 0 ? _b : bandData.maximum,
|
|
93
|
-
mean: bandData.mean,
|
|
94
|
-
stdDev: bandData.stdDev
|
|
95
|
-
},
|
|
96
|
-
metadata: bandData.metadata,
|
|
97
|
-
histogram: bandData.histogram
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
setBandRows(bandsArr);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
64
|
const buildColorInfo = () => {
|
|
104
65
|
var _a;
|
|
105
66
|
// This it to parse a color object on the layer
|
|
@@ -159,7 +120,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
159
120
|
return;
|
|
160
121
|
}
|
|
161
122
|
const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
|
|
162
|
-
const source =
|
|
123
|
+
const source = model.getSource(sourceId);
|
|
163
124
|
if (!source || !source.parameters) {
|
|
164
125
|
return;
|
|
165
126
|
}
|
|
@@ -168,7 +129,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
168
129
|
sourceInfo.min = bandRow.stats.minimum;
|
|
169
130
|
sourceInfo.max = bandRow.stats.maximum;
|
|
170
131
|
source.parameters.urls[0] = sourceInfo;
|
|
171
|
-
|
|
132
|
+
model.sharedModel.updateSource(sourceId, source);
|
|
172
133
|
// Update layer
|
|
173
134
|
if (!layer.parameters) {
|
|
174
135
|
return;
|
|
@@ -232,7 +193,8 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
232
193
|
};
|
|
233
194
|
layer.parameters.symbologyState = symbologyState;
|
|
234
195
|
layer.parameters.color = colorExpr;
|
|
235
|
-
|
|
196
|
+
layer.type = 'WebGlLayer';
|
|
197
|
+
model.sharedModel.updateLayer(layerId, layer);
|
|
236
198
|
cancel();
|
|
237
199
|
};
|
|
238
200
|
const addStopRow = () => {
|
|
@@ -259,7 +221,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
259
221
|
});
|
|
260
222
|
let stops = [];
|
|
261
223
|
const currentBand = bandRows[selectedBand - 1];
|
|
262
|
-
const source =
|
|
224
|
+
const source = model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
|
|
263
225
|
const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
|
|
264
226
|
const nClasses = selectedMode === 'continuous' ? 52 : +numberOfShades;
|
|
265
227
|
setIsLoading(true);
|
|
@@ -297,9 +259,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
|
|
|
297
259
|
return (value * (1 - 0) - min * (1 - 0)) / (max - min);
|
|
298
260
|
};
|
|
299
261
|
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
300
|
-
React.createElement("div", { className: "jp-gis-band-container" },
|
|
301
|
-
// Band numbers are 1 indexed
|
|
302
|
-
, {
|
|
262
|
+
React.createElement("div", { className: "jp-gis-band-container" }, loading ? (React.createElement(Spinner, { loading: loading })) : (React.createElement(BandRow, { label: "Band",
|
|
303
263
|
// Band numbers are 1 indexed
|
|
304
264
|
index: selectedBand - 1, bandRow: bandRows[selectedBand - 1], bandRows: bandRows, setSelectedBand: setSelectedBand, setBandRows: setBandRows }))),
|
|
305
265
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ISymbologyDialogProps } from '../symbologyDialog';
|
|
3
|
-
declare const VectorRendering: ({
|
|
3
|
+
declare const VectorRendering: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
4
4
|
export default VectorRendering;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import Categorized from './types/Categorized';
|
|
2
3
|
import Graduated from './types/Graduated';
|
|
4
|
+
import Heatmap from './types/Heatmap';
|
|
3
5
|
import SimpleSymbol from './types/SimpleSymbol';
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const [selectedRenderType, setSelectedRenderType] = useState('Single Symbol');
|
|
6
|
+
const VectorRendering = ({ model, state, okSignalPromise, cancel, layerId }) => {
|
|
7
|
+
const [selectedRenderType, setSelectedRenderType] = useState('');
|
|
7
8
|
const [componentToRender, setComponentToRender] = useState(null);
|
|
8
9
|
const [renderTypeOptions, setRenderTypeOptions] = useState([
|
|
9
10
|
'Single Symbol'
|
|
@@ -12,32 +13,36 @@ const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) =
|
|
|
12
13
|
if (!layerId) {
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
|
-
const layer =
|
|
16
|
+
const layer = model.getLayer(layerId);
|
|
16
17
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
useEffect(() => {
|
|
20
21
|
var _a, _b;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const options = ['Single Symbol', 'Graduated', 'Categorized'];
|
|
25
|
-
setRenderTypeOptions(options);
|
|
22
|
+
let renderType = (_b = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) === null || _b === void 0 ? void 0 : _b.renderType;
|
|
23
|
+
if (!renderType) {
|
|
24
|
+
renderType = layer.type === 'HeatmapLayer' ? 'Heatmap' : 'Single Symbol';
|
|
26
25
|
}
|
|
26
|
+
setSelectedRenderType(renderType);
|
|
27
|
+
const options = ['Single Symbol', 'Graduated', 'Categorized', 'Heatmap'];
|
|
28
|
+
setRenderTypeOptions(options);
|
|
27
29
|
}, []);
|
|
28
30
|
useEffect(() => {
|
|
29
31
|
switch (selectedRenderType) {
|
|
30
32
|
case 'Single Symbol':
|
|
31
|
-
RenderComponent = (React.createElement(SimpleSymbol, {
|
|
33
|
+
RenderComponent = (React.createElement(SimpleSymbol, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
32
34
|
break;
|
|
33
35
|
case 'Graduated':
|
|
34
|
-
RenderComponent = (React.createElement(Graduated, {
|
|
36
|
+
RenderComponent = (React.createElement(Graduated, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
35
37
|
break;
|
|
36
38
|
case 'Categorized':
|
|
37
|
-
RenderComponent = (React.createElement(Categorized, {
|
|
39
|
+
RenderComponent = (React.createElement(Categorized, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
40
|
+
break;
|
|
41
|
+
case 'Heatmap':
|
|
42
|
+
RenderComponent = (React.createElement(Heatmap, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
38
43
|
break;
|
|
39
44
|
default:
|
|
40
|
-
RenderComponent = React.createElement("div", null, "
|
|
45
|
+
RenderComponent = React.createElement("div", null, "Select a render type");
|
|
41
46
|
}
|
|
42
47
|
setComponentToRender(RenderComponent);
|
|
43
48
|
}, [selectedRenderType]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ISymbologyDialogProps } from '../../symbologyDialog';
|
|
3
|
-
declare const Categorized: ({
|
|
3
|
+
declare const Categorized: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
4
4
|
export default Categorized;
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { getNumericFeatureAttributes } from '../../../../tools';
|
|
3
|
+
import ColorRamp from '../../components/color_ramp/ColorRamp';
|
|
4
4
|
import StopContainer from '../../components/color_stops/StopContainer';
|
|
5
|
+
import { useGetProperties } from '../../hooks/useGetProperties';
|
|
5
6
|
import { Utils, VectorUtils } from '../../symbologyUtils';
|
|
6
|
-
import
|
|
7
|
-
const Categorized = ({
|
|
7
|
+
import ValueSelect from '../components/ValueSelect';
|
|
8
|
+
const Categorized = ({ model, state, okSignalPromise, cancel, layerId }) => {
|
|
8
9
|
const selectedValueRef = useRef();
|
|
9
10
|
const stopRowsRef = useRef();
|
|
10
11
|
const colorRampOptionsRef = useRef();
|
|
11
12
|
const [selectedValue, setSelectedValue] = useState('');
|
|
12
13
|
const [stopRows, setStopRows] = useState([]);
|
|
13
14
|
const [colorRampOptions, setColorRampOptions] = useState();
|
|
15
|
+
const [features, setFeatures] = useState({});
|
|
14
16
|
if (!layerId) {
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
17
|
-
const layer =
|
|
19
|
+
const layer = model.getLayer(layerId);
|
|
18
20
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
19
21
|
return;
|
|
20
22
|
}
|
|
21
|
-
const {
|
|
23
|
+
const { featureProperties } = useGetProperties({
|
|
22
24
|
layerId,
|
|
23
|
-
model:
|
|
25
|
+
model: model
|
|
24
26
|
});
|
|
25
27
|
useEffect(() => {
|
|
26
28
|
const valueColorPairs = VectorUtils.buildColorInfo(layer);
|
|
@@ -35,19 +37,19 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
35
37
|
};
|
|
36
38
|
}, []);
|
|
37
39
|
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
var _a, _b;
|
|
41
|
+
// We only want number values here
|
|
42
|
+
const numericFeatures = getNumericFeatureAttributes(featureProperties);
|
|
43
|
+
setFeatures(numericFeatures);
|
|
44
|
+
const layerParams = layer.parameters;
|
|
45
|
+
const value = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(numericFeatures)[0];
|
|
46
|
+
setSelectedValue(value);
|
|
47
|
+
}, [featureProperties]);
|
|
40
48
|
useEffect(() => {
|
|
41
49
|
selectedValueRef.current = selectedValue;
|
|
42
50
|
stopRowsRef.current = stopRows;
|
|
43
51
|
colorRampOptionsRef.current = colorRampOptions;
|
|
44
52
|
}, [selectedValue, stopRows, colorRampOptions]);
|
|
45
|
-
const populateOptions = async () => {
|
|
46
|
-
var _a, _b;
|
|
47
|
-
const layerParams = layer.parameters;
|
|
48
|
-
const value = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(featureProps)[0];
|
|
49
|
-
setSelectedValue(value);
|
|
50
|
-
};
|
|
51
53
|
const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp, setIsLoading) => {
|
|
52
54
|
setColorRampOptions({
|
|
53
55
|
selectedFunction: '',
|
|
@@ -55,7 +57,7 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
55
57
|
numberOfShades: '',
|
|
56
58
|
selectedMode: ''
|
|
57
59
|
});
|
|
58
|
-
const stops = Array.from(
|
|
60
|
+
const stops = Array.from(features[selectedValue]).sort((a, b) => a - b);
|
|
59
61
|
const valueColorPairs = Utils.getValueColorPairs(stops, selectedRamp, stops.length);
|
|
60
62
|
setStopRows(valueColorPairs);
|
|
61
63
|
};
|
|
@@ -73,7 +75,15 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
73
75
|
// fallback value
|
|
74
76
|
colorExpr.push([0, 0, 0, 0.0]);
|
|
75
77
|
const newStyle = Object.assign({}, layer.parameters.color);
|
|
76
|
-
|
|
78
|
+
if (layer.parameters.type === 'fill') {
|
|
79
|
+
newStyle['fill-color'] = colorExpr;
|
|
80
|
+
}
|
|
81
|
+
if (layer.parameters.type === 'line') {
|
|
82
|
+
newStyle['stroke-color'] = colorExpr;
|
|
83
|
+
}
|
|
84
|
+
if (layer.parameters.type === 'circle') {
|
|
85
|
+
newStyle['circle-fill-color'] = colorExpr;
|
|
86
|
+
}
|
|
77
87
|
const symbologyState = {
|
|
78
88
|
renderType: 'Categorized',
|
|
79
89
|
value: selectedValueRef.current,
|
|
@@ -83,11 +93,12 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
83
93
|
};
|
|
84
94
|
layer.parameters.symbologyState = symbologyState;
|
|
85
95
|
layer.parameters.color = newStyle;
|
|
86
|
-
|
|
96
|
+
layer.type = 'VectorLayer';
|
|
97
|
+
model.sharedModel.updateLayer(layerId, layer);
|
|
87
98
|
cancel();
|
|
88
99
|
};
|
|
89
100
|
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
90
|
-
React.createElement(ValueSelect, { featureProperties:
|
|
101
|
+
React.createElement(ValueSelect, { featureProperties: features, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
|
|
91
102
|
React.createElement(ColorRamp, { layerParams: layer.parameters, modeOptions: [], classifyFunc: buildColorInfoFromClassification, showModeRow: false }),
|
|
92
103
|
React.createElement(StopContainer, { selectedMethod: '', stopRows: stopRows, setStopRows: setStopRows })));
|
|
93
104
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ISymbologyDialogProps } from '../../symbologyDialog';
|
|
3
|
-
declare const Graduated: ({
|
|
3
|
+
declare const Graduated: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
4
4
|
export default Graduated;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { getNumericFeatureAttributes } from '../../../../tools';
|
|
2
3
|
import { VectorClassifications } from '../../classificationModes';
|
|
3
4
|
import ColorRamp from '../../components/color_ramp/ColorRamp';
|
|
4
|
-
import ValueSelect from '../components/ValueSelect';
|
|
5
5
|
import StopContainer from '../../components/color_stops/StopContainer';
|
|
6
6
|
import { useGetProperties } from '../../hooks/useGetProperties';
|
|
7
7
|
import { Utils, VectorUtils } from '../../symbologyUtils';
|
|
8
|
-
|
|
8
|
+
import ValueSelect from '../components/ValueSelect';
|
|
9
|
+
const Graduated = ({ model, state, okSignalPromise, cancel, layerId }) => {
|
|
9
10
|
const modeOptions = [
|
|
10
11
|
'quantile',
|
|
11
12
|
'equal interval',
|
|
@@ -21,17 +22,18 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
21
22
|
const [selectedMethod, setSelectedMethod] = useState('color');
|
|
22
23
|
const [stopRows, setStopRows] = useState([]);
|
|
23
24
|
const [methodOptions, setMethodOptions] = useState(['color']);
|
|
25
|
+
const [features, setFeatures] = useState({});
|
|
24
26
|
const [colorRampOptions, setColorRampOptions] = useState();
|
|
25
27
|
if (!layerId) {
|
|
26
28
|
return;
|
|
27
29
|
}
|
|
28
|
-
const layer =
|
|
30
|
+
const layer = model.getLayer(layerId);
|
|
29
31
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
32
|
-
const {
|
|
34
|
+
const { featureProperties } = useGetProperties({
|
|
33
35
|
layerId,
|
|
34
|
-
model:
|
|
36
|
+
model: model
|
|
35
37
|
});
|
|
36
38
|
useEffect(() => {
|
|
37
39
|
var _a, _b;
|
|
@@ -61,21 +63,21 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
61
63
|
colorRampOptionsRef.current = colorRampOptions;
|
|
62
64
|
}, [selectedValue, selectedMethod, stopRows, colorRampOptions]);
|
|
63
65
|
useEffect(() => {
|
|
64
|
-
populateOptions();
|
|
65
|
-
}, [featureProps]);
|
|
66
|
-
const populateOptions = async () => {
|
|
67
66
|
var _a, _b, _c, _d, _e;
|
|
68
67
|
// Set up method options
|
|
69
68
|
if (((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.type) === 'circle') {
|
|
70
69
|
const options = ['color', 'radius'];
|
|
71
70
|
setMethodOptions(options);
|
|
72
71
|
}
|
|
72
|
+
// We only want number values here
|
|
73
|
+
const numericFeatures = getNumericFeatureAttributes(featureProperties);
|
|
74
|
+
setFeatures(numericFeatures);
|
|
73
75
|
const layerParams = layer.parameters;
|
|
74
|
-
const value = (_c = (_b = layerParams.symbologyState) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : Object.keys(
|
|
76
|
+
const value = (_c = (_b = layerParams.symbologyState) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : Object.keys(numericFeatures)[0];
|
|
75
77
|
const method = (_e = (_d = layerParams.symbologyState) === null || _d === void 0 ? void 0 : _d.method) !== null && _e !== void 0 ? _e : 'color';
|
|
76
78
|
setSelectedValue(value);
|
|
77
79
|
setSelectedMethod(method);
|
|
78
|
-
};
|
|
80
|
+
}, [featureProperties]);
|
|
79
81
|
const handleOk = () => {
|
|
80
82
|
var _a, _b, _c, _d;
|
|
81
83
|
if (!layer.parameters) {
|
|
@@ -116,7 +118,8 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
116
118
|
};
|
|
117
119
|
layer.parameters.symbologyState = symbologyState;
|
|
118
120
|
layer.parameters.color = newStyle;
|
|
119
|
-
|
|
121
|
+
layer.type = 'VectorLayer';
|
|
122
|
+
model.sharedModel.updateLayer(layerId, layer);
|
|
120
123
|
cancel();
|
|
121
124
|
};
|
|
122
125
|
const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp) => {
|
|
@@ -126,7 +129,7 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
126
129
|
selectedMode
|
|
127
130
|
});
|
|
128
131
|
let stops;
|
|
129
|
-
const values = Array.from(
|
|
132
|
+
const values = Array.from(features[selectedValue]);
|
|
130
133
|
switch (selectedMode) {
|
|
131
134
|
case 'quantile':
|
|
132
135
|
stops = VectorClassifications.calculateQuantileBreaks(values, +numberOfShades);
|
|
@@ -159,7 +162,7 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
159
162
|
setStopRows(stopOutputPairs);
|
|
160
163
|
};
|
|
161
164
|
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
162
|
-
React.createElement(ValueSelect, { featureProperties:
|
|
165
|
+
React.createElement(ValueSelect, { featureProperties: features, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
|
|
163
166
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
164
167
|
React.createElement("label", { htmlFor: 'vector-method-select' }, "Method:"),
|
|
165
168
|
React.createElement("select", { name: 'vector-method-select', onChange: event => setSelectedMethod(event.target.value), className: "jp-mod-styled" }, methodOptions.map((method, index) => (React.createElement("option", { key: index, value: method, selected: method === selectedMethod, className: "jp-mod-styled" }, method))))),
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import colormap from 'colormap';
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import CanvasSelectComponent from '../../components/color_ramp/CanvasSelectComponent';
|
|
4
|
+
const Heatmap = ({ model, state, okSignalPromise, cancel, layerId }) => {
|
|
5
|
+
if (!layerId) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const layer = model.getLayer(layerId);
|
|
9
|
+
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const [selectedRamp, setSelectedRamp] = useState('');
|
|
13
|
+
const [heatmapOptions, setHetamapOptions] = useState({
|
|
14
|
+
radius: 8,
|
|
15
|
+
blur: 15
|
|
16
|
+
});
|
|
17
|
+
const selectedRampRef = useRef('cool');
|
|
18
|
+
const heatmapOptionsRef = useRef({
|
|
19
|
+
radius: 8,
|
|
20
|
+
blur: 15
|
|
21
|
+
});
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
populateOptions();
|
|
24
|
+
okSignalPromise.promise.then(okSignal => {
|
|
25
|
+
okSignal.connect(handleOk, this);
|
|
26
|
+
});
|
|
27
|
+
return () => {
|
|
28
|
+
okSignalPromise.promise.then(okSignal => {
|
|
29
|
+
okSignal.disconnect(handleOk, this);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}, []);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
selectedRampRef.current = selectedRamp;
|
|
35
|
+
heatmapOptionsRef.current = heatmapOptions;
|
|
36
|
+
}, [selectedRamp, heatmapOptions]);
|
|
37
|
+
const populateOptions = async () => {
|
|
38
|
+
var _a;
|
|
39
|
+
let colorRamp;
|
|
40
|
+
if ((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) {
|
|
41
|
+
colorRamp = layer.parameters.symbologyState.colorRamp;
|
|
42
|
+
}
|
|
43
|
+
setSelectedRamp(colorRamp ? colorRamp : 'cool');
|
|
44
|
+
};
|
|
45
|
+
const handleOk = () => {
|
|
46
|
+
if (!layer.parameters) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const colorMap = colormap({
|
|
50
|
+
colormap: selectedRampRef.current,
|
|
51
|
+
nshades: 9,
|
|
52
|
+
format: 'hex'
|
|
53
|
+
});
|
|
54
|
+
const symbologyState = {
|
|
55
|
+
renderType: 'Heatmap',
|
|
56
|
+
colorRamp: selectedRampRef.current
|
|
57
|
+
};
|
|
58
|
+
layer.parameters.symbologyState = symbologyState;
|
|
59
|
+
layer.parameters.color = colorMap;
|
|
60
|
+
layer.parameters.blur = heatmapOptionsRef.current.blur;
|
|
61
|
+
layer.parameters.radius = heatmapOptionsRef.current.radius;
|
|
62
|
+
layer.type = 'HeatmapLayer';
|
|
63
|
+
model.sharedModel.updateLayer(layerId, layer);
|
|
64
|
+
cancel();
|
|
65
|
+
};
|
|
66
|
+
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
67
|
+
React.createElement("div", { className: "jp-gis-symbology-row jp-gis-heatmap" },
|
|
68
|
+
React.createElement("label", { htmlFor: "color-ramp-select" }, "Color Ramp:"),
|
|
69
|
+
React.createElement(CanvasSelectComponent, { selectedRamp: selectedRamp, setSelected: setSelectedRamp })),
|
|
70
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
71
|
+
React.createElement("label", { htmlFor: 'vector-value-select' }, "Radius:"),
|
|
72
|
+
React.createElement("input", { type: "number", value: heatmapOptions.radius, className: "jp-mod-styled", onChange: event => setHetamapOptions(prevState => (Object.assign(Object.assign({}, prevState), { radius: +event.target.value }))) })),
|
|
73
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
74
|
+
React.createElement("label", { htmlFor: 'vector-value-select' }, "Blur:"),
|
|
75
|
+
React.createElement("input", { type: "number", value: heatmapOptions.blur, className: "jp-mod-styled", onChange: event => setHetamapOptions(prevState => (Object.assign(Object.assign({}, prevState), { blur: +event.target.value }))) }))));
|
|
76
|
+
};
|
|
77
|
+
export default Heatmap;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ISymbologyDialogProps } from '../../symbologyDialog';
|
|
3
|
-
declare const SimpleSymbol: ({
|
|
3
|
+
declare const SimpleSymbol: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
4
4
|
export default SimpleSymbol;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { parseColor } from '../../../../tools';
|
|
3
|
-
const SimpleSymbol = ({
|
|
3
|
+
const SimpleSymbol = ({ model, state, okSignalPromise, cancel, layerId }) => {
|
|
4
4
|
const styleRef = useRef();
|
|
5
5
|
const [useCircleStuff, setUseCircleStuff] = useState(false);
|
|
6
6
|
const [style, setStyle] = useState({
|
|
@@ -16,7 +16,7 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
16
16
|
if (!layerId) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
const layer =
|
|
19
|
+
const layer = model.getLayer(layerId);
|
|
20
20
|
if (!layer) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
@@ -75,7 +75,8 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
|
75
75
|
};
|
|
76
76
|
layer.parameters.symbologyState = symbologyState;
|
|
77
77
|
layer.parameters.color = styleExpr;
|
|
78
|
-
|
|
78
|
+
layer.type = 'VectorLayer';
|
|
79
|
+
model.sharedModel.updateLayer(layerId, layer);
|
|
79
80
|
cancel();
|
|
80
81
|
};
|
|
81
82
|
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
2
1
|
import { IDict, IJGISFormSchemaRegistry, IJupyterGISModel, LayerType, SourceType } from '@jupytergis/schema';
|
|
3
2
|
import { Dialog } from '@jupyterlab/apputils';
|
|
4
3
|
import { Signal } from '@lumino/signaling';
|
|
@@ -37,12 +36,17 @@ export interface ICreationFormProps {
|
|
|
37
36
|
*/
|
|
38
37
|
cancel?: () => void;
|
|
39
38
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
40
|
-
|
|
39
|
+
model: IJupyterGISModel;
|
|
41
40
|
/**
|
|
42
41
|
* A signal emitting when the form changed, with a boolean whether there are some
|
|
43
42
|
* extra errors or not.
|
|
44
43
|
*/
|
|
45
44
|
formErrorSignal?: Signal<Dialog<any>, boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Configuration options for the dialog, including settings for layer data, source data,
|
|
47
|
+
* and other form-related parameters.
|
|
48
|
+
*/
|
|
49
|
+
dialogOptions?: any;
|
|
46
50
|
}
|
|
47
51
|
/**
|
|
48
52
|
* Form for creating a source, a layer or both at the same time
|
|
@@ -21,8 +21,8 @@ export class CreationForm extends React.Component {
|
|
|
21
21
|
constructor(props) {
|
|
22
22
|
super(props);
|
|
23
23
|
this.sourceFormChangedSignal = new Signal(this);
|
|
24
|
-
this.filePath = props.
|
|
25
|
-
this.jGISModel = props.
|
|
24
|
+
this.filePath = props.model.filePath;
|
|
25
|
+
this.jGISModel = props.model;
|
|
26
26
|
}
|
|
27
27
|
render() {
|
|
28
28
|
var _a;
|
|
@@ -105,13 +105,13 @@ export class CreationForm extends React.Component {
|
|
|
105
105
|
return (React.createElement("div", null,
|
|
106
106
|
this.props.createSource && (React.createElement("div", null,
|
|
107
107
|
React.createElement("h3", null, "Source Properties"),
|
|
108
|
-
React.createElement(SourceForm, { formContext: "create", model: this.jGISModel, filePath:
|
|
108
|
+
React.createElement(SourceForm, { formContext: "create", model: this.jGISModel, filePath: this.filePath, schema: sourceSchema, sourceData: this.props.sourceData, syncData: (properties) => {
|
|
109
109
|
sourceCreationPromise === null || sourceCreationPromise === void 0 ? void 0 : sourceCreationPromise.resolve(properties);
|
|
110
|
-
}, ok: this.props.ok, cancel: this.props.cancel, formChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal }))),
|
|
110
|
+
}, ok: this.props.ok, cancel: this.props.cancel, formChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal, dialogOptions: this.props.dialogOptions, sourceType: this.props.sourceType }))),
|
|
111
111
|
this.props.createLayer && (React.createElement("div", null,
|
|
112
112
|
React.createElement("h3", null, "Layer Properties"),
|
|
113
|
-
React.createElement(LayerForm, { formContext: "create", sourceType: this.props.sourceType, model: this.jGISModel, filePath:
|
|
113
|
+
React.createElement(LayerForm, { formContext: "create", sourceType: this.props.sourceType, model: this.jGISModel, filePath: this.filePath, schema: layerSchema, sourceData: layerData, syncData: (properties) => {
|
|
114
114
|
layerCreationPromise === null || layerCreationPromise === void 0 ? void 0 : layerCreationPromise.resolve(properties);
|
|
115
|
-
}, ok: this.props.ok, cancel: this.props.cancel, sourceFormChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal })))));
|
|
115
|
+
}, ok: this.props.ok, cancel: this.props.cancel, sourceFormChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal, dialogOptions: this.props.dialogOptions })))));
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
2
1
|
import { IJGISFormSchemaRegistry, IJupyterGISModel } from '@jupytergis/schema';
|
|
3
2
|
import * as React from 'react';
|
|
4
3
|
export interface IEditFormProps {
|
|
@@ -11,7 +10,7 @@ export interface IEditFormProps {
|
|
|
11
10
|
*/
|
|
12
11
|
source: string | undefined;
|
|
13
12
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
14
|
-
|
|
13
|
+
model: IJupyterGISModel;
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Form for editing a source, a layer or both at the same time
|
|
@@ -21,4 +20,5 @@ export declare class EditForm extends React.Component<IEditFormProps, any> {
|
|
|
21
20
|
[key: string]: any;
|
|
22
21
|
}): Promise<void>;
|
|
23
22
|
render(): React.JSX.Element | undefined;
|
|
23
|
+
private sourceFormChangedSignal;
|
|
24
24
|
}
|