@jupytergis/base 0.1.6 → 0.2.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 +11 -0
- package/lib/annotations/components/Annotation.js +61 -0
- package/lib/annotations/components/AnnotationFloater.d.ts +7 -0
- package/lib/annotations/components/AnnotationFloater.js +30 -0
- package/lib/annotations/components/Message.d.ts +8 -0
- package/lib/annotations/components/Message.js +17 -0
- package/lib/annotations/index.d.ts +3 -0
- package/lib/annotations/index.js +3 -0
- package/lib/annotations/model.d.ts +28 -0
- package/lib/annotations/model.js +67 -0
- package/lib/classificationModes.d.ts +13 -0
- package/lib/classificationModes.js +326 -0
- package/lib/commands.js +52 -7
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +5 -1
- package/lib/dialogs/symbology/classificationModes.d.ts +13 -0
- package/lib/dialogs/symbology/classificationModes.js +326 -0
- package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.d.ts +11 -0
- package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.js +119 -0
- package/lib/dialogs/symbology/components/color_ramp/ColorRamp.d.ts +15 -0
- package/lib/dialogs/symbology/components/color_ramp/ColorRamp.js +33 -0
- package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.d.ts +9 -0
- package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.js +24 -0
- package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.d.ts +10 -0
- package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.js +11 -0
- package/lib/dialogs/symbology/components/color_stops/StopContainer.d.ts +9 -0
- package/lib/dialogs/symbology/components/color_stops/StopContainer.js +28 -0
- package/lib/dialogs/{components/symbology → symbology/components/color_stops}/StopRow.js +9 -2
- package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +12 -0
- package/lib/dialogs/symbology/hooks/useGetProperties.js +47 -0
- package/lib/dialogs/{symbologyDialog.js → symbology/symbologyDialog.js} +3 -3
- package/lib/dialogs/symbology/symbologyUtils.d.ts +9 -0
- package/lib/dialogs/symbology/symbologyUtils.js +94 -0
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +4 -0
- package/lib/dialogs/{components/symbology/BandRendering.js → symbology/tiff_layer/TiffRendering.js} +3 -3
- package/lib/dialogs/{components/symbology → symbology/tiff_layer/components}/BandRow.d.ts +1 -1
- package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.d.ts +9 -1
- package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.js +131 -83
- package/lib/dialogs/{components/symbology → symbology/vector_layer}/VectorRendering.d.ts +1 -1
- package/lib/dialogs/{components/symbology → symbology/vector_layer}/VectorRendering.js +10 -13
- package/lib/dialogs/symbology/vector_layer/components/ValueSelect.d.ts +8 -0
- package/lib/dialogs/symbology/vector_layer/components/ValueSelect.js +7 -0
- package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +4 -0
- package/lib/dialogs/symbology/vector_layer/types/Categorized.js +94 -0
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +169 -0
- package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/SimpleSymbol.js +8 -13
- package/lib/formbuilder/formselectors.js +4 -0
- package/lib/formbuilder/objectform/baseform.d.ts +1 -1
- package/lib/formbuilder/objectform/baseform.js +31 -42
- package/lib/formbuilder/objectform/geojsonsource.js +33 -30
- package/lib/formbuilder/objectform/geotiffsource.d.ts +16 -0
- package/lib/formbuilder/objectform/geotiffsource.js +71 -0
- package/lib/formbuilder/objectform/vectorlayerform.js +1 -0
- package/lib/formbuilder/objectform/webGlLayerForm.js +1 -0
- package/lib/index.d.ts +7 -4
- package/lib/index.js +7 -4
- package/lib/mainview/CollaboratorPointers.d.ts +17 -0
- package/lib/mainview/CollaboratorPointers.js +37 -0
- package/lib/mainview/FollowIndicator.d.ts +7 -0
- package/lib/mainview/FollowIndicator.js +9 -0
- package/lib/mainview/mainView.d.ts +39 -3
- package/lib/mainview/mainView.js +451 -41
- package/lib/mainview/mainviewmodel.d.ts +2 -1
- package/lib/mainview/mainviewmodel.js +5 -0
- package/lib/panelview/annotationPanel.d.ts +27 -0
- package/lib/panelview/annotationPanel.js +45 -0
- package/lib/panelview/components/filter-panel/Filter.d.ts +7 -2
- package/lib/panelview/components/filter-panel/Filter.js +1 -1
- package/lib/panelview/components/filter-panel/FilterRow.js +3 -3
- package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +15 -0
- package/lib/panelview/components/identify-panel/IdentifyPanel.js +108 -0
- package/lib/panelview/components/layers.js +4 -4
- package/lib/panelview/leftpanel.js +8 -0
- package/lib/panelview/rightpanel.d.ts +4 -1
- package/lib/panelview/rightpanel.js +28 -7
- package/lib/store.d.ts +9 -0
- package/lib/store.js +25 -0
- package/lib/toolbar/widget.js +12 -2
- package/lib/tools.d.ts +35 -0
- package/lib/tools.js +86 -0
- package/lib/types.d.ts +14 -0
- package/package.json +18 -20
- package/style/base.css +4 -8
- package/style/dialog.css +1 -1
- package/style/icons/logo_mini.svg +70 -148
- package/style/icons/nonvisibility.svg +2 -7
- package/style/icons/visibility.svg +2 -6
- package/style/leftPanel.css +5 -0
- package/style/symbologyDialog.css +104 -3
- package/lib/dialogs/components/symbology/BandRendering.d.ts +0 -4
- package/lib/dialogs/components/symbology/Graduated.js +0 -188
- /package/lib/dialogs/{components/symbology → symbology/components/color_stops}/StopRow.d.ts +0 -0
- /package/lib/dialogs/{symbologyDialog.d.ts → symbology/symbologyDialog.d.ts} +0 -0
- /package/lib/dialogs/{components/symbology → symbology/tiff_layer/components}/BandRow.js +0 -0
- /package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/Graduated.d.ts +0 -0
- /package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/SimpleSymbol.d.ts +0 -0
package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.js
RENAMED
|
@@ -1,101 +1,109 @@
|
|
|
1
|
-
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
3
1
|
import { Button } from '@jupyterlab/ui-components';
|
|
4
2
|
import React, { useEffect, useRef, useState } from 'react';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
3
|
+
import { GeoTiffClassifications } from '../../classificationModes';
|
|
4
|
+
import { GlobalStateDbManager } from '../../../../store';
|
|
5
|
+
import BandRow from '../components/BandRow';
|
|
6
|
+
import ColorRamp from '../../components/color_ramp/ColorRamp';
|
|
7
|
+
import StopRow from '../../components/color_stops/StopRow';
|
|
8
|
+
import { Utils } from '../../symbologyUtils';
|
|
9
|
+
import { Spinner } from '../../../../mainview/spinner';
|
|
10
|
+
import { loadGeoTIFFWithCache } from '../../../../tools';
|
|
11
|
+
const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) => {
|
|
9
12
|
const functions = ['discrete', 'linear', 'exact'];
|
|
13
|
+
const modeOptions = ['continuous', 'equal interval', 'quantile'];
|
|
10
14
|
const stopRowsRef = useRef();
|
|
11
15
|
const bandRowsRef = useRef([]);
|
|
12
16
|
const selectedFunctionRef = useRef();
|
|
13
|
-
const
|
|
17
|
+
const colorRampOptionsRef = useRef();
|
|
18
|
+
const layerStateRef = useRef();
|
|
19
|
+
const selectedBandRef = useRef();
|
|
20
|
+
const [layerState, setLayerState] = useState();
|
|
14
21
|
const [selectedBand, setSelectedBand] = useState(1);
|
|
15
22
|
const [stopRows, setStopRows] = useState([]);
|
|
16
23
|
const [bandRows, setBandRows] = useState([]);
|
|
24
|
+
const [selectedFunction, setSelectedFunction] = useState('linear');
|
|
25
|
+
const [colorRampOptions, setColorRampOptions] = useState();
|
|
17
26
|
if (!layerId) {
|
|
18
27
|
return;
|
|
19
28
|
}
|
|
20
29
|
const layer = context.model.getLayer(layerId);
|
|
21
|
-
if (!layer) {
|
|
30
|
+
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
22
31
|
return;
|
|
23
32
|
}
|
|
33
|
+
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
|
|
24
34
|
useEffect(() => {
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
populateOptions();
|
|
36
|
+
okSignalPromise.promise.then(okSignal => {
|
|
37
|
+
okSignal.connect(handleOk);
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
okSignalPromise.promise.then(okSignal => {
|
|
41
|
+
okSignal.disconnect(handleOk, this);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
27
44
|
}, []);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
layerStateRef.current = layerState;
|
|
47
|
+
getBandInfo();
|
|
48
|
+
}, [layerState]);
|
|
28
49
|
useEffect(() => {
|
|
29
50
|
bandRowsRef.current = bandRows;
|
|
30
51
|
buildColorInfo();
|
|
31
52
|
}, [bandRows]);
|
|
32
53
|
useEffect(() => {
|
|
33
54
|
stopRowsRef.current = stopRows;
|
|
34
|
-
}, [stopRows]);
|
|
35
|
-
useEffect(() => {
|
|
36
55
|
selectedFunctionRef.current = selectedFunction;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
? setSelectedFunction('discrete')
|
|
54
|
-
: setSelectedFunction('exact');
|
|
56
|
+
colorRampOptionsRef.current = colorRampOptions;
|
|
57
|
+
selectedBandRef.current = selectedBand;
|
|
58
|
+
layerStateRef.current = layerState;
|
|
59
|
+
}, [stopRows, selectedFunction, colorRampOptions, selectedBand, layerState]);
|
|
60
|
+
const populateOptions = async () => {
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
const layerState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(`jupytergis:${layerId}`)));
|
|
63
|
+
setLayerState(layerState);
|
|
64
|
+
const layerParams = layer.parameters;
|
|
65
|
+
const band = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.band) !== null && _b !== void 0 ? _b : 1;
|
|
66
|
+
const interpolation = (_d = (_c = layerParams.symbologyState) === null || _c === void 0 ? void 0 : _c.interpolation) !== null && _d !== void 0 ? _d : 'linear';
|
|
67
|
+
setSelectedBand(band);
|
|
68
|
+
setSelectedFunction(interpolation);
|
|
69
|
+
};
|
|
70
|
+
const preloadGeoTiffFile = async (sourceInfo) => {
|
|
71
|
+
return await loadGeoTIFFWithCache(sourceInfo);
|
|
55
72
|
};
|
|
56
73
|
const getBandInfo = async () => {
|
|
57
74
|
var _a, _b;
|
|
58
75
|
const bandsArr = [];
|
|
59
76
|
const source = context.model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
|
|
60
77
|
const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
|
|
61
|
-
if (!sourceInfo.url) {
|
|
78
|
+
if (!(sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url)) {
|
|
62
79
|
return;
|
|
63
80
|
}
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
band: bandData.band,
|
|
83
|
-
colorInterpretation: bandData.colorInterpretation,
|
|
84
|
-
stats: {
|
|
85
|
-
minimum: (_a = sourceInfo.min) !== null && _a !== void 0 ? _a : bandData.minimum,
|
|
86
|
-
maximum: (_b = sourceInfo.max) !== null && _b !== void 0 ? _b : bandData.maximum,
|
|
87
|
-
mean: bandData.mean,
|
|
88
|
-
stdDev: bandData.stdDev
|
|
89
|
-
},
|
|
90
|
-
metadata: bandData.metadata
|
|
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
|
+
});
|
|
91
99
|
});
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
setBandRows(bandsArr);
|
|
101
|
+
}
|
|
94
102
|
};
|
|
95
103
|
const buildColorInfo = () => {
|
|
96
104
|
var _a;
|
|
97
105
|
// This it to parse a color object on the layer
|
|
98
|
-
if (!((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.color)) {
|
|
106
|
+
if (!((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.color) || !layerState) {
|
|
99
107
|
return;
|
|
100
108
|
}
|
|
101
109
|
const color = layer.parameters.color;
|
|
@@ -103,6 +111,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
103
111
|
if (typeof color === 'string') {
|
|
104
112
|
return;
|
|
105
113
|
}
|
|
114
|
+
const isQuantile = layerState.selectedMode === 'quantile';
|
|
106
115
|
const valueColorPairs = [];
|
|
107
116
|
// So if it's not a string then it's an array and we parse
|
|
108
117
|
// Color[0] is the operator used for the color expression
|
|
@@ -115,7 +124,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
115
124
|
// Sixth and on is value:color pairs
|
|
116
125
|
for (let i = 5; i < color.length; i += 2) {
|
|
117
126
|
const obj = {
|
|
118
|
-
stop: scaleValue(color[i]),
|
|
127
|
+
stop: scaleValue(color[i], isQuantile),
|
|
119
128
|
output: color[i + 1]
|
|
120
129
|
};
|
|
121
130
|
valueColorPairs.push(obj);
|
|
@@ -132,7 +141,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
132
141
|
// Last element is fallback value
|
|
133
142
|
for (let i = 3; i < color.length - 1; i += 2) {
|
|
134
143
|
const obj = {
|
|
135
|
-
stop: scaleValue(color[i][2]),
|
|
144
|
+
stop: scaleValue(color[i][2], isQuantile),
|
|
136
145
|
output: color[i + 1]
|
|
137
146
|
};
|
|
138
147
|
valueColorPairs.push(obj);
|
|
@@ -143,7 +152,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
143
152
|
setStopRows(valueColorPairs);
|
|
144
153
|
};
|
|
145
154
|
const handleOk = () => {
|
|
146
|
-
var _a, _b, _c, _d;
|
|
155
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
147
156
|
// Update source
|
|
148
157
|
const bandRow = bandRowsRef.current[selectedBand - 1];
|
|
149
158
|
if (!bandRow) {
|
|
@@ -154,6 +163,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
154
163
|
if (!source || !source.parameters) {
|
|
155
164
|
return;
|
|
156
165
|
}
|
|
166
|
+
const isQuantile = ((_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.selectedMode) === 'quantile';
|
|
157
167
|
const sourceInfo = source.parameters.urls[0];
|
|
158
168
|
sourceInfo.min = bandRow.stats.minimum;
|
|
159
169
|
sourceInfo.max = bandRow.stats.maximum;
|
|
@@ -171,8 +181,8 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
171
181
|
colorExpr.push(['band', selectedBand]);
|
|
172
182
|
// Set NoData values to transparent
|
|
173
183
|
colorExpr.push(0.0, [0.0, 0.0, 0.0, 0.0]);
|
|
174
|
-
(
|
|
175
|
-
colorExpr.push(unscaleValue(stop.stop));
|
|
184
|
+
(_c = stopRowsRef.current) === null || _c === void 0 ? void 0 : _c.map(stop => {
|
|
185
|
+
colorExpr.push(unscaleValue(stop.stop, isQuantile));
|
|
176
186
|
colorExpr.push(stop.output);
|
|
177
187
|
});
|
|
178
188
|
break;
|
|
@@ -182,11 +192,11 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
182
192
|
// Set NoData values to transparent
|
|
183
193
|
colorExpr.push(['==', ['band', selectedBand], 0]);
|
|
184
194
|
colorExpr.push([0.0, 0.0, 0.0, 0.0]);
|
|
185
|
-
(
|
|
195
|
+
(_d = stopRowsRef.current) === null || _d === void 0 ? void 0 : _d.map(stop => {
|
|
186
196
|
colorExpr.push([
|
|
187
197
|
'<=',
|
|
188
198
|
['band', selectedBand],
|
|
189
|
-
unscaleValue(stop.stop)
|
|
199
|
+
unscaleValue(stop.stop, isQuantile)
|
|
190
200
|
]);
|
|
191
201
|
colorExpr.push(stop.output);
|
|
192
202
|
});
|
|
@@ -199,11 +209,11 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
199
209
|
// Set NoData values to transparent
|
|
200
210
|
colorExpr.push(['==', ['band', selectedBand], 0]);
|
|
201
211
|
colorExpr.push([0.0, 0.0, 0.0, 0.0]);
|
|
202
|
-
(
|
|
212
|
+
(_e = stopRowsRef.current) === null || _e === void 0 ? void 0 : _e.map(stop => {
|
|
203
213
|
colorExpr.push([
|
|
204
214
|
'==',
|
|
205
215
|
['band', selectedBand],
|
|
206
|
-
unscaleValue(stop.stop)
|
|
216
|
+
unscaleValue(stop.stop, isQuantile)
|
|
207
217
|
]);
|
|
208
218
|
colorExpr.push(stop.output);
|
|
209
219
|
});
|
|
@@ -212,13 +222,19 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
212
222
|
break;
|
|
213
223
|
}
|
|
214
224
|
}
|
|
225
|
+
const symbologyState = {
|
|
226
|
+
renderType: 'Singleband Pseudocolor',
|
|
227
|
+
band: selectedBandRef.current,
|
|
228
|
+
interpolation: selectedFunctionRef.current,
|
|
229
|
+
colorRamp: (_f = colorRampOptionsRef.current) === null || _f === void 0 ? void 0 : _f.selectedRamp,
|
|
230
|
+
nClasses: (_g = colorRampOptionsRef.current) === null || _g === void 0 ? void 0 : _g.numberOfShades,
|
|
231
|
+
mode: (_h = colorRampOptionsRef.current) === null || _h === void 0 ? void 0 : _h.selectedMode
|
|
232
|
+
};
|
|
233
|
+
layer.parameters.symbologyState = symbologyState;
|
|
215
234
|
layer.parameters.color = colorExpr;
|
|
216
235
|
context.model.sharedModel.updateLayer(layerId, layer);
|
|
217
236
|
cancel();
|
|
218
237
|
};
|
|
219
|
-
okSignalPromise.promise.then(okSignal => {
|
|
220
|
-
okSignal.connect(handleOk);
|
|
221
|
-
});
|
|
222
238
|
const addStopRow = () => {
|
|
223
239
|
setStopRows([
|
|
224
240
|
{
|
|
@@ -233,24 +249,55 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
233
249
|
newFilters.splice(index, 1);
|
|
234
250
|
setStopRows(newFilters);
|
|
235
251
|
};
|
|
236
|
-
const
|
|
252
|
+
const buildColorInfoFromClassification = async (selectedMode, numberOfShades, selectedRamp, setIsLoading) => {
|
|
253
|
+
var _a, _b;
|
|
254
|
+
// Update layer state with selected options
|
|
255
|
+
setColorRampOptions({
|
|
256
|
+
selectedRamp,
|
|
257
|
+
numberOfShades,
|
|
258
|
+
selectedMode
|
|
259
|
+
});
|
|
260
|
+
let stops = [];
|
|
261
|
+
const currentBand = bandRows[selectedBand - 1];
|
|
262
|
+
const source = context.model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
|
|
263
|
+
const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
|
|
264
|
+
const nClasses = selectedMode === 'continuous' ? 52 : +numberOfShades;
|
|
265
|
+
setIsLoading(true);
|
|
266
|
+
switch (selectedMode) {
|
|
267
|
+
case 'quantile':
|
|
268
|
+
stops = await GeoTiffClassifications.classifyQuantileBreaks(nClasses, selectedBand, sourceInfo.url, selectedFunction);
|
|
269
|
+
break;
|
|
270
|
+
case 'continuous':
|
|
271
|
+
stops = GeoTiffClassifications.classifyContinuousBreaks(nClasses, currentBand.stats.minimum, currentBand.stats.maximum, selectedFunction);
|
|
272
|
+
break;
|
|
273
|
+
case 'equal interval':
|
|
274
|
+
stops = GeoTiffClassifications.classifyEqualIntervalBreaks(nClasses, currentBand.stats.minimum, currentBand.stats.maximum, selectedFunction);
|
|
275
|
+
break;
|
|
276
|
+
default:
|
|
277
|
+
console.warn('No mode selected');
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
setIsLoading(false);
|
|
281
|
+
const valueColorPairs = Utils.getValueColorPairs(stops, selectedRamp, nClasses);
|
|
282
|
+
setStopRows(valueColorPairs);
|
|
283
|
+
};
|
|
284
|
+
const scaleValue = (bandValue, isQuantile) => {
|
|
237
285
|
const currentBand = bandRows[selectedBand - 1];
|
|
238
286
|
if (!currentBand) {
|
|
239
287
|
return bandValue;
|
|
240
288
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
289
|
+
const min = isQuantile ? 1 : currentBand.stats.minimum;
|
|
290
|
+
const max = isQuantile ? 65535 : currentBand.stats.maximum;
|
|
291
|
+
return (bandValue * (max - min)) / (1 - 0) + min;
|
|
244
292
|
};
|
|
245
|
-
const unscaleValue = (value) => {
|
|
293
|
+
const unscaleValue = (value, isQuantile) => {
|
|
246
294
|
const currentBand = bandRowsRef.current[selectedBand - 1];
|
|
247
|
-
|
|
248
|
-
|
|
295
|
+
const min = isQuantile ? 1 : currentBand.stats.minimum;
|
|
296
|
+
const max = isQuantile ? 65535 : currentBand.stats.maximum;
|
|
297
|
+
return (value * (1 - 0) - min * (1 - 0)) / (max - min);
|
|
249
298
|
};
|
|
250
299
|
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
251
|
-
React.createElement("div", { className: "jp-gis-band-container" }, bandRows.length === 0 ? (React.createElement(
|
|
252
|
-
React.createElement("span", null, "Fetching band info..."),
|
|
253
|
-
React.createElement(FontAwesomeIcon, { icon: faSpinner, className: "jp-gis-loading-spinner" }))) : (React.createElement(BandRow
|
|
300
|
+
React.createElement("div", { className: "jp-gis-band-container" }, bandRows.length === 0 ? (React.createElement(Spinner, { loading: bandRows.length === 0 })) : (React.createElement(BandRow
|
|
254
301
|
// Band numbers are 1 indexed
|
|
255
302
|
, {
|
|
256
303
|
// Band numbers are 1 indexed
|
|
@@ -261,6 +308,7 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
|
|
|
261
308
|
React.createElement("select", { name: "function-select", id: "function-select", className: "jp-mod-styled", value: selectedFunction, style: { textTransform: 'capitalize' }, onChange: event => {
|
|
262
309
|
setSelectedFunction(event.target.value);
|
|
263
310
|
} }, functions.map((func, funcIndex) => (React.createElement("option", { key: func, value: func, style: { textTransform: 'capitalize' } }, func)))))),
|
|
311
|
+
bandRows.length > 0 && (React.createElement(ColorRamp, { layerParams: layer.parameters, modeOptions: modeOptions, classifyFunc: buildColorInfoFromClassification, showModeRow: true })),
|
|
264
312
|
React.createElement("div", { className: "jp-gis-stop-container" },
|
|
265
313
|
React.createElement("div", { className: "jp-gis-stop-labels", style: { display: 'flex', gap: 6 } },
|
|
266
314
|
React.createElement("span", { style: { flex: '0 0 18%' } },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { ISymbologyDialogProps } from '
|
|
2
|
+
import { ISymbologyDialogProps } from '../symbologyDialog';
|
|
3
3
|
declare const VectorRendering: ({ context, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
4
4
|
export default VectorRendering;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import Graduated from './Graduated';
|
|
3
|
-
import SimpleSymbol from './SimpleSymbol';
|
|
2
|
+
import Graduated from './types/Graduated';
|
|
3
|
+
import SimpleSymbol from './types/SimpleSymbol';
|
|
4
|
+
import Categorized from './types/Categorized';
|
|
4
5
|
const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
5
6
|
const [selectedRenderType, setSelectedRenderType] = useState('Single Symbol');
|
|
6
7
|
const [componentToRender, setComponentToRender] = useState(null);
|
|
@@ -16,20 +17,13 @@ const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) =
|
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
19
|
useEffect(() => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const renderType = layerState
|
|
25
|
-
.renderType;
|
|
26
|
-
setSelectedRenderType(renderType !== null && renderType !== void 0 ? renderType : 'Single Symbol');
|
|
27
|
-
};
|
|
20
|
+
var _a, _b;
|
|
21
|
+
const renderType = (_b = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) === null || _b === void 0 ? void 0 : _b.renderType;
|
|
22
|
+
setSelectedRenderType(renderType !== null && renderType !== void 0 ? renderType : 'Single Symbol');
|
|
28
23
|
if (layer.type === 'VectorLayer') {
|
|
29
|
-
const options = ['Single Symbol', 'Graduated'];
|
|
24
|
+
const options = ['Single Symbol', 'Graduated', 'Categorized'];
|
|
30
25
|
setRenderTypeOptions(options);
|
|
31
26
|
}
|
|
32
|
-
getSelectedRenderType();
|
|
33
27
|
}, []);
|
|
34
28
|
useEffect(() => {
|
|
35
29
|
switch (selectedRenderType) {
|
|
@@ -39,6 +33,9 @@ const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) =
|
|
|
39
33
|
case 'Graduated':
|
|
40
34
|
RenderComponent = (React.createElement(Graduated, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
41
35
|
break;
|
|
36
|
+
case 'Categorized':
|
|
37
|
+
RenderComponent = (React.createElement(Categorized, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
|
|
38
|
+
break;
|
|
42
39
|
default:
|
|
43
40
|
RenderComponent = React.createElement("div", null, "Render Type Not Implemented (yet)");
|
|
44
41
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface IValueSelectProps {
|
|
3
|
+
featureProperties: any;
|
|
4
|
+
selectedValue: string;
|
|
5
|
+
setSelectedValue: (value: string) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const ValueSelect: ({ featureProperties, selectedValue, setSelectedValue }: IValueSelectProps) => React.JSX.Element;
|
|
8
|
+
export default ValueSelect;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
const ValueSelect = ({ featureProperties, selectedValue, setSelectedValue }) => {
|
|
3
|
+
return (React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
4
|
+
React.createElement("label", { htmlFor: 'vector-value-select' }, "Value:"),
|
|
5
|
+
React.createElement("select", { name: 'vector-value-select', onChange: event => setSelectedValue(event.target.value), className: "jp-mod-styled" }, Object.keys(featureProperties).map((feature, index) => (React.createElement("option", { key: index, value: feature, selected: feature === selectedValue, className: "jp-mod-styled" }, feature))))));
|
|
6
|
+
};
|
|
7
|
+
export default ValueSelect;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import ValueSelect from '../components/ValueSelect';
|
|
3
|
+
import { useGetProperties } from '../../hooks/useGetProperties';
|
|
4
|
+
import StopContainer from '../../components/color_stops/StopContainer';
|
|
5
|
+
import { Utils, VectorUtils } from '../../symbologyUtils';
|
|
6
|
+
import ColorRamp from '../../components/color_ramp/ColorRamp';
|
|
7
|
+
const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
8
|
+
const selectedValueRef = useRef();
|
|
9
|
+
const stopRowsRef = useRef();
|
|
10
|
+
const colorRampOptionsRef = useRef();
|
|
11
|
+
const [selectedValue, setSelectedValue] = useState('');
|
|
12
|
+
const [stopRows, setStopRows] = useState([]);
|
|
13
|
+
const [colorRampOptions, setColorRampOptions] = useState();
|
|
14
|
+
if (!layerId) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const layer = context.model.getLayer(layerId);
|
|
18
|
+
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const { featureProps } = useGetProperties({
|
|
22
|
+
layerId,
|
|
23
|
+
model: context.model
|
|
24
|
+
});
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const valueColorPairs = VectorUtils.buildColorInfo(layer);
|
|
27
|
+
setStopRows(valueColorPairs);
|
|
28
|
+
okSignalPromise.promise.then(okSignal => {
|
|
29
|
+
okSignal.connect(handleOk, this);
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
okSignalPromise.promise.then(okSignal => {
|
|
33
|
+
okSignal.disconnect(handleOk, this);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
populateOptions();
|
|
39
|
+
}, [featureProps]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
selectedValueRef.current = selectedValue;
|
|
42
|
+
stopRowsRef.current = stopRows;
|
|
43
|
+
colorRampOptionsRef.current = colorRampOptions;
|
|
44
|
+
}, [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
|
+
const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp, setIsLoading) => {
|
|
52
|
+
setColorRampOptions({
|
|
53
|
+
selectedFunction: '',
|
|
54
|
+
selectedRamp,
|
|
55
|
+
numberOfShades: '',
|
|
56
|
+
selectedMode: ''
|
|
57
|
+
});
|
|
58
|
+
const stops = Array.from(featureProps[selectedValue]).sort((a, b) => a - b);
|
|
59
|
+
const valueColorPairs = Utils.getValueColorPairs(stops, selectedRamp, stops.length);
|
|
60
|
+
setStopRows(valueColorPairs);
|
|
61
|
+
};
|
|
62
|
+
const handleOk = () => {
|
|
63
|
+
var _a, _b, _c, _d;
|
|
64
|
+
if (!layer.parameters) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const colorExpr = [];
|
|
68
|
+
colorExpr.push('case');
|
|
69
|
+
(_a = stopRowsRef.current) === null || _a === void 0 ? void 0 : _a.map(stop => {
|
|
70
|
+
colorExpr.push(['==', ['get', selectedValueRef.current], stop.stop]);
|
|
71
|
+
colorExpr.push(stop.output);
|
|
72
|
+
});
|
|
73
|
+
// fallback value
|
|
74
|
+
colorExpr.push([0, 0, 0, 0.0]);
|
|
75
|
+
const newStyle = Object.assign({}, layer.parameters.color);
|
|
76
|
+
newStyle['circle-fill-color'] = colorExpr;
|
|
77
|
+
const symbologyState = {
|
|
78
|
+
renderType: 'Categorized',
|
|
79
|
+
value: selectedValueRef.current,
|
|
80
|
+
colorRamp: (_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.selectedRamp,
|
|
81
|
+
nClasses: (_c = colorRampOptionsRef.current) === null || _c === void 0 ? void 0 : _c.numberOfShades,
|
|
82
|
+
mode: (_d = colorRampOptionsRef.current) === null || _d === void 0 ? void 0 : _d.selectedMode
|
|
83
|
+
};
|
|
84
|
+
layer.parameters.symbologyState = symbologyState;
|
|
85
|
+
layer.parameters.color = newStyle;
|
|
86
|
+
context.model.sharedModel.updateLayer(layerId, layer);
|
|
87
|
+
cancel();
|
|
88
|
+
};
|
|
89
|
+
return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
90
|
+
React.createElement(ValueSelect, { featureProperties: featureProps, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
|
|
91
|
+
React.createElement(ColorRamp, { layerParams: layer.parameters, modeOptions: [], classifyFunc: buildColorInfoFromClassification, showModeRow: false }),
|
|
92
|
+
React.createElement(StopContainer, { selectedMethod: '', stopRows: stopRows, setStopRows: setStopRows })));
|
|
93
|
+
};
|
|
94
|
+
export default Categorized;
|