@jupytergis/base 0.12.2 → 0.13.1
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/commands/index.js +2 -6
- package/lib/dialogs/symbology/hooks/useEffectiveSymbologyParams.d.ts +16 -0
- package/lib/dialogs/symbology/hooks/useEffectiveSymbologyParams.js +24 -0
- package/lib/dialogs/symbology/hooks/useOkSignal.d.ts +6 -0
- package/lib/dialogs/symbology/hooks/useOkSignal.js +25 -0
- package/lib/dialogs/symbology/symbologyDialog.d.ts +4 -2
- package/lib/dialogs/symbology/symbologyDialog.js +6 -10
- package/lib/dialogs/symbology/symbologyUtils.d.ts +25 -2
- package/lib/dialogs/symbology/symbologyUtils.js +74 -4
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +3 -3
- package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +31 -34
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +68 -62
- package/lib/dialogs/symbology/vector_layer/VectorRendering.js +33 -21
- package/lib/dialogs/symbology/vector_layer/types/Canonical.js +23 -24
- package/lib/dialogs/symbology/vector_layer/types/Categorized.js +49 -50
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +53 -62
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +35 -34
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +45 -47
- package/lib/formbuilder/objectform/StoryEditorForm.js +0 -17
- package/lib/formbuilder/objectform/baseform.d.ts +11 -0
- package/lib/formbuilder/objectform/baseform.js +72 -38
- package/lib/formbuilder/objectform/components/LayerSelect.d.ts +7 -0
- package/lib/formbuilder/objectform/components/LayerSelect.js +43 -0
- package/lib/formbuilder/objectform/components/OpacitySlider.d.ts +4 -0
- package/lib/formbuilder/objectform/components/OpacitySlider.js +40 -0
- package/lib/formbuilder/objectform/components/SegmentFormSymbology.d.ts +3 -0
- package/lib/formbuilder/objectform/components/SegmentFormSymbology.js +59 -0
- package/lib/formbuilder/objectform/layer/storySegmentLayerForm.d.ts +2 -2
- package/lib/formbuilder/objectform/layer/storySegmentLayerForm.js +19 -0
- package/lib/formbuilder/objectform/source/geojsonsource.js +1 -3
- package/lib/mainview/mainView.js +6 -1
- package/lib/panelview/rightpanel.d.ts +3 -1
- package/lib/panelview/rightpanel.js +2 -2
- package/lib/panelview/story-maps/StoryViewerPanel.d.ts +3 -1
- package/lib/panelview/story-maps/StoryViewerPanel.js +127 -19
- package/lib/shared/hooks/useLatest.d.ts +1 -0
- package/lib/shared/hooks/useLatest.js +8 -0
- package/lib/types.d.ts +1 -0
- package/lib/types.js +6 -1
- package/package.json +2 -2
- package/style/base.css +8 -0
- package/style/storyPanel.css +4 -4
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import { Button } from '@jupyterlab/ui-components';
|
|
2
|
-
import React, { useEffect,
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
3
|
import { GeoTiffClassifications } from "../../classificationModes";
|
|
4
4
|
import ColorRampControls from "../../components/color_ramp/ColorRampControls";
|
|
5
5
|
import StopRow from "../../components/color_stops/StopRow";
|
|
6
6
|
import useGetBandInfo from "../../hooks/useGetBandInfo";
|
|
7
|
-
import {
|
|
7
|
+
import { useOkSignal } from "../../hooks/useOkSignal";
|
|
8
|
+
import { saveSymbology, Utils, } from "../../symbologyUtils";
|
|
8
9
|
import BandRow from "../components/BandRow";
|
|
9
10
|
import { LoadingOverlay } from "../../../../shared/components/loading";
|
|
11
|
+
import { useLatest } from "../../../../shared/hooks/useLatest";
|
|
10
12
|
import { GlobalStateDbManager } from "../../../../store";
|
|
11
|
-
|
|
13
|
+
import { useEffectiveSymbologyParams } from '../../hooks/useEffectiveSymbologyParams';
|
|
14
|
+
const SingleBandPseudoColor = ({ model, okSignalPromise, layerId, isStorySegmentOverride, segmentId, }) => {
|
|
12
15
|
if (!layerId) {
|
|
13
16
|
return;
|
|
14
17
|
}
|
|
15
18
|
const layer = model.getLayer(layerId);
|
|
16
|
-
|
|
19
|
+
const params = useEffectiveSymbologyParams({
|
|
20
|
+
model,
|
|
21
|
+
layerId: layerId,
|
|
22
|
+
layer,
|
|
23
|
+
isStorySegmentOverride,
|
|
24
|
+
segmentId,
|
|
25
|
+
});
|
|
26
|
+
if (!params || !layer) {
|
|
17
27
|
return;
|
|
18
28
|
}
|
|
19
29
|
const functions = ['discrete', 'linear', 'exact'];
|
|
@@ -29,56 +39,40 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
29
39
|
const [stopRows, setStopRows] = useState([]);
|
|
30
40
|
const [selectedFunction, setSelectedFunction] = useState('linear');
|
|
31
41
|
const [colorRampOptions, setColorRampOptions] = useState();
|
|
32
|
-
const stopRowsRef =
|
|
33
|
-
const bandRowsRef =
|
|
34
|
-
const selectedFunctionRef =
|
|
35
|
-
const colorRampOptionsRef =
|
|
36
|
-
const selectedBandRef =
|
|
42
|
+
const stopRowsRef = useLatest(stopRows);
|
|
43
|
+
const bandRowsRef = useLatest(bandRows);
|
|
44
|
+
const selectedFunctionRef = useLatest(selectedFunction);
|
|
45
|
+
const colorRampOptionsRef = useLatest(colorRampOptions);
|
|
46
|
+
const selectedBandRef = useLatest(selectedBand);
|
|
37
47
|
useEffect(() => {
|
|
38
48
|
populateOptions();
|
|
39
|
-
okSignalPromise.promise.then(okSignal => {
|
|
40
|
-
okSignal.connect(handleOk);
|
|
41
|
-
});
|
|
42
|
-
return () => {
|
|
43
|
-
okSignalPromise.promise.then(okSignal => {
|
|
44
|
-
okSignal.disconnect(handleOk, this);
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
49
|
}, []);
|
|
48
50
|
useEffect(() => {
|
|
49
|
-
bandRowsRef.current = bandRows;
|
|
50
51
|
buildColorInfo();
|
|
51
52
|
}, [bandRows]);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
stopRowsRef.current = stopRows;
|
|
54
|
-
selectedFunctionRef.current = selectedFunction;
|
|
55
|
-
colorRampOptionsRef.current = colorRampOptions;
|
|
56
|
-
selectedBandRef.current = selectedBand;
|
|
57
|
-
}, [stopRows, selectedFunction, colorRampOptions, selectedBand, layerState]);
|
|
58
53
|
const populateOptions = async () => {
|
|
59
54
|
var _a, _b, _c, _d;
|
|
60
55
|
const layerState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(`jupytergis:${layerId}`)));
|
|
61
56
|
setLayerState(layerState);
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
const interpolation = (_d = (_c = layerParams.symbologyState) === null || _c === void 0 ? void 0 : _c.interpolation) !== null && _d !== void 0 ? _d : 'linear';
|
|
57
|
+
const band = (_b = (_a = params.symbologyState) === null || _a === void 0 ? void 0 : _a.band) !== null && _b !== void 0 ? _b : 1;
|
|
58
|
+
const interpolation = (_d = (_c = params.symbologyState) === null || _c === void 0 ? void 0 : _c.interpolation) !== null && _d !== void 0 ? _d : 'linear';
|
|
65
59
|
setSelectedBand(band);
|
|
66
60
|
setSelectedFunction(interpolation);
|
|
67
61
|
};
|
|
68
62
|
const buildColorInfo = () => {
|
|
69
|
-
var _a;
|
|
70
63
|
// This it to parse a color object on the layer
|
|
71
|
-
if (!
|
|
64
|
+
if (!params.color || !layerState) {
|
|
72
65
|
return;
|
|
73
66
|
}
|
|
74
|
-
const color =
|
|
67
|
+
const color = params.color;
|
|
75
68
|
// If color is a string we don't need to parse
|
|
76
|
-
|
|
69
|
+
// Otherwise color expression should be an array (e.g. ['interpolate', ...] or ['case', ...])
|
|
70
|
+
if (!Array.isArray(color)) {
|
|
77
71
|
return;
|
|
78
72
|
}
|
|
73
|
+
// ! wtf ? dont use statedb just read from the file??
|
|
79
74
|
const isQuantile = layerState.selectedMode === 'quantile';
|
|
80
75
|
const valueColorPairs = [];
|
|
81
|
-
// So if it's not a string then it's an array and we parse
|
|
82
76
|
// Color[0] is the operator used for the color expression
|
|
83
77
|
switch (color[0]) {
|
|
84
78
|
case 'interpolate': {
|
|
@@ -89,7 +83,7 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
89
83
|
// Sixth and on is value:color pairs
|
|
90
84
|
for (let i = 5; i < color.length; i += 2) {
|
|
91
85
|
const obj = {
|
|
92
|
-
stop: scaleValue(color[i], isQuantile),
|
|
86
|
+
stop: scaleValue(Number(color[i]), isQuantile),
|
|
93
87
|
output: color[i + 1],
|
|
94
88
|
};
|
|
95
89
|
valueColorPairs.push(obj);
|
|
@@ -105,8 +99,11 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
105
99
|
// Fifth is color
|
|
106
100
|
// Last element is fallback value
|
|
107
101
|
for (let i = 3; i < color.length - 1; i += 2) {
|
|
102
|
+
const stopVal = Number(Array.isArray(color[i])
|
|
103
|
+
? color[i][2]
|
|
104
|
+
: color[i]);
|
|
108
105
|
const obj = {
|
|
109
|
-
stop: scaleValue(
|
|
106
|
+
stop: scaleValue(stopVal, isQuantile),
|
|
110
107
|
output: color[i + 1],
|
|
111
108
|
};
|
|
112
109
|
valueColorPairs.push(obj);
|
|
@@ -118,26 +115,11 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
118
115
|
};
|
|
119
116
|
const handleOk = () => {
|
|
120
117
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
121
|
-
// Update source
|
|
122
118
|
const bandRow = bandRowsRef.current[selectedBand - 1];
|
|
123
119
|
if (!bandRow) {
|
|
124
120
|
return;
|
|
125
121
|
}
|
|
126
|
-
const
|
|
127
|
-
const source = model.getSource(sourceId);
|
|
128
|
-
if (!source || !source.parameters) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const isQuantile = ((_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.selectedMode) === 'quantile';
|
|
132
|
-
const sourceInfo = source.parameters.urls[0];
|
|
133
|
-
sourceInfo.min = bandRow.stats.minimum;
|
|
134
|
-
sourceInfo.max = bandRow.stats.maximum;
|
|
135
|
-
source.parameters.urls[0] = sourceInfo;
|
|
136
|
-
model.sharedModel.updateSource(sourceId, source);
|
|
137
|
-
// Update layer
|
|
138
|
-
if (!layer.parameters) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
122
|
+
const isQuantile = ((_a = colorRampOptionsRef.current) === null || _a === void 0 ? void 0 : _a.selectedMode) === 'quantile';
|
|
141
123
|
// TODO: Different viewers will have different types
|
|
142
124
|
let colorExpr = [];
|
|
143
125
|
switch (selectedFunctionRef.current) {
|
|
@@ -146,7 +128,7 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
146
128
|
colorExpr.push(['band', selectedBand]);
|
|
147
129
|
// Set NoData values to transparent
|
|
148
130
|
colorExpr.push(0.0, [0.0, 0.0, 0.0, 0.0]);
|
|
149
|
-
(
|
|
131
|
+
(_b = stopRowsRef.current) === null || _b === void 0 ? void 0 : _b.map(stop => {
|
|
150
132
|
colorExpr.push(unscaleValue(stop.stop, isQuantile));
|
|
151
133
|
colorExpr.push(stop.output);
|
|
152
134
|
});
|
|
@@ -157,7 +139,7 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
157
139
|
// Set NoData values to transparent
|
|
158
140
|
colorExpr.push(['==', ['band', selectedBand], 0]);
|
|
159
141
|
colorExpr.push([0.0, 0.0, 0.0, 0.0]);
|
|
160
|
-
(
|
|
142
|
+
(_c = stopRowsRef.current) === null || _c === void 0 ? void 0 : _c.map(stop => {
|
|
161
143
|
colorExpr.push([
|
|
162
144
|
'<=',
|
|
163
145
|
['band', selectedBand],
|
|
@@ -174,7 +156,7 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
174
156
|
// Set NoData values to transparent
|
|
175
157
|
colorExpr.push(['==', ['band', selectedBand], 0]);
|
|
176
158
|
colorExpr.push([0.0, 0.0, 0.0, 0.0]);
|
|
177
|
-
(
|
|
159
|
+
(_d = stopRowsRef.current) === null || _d === void 0 ? void 0 : _d.map(stop => {
|
|
178
160
|
colorExpr.push([
|
|
179
161
|
'==',
|
|
180
162
|
['band', selectedBand],
|
|
@@ -191,16 +173,40 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
191
173
|
renderType: 'Singleband Pseudocolor',
|
|
192
174
|
band: selectedBandRef.current,
|
|
193
175
|
interpolation: selectedFunctionRef.current,
|
|
194
|
-
colorRamp: (
|
|
195
|
-
nClasses: (
|
|
196
|
-
|
|
176
|
+
colorRamp: (_e = colorRampOptionsRef.current) === null || _e === void 0 ? void 0 : _e.selectedRamp,
|
|
177
|
+
nClasses: ((_f = colorRampOptionsRef.current) === null || _f === void 0 ? void 0 : _f.numberOfShades) !== undefined
|
|
178
|
+
? String(colorRampOptionsRef.current.numberOfShades)
|
|
179
|
+
: undefined,
|
|
180
|
+
mode: (_g = colorRampOptionsRef.current) === null || _g === void 0 ? void 0 : _g.selectedMode,
|
|
197
181
|
};
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
182
|
+
if (!isStorySegmentOverride) {
|
|
183
|
+
// Update source
|
|
184
|
+
const sourceId = (_h = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _h === void 0 ? void 0 : _h.source;
|
|
185
|
+
const source = model.getSource(sourceId);
|
|
186
|
+
if (!source || !source.parameters) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const sourceInfo = source.parameters.urls[0];
|
|
190
|
+
sourceInfo.min = bandRow.stats.minimum;
|
|
191
|
+
sourceInfo.max = bandRow.stats.maximum;
|
|
192
|
+
source.parameters.urls[0] = sourceInfo;
|
|
193
|
+
model.sharedModel.updateSource(sourceId, source);
|
|
194
|
+
}
|
|
195
|
+
saveSymbology({
|
|
196
|
+
model,
|
|
197
|
+
layerId,
|
|
198
|
+
isStorySegmentOverride,
|
|
199
|
+
segmentId,
|
|
200
|
+
payload: {
|
|
201
|
+
symbologyState,
|
|
202
|
+
color: colorExpr,
|
|
203
|
+
},
|
|
204
|
+
mutateLayerBeforeSave: targetLayer => {
|
|
205
|
+
targetLayer.type = 'WebGlLayer';
|
|
206
|
+
},
|
|
207
|
+
});
|
|
203
208
|
};
|
|
209
|
+
useOkSignal(okSignalPromise, handleOk);
|
|
204
210
|
const addStopRow = () => {
|
|
205
211
|
setStopRows([
|
|
206
212
|
{
|
|
@@ -274,7 +280,7 @@ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId, }) =>
|
|
|
274
280
|
React.createElement("select", { name: "function-select", id: "function-select", className: "jp-mod-styled", value: selectedFunction, style: { textTransform: 'capitalize' }, onChange: event => {
|
|
275
281
|
setSelectedFunction(event.target.value);
|
|
276
282
|
} }, functions.map((func, funcIndex) => (React.createElement("option", { key: func, value: func, style: { textTransform: 'capitalize' } }, func)))))),
|
|
277
|
-
bandRows.length > 0 && (React.createElement(ColorRampControls, { layerParams:
|
|
283
|
+
bandRows.length > 0 && (React.createElement(ColorRampControls, { layerParams: params, modeOptions: modeOptions, classifyFunc: buildColorInfoFromClassification, showModeRow: true, showRampSelector: true })),
|
|
278
284
|
React.createElement("div", { className: "jp-gis-stop-container" },
|
|
279
285
|
React.createElement("div", { className: "jp-gis-stop-labels", style: { display: 'flex', gap: 6 } },
|
|
280
286
|
React.createElement("span", { style: { flex: '0 0 18%' } },
|
|
@@ -47,35 +47,47 @@ const getSelectableRenderTypes = (featureProperties, layerType) => {
|
|
|
47
47
|
]);
|
|
48
48
|
return Object.fromEntries(entries);
|
|
49
49
|
};
|
|
50
|
-
const
|
|
51
|
-
var _a, _b;
|
|
52
|
-
let renderType = (_b = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) === null || _b === void 0 ? void 0 : _b.renderType;
|
|
53
|
-
if (!renderType) {
|
|
54
|
-
renderType = layer.type === 'HeatmapLayer' ? 'Heatmap' : 'Single Symbol';
|
|
55
|
-
}
|
|
56
|
-
setSelectedRenderType(renderType);
|
|
57
|
-
}, []);
|
|
58
|
-
const VectorRendering = ({ model, state, okSignalPromise, cancel, layerId, }) => {
|
|
59
|
-
const [selectedRenderType, setSelectedRenderType] = useState();
|
|
50
|
+
const VectorRendering = ({ model, okSignalPromise, layerId, isStorySegmentOverride = false, segmentId, }) => {
|
|
60
51
|
const [symbologyTab, setSymbologyTab] = useState('color');
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
const [selectedRenderType, setSelectedRenderType] = useState();
|
|
53
|
+
const layer = layerId !== undefined ? model.getLayer(layerId) : null;
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
var _a, _b, _c, _d, _e;
|
|
56
|
+
if (!layer) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let renderType;
|
|
60
|
+
if (isStorySegmentOverride) {
|
|
61
|
+
const segment = segmentId ? model.getLayer(segmentId) : undefined;
|
|
62
|
+
if (!segment) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const override = (_b = (_a = segment.parameters) === null || _a === void 0 ? void 0 : _a.layerOverride) === null || _b === void 0 ? void 0 : _b.find((override) => override.targetLayer === layerId);
|
|
66
|
+
if (!override) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
renderType = (_c = override.symbologyState) === null || _c === void 0 ? void 0 : _c.renderType;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
renderType = (_e = (_d = layer.parameters) === null || _d === void 0 ? void 0 : _d.symbologyState) === null || _e === void 0 ? void 0 : _e.renderType;
|
|
73
|
+
}
|
|
74
|
+
if (!renderType) {
|
|
75
|
+
renderType = layer.type === 'HeatmapLayer' ? 'Heatmap' : 'Single Symbol';
|
|
76
|
+
}
|
|
77
|
+
setSelectedRenderType(renderType);
|
|
78
|
+
}, []);
|
|
68
79
|
const { featureProperties, isLoading: featuresLoading } = useGetProperties({
|
|
69
80
|
layerId,
|
|
70
81
|
model: model,
|
|
71
82
|
});
|
|
72
|
-
|
|
83
|
+
if (!layerId || !(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
73
86
|
if (featuresLoading) {
|
|
74
87
|
return React.createElement("p", null, "Loading...");
|
|
75
88
|
}
|
|
76
89
|
if (selectedRenderType === undefined) {
|
|
77
|
-
|
|
78
|
-
return;
|
|
90
|
+
return null;
|
|
79
91
|
}
|
|
80
92
|
const selectableRenderTypes = getSelectableRenderTypes(featureProperties, layer.type);
|
|
81
93
|
const selectedRenderTypeProps = selectableRenderTypes[selectedRenderType];
|
|
@@ -90,7 +102,7 @@ const VectorRendering = ({ model, state, okSignalPromise, cancel, layerId, }) =>
|
|
|
90
102
|
.filter(([renderType, renderTypeProps]) => renderTypeProps.layerTypeSupported &&
|
|
91
103
|
!(renderType === 'Heatmap' && symbologyTab === 'radius'))
|
|
92
104
|
.map(([renderType, _]) => (React.createElement("option", { key: renderType, value: renderType }, renderType)))))),
|
|
93
|
-
React.createElement(selectedRenderTypeProps.component, Object.assign({ model: model,
|
|
105
|
+
React.createElement(selectedRenderTypeProps.component, Object.assign({ model: model, okSignalPromise: okSignalPromise, layerId: layerId, isStorySegmentOverride: isStorySegmentOverride, segmentId: segmentId }, (selectedRenderTypeProps.isTabbed ? { symbologyTab } : {}), (selectedRenderTypeProps.selectableAttributesAndValues
|
|
94
106
|
? {
|
|
95
107
|
selectableAttributesAndValues: selectedRenderTypeProps.selectableAttributesAndValues,
|
|
96
108
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { useOkSignal } from "../../hooks/useOkSignal";
|
|
3
|
+
import { saveSymbology } from "../../symbologyUtils";
|
|
2
4
|
import ValueSelect from "../components/ValueSelect";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
import { useLatest } from "../../../../shared/hooks/useLatest";
|
|
6
|
+
const Canonical = ({ model, okSignalPromise, layerId, selectableAttributesAndValues, isStorySegmentOverride, segmentId, }) => {
|
|
5
7
|
const [selectedValue, setSelectedValue] = useState('');
|
|
8
|
+
const selectedValueRef = useLatest(selectedValue);
|
|
6
9
|
if (!layerId) {
|
|
7
10
|
return;
|
|
8
11
|
}
|
|
@@ -10,30 +13,17 @@ const Canonical = ({ model, state, okSignalPromise, cancel, layerId, selectableA
|
|
|
10
13
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
11
14
|
return;
|
|
12
15
|
}
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
okSignalPromise.promise.then(okSignal => {
|
|
15
|
-
okSignal.connect(handleOk, this);
|
|
16
|
-
});
|
|
17
|
-
return () => {
|
|
18
|
-
okSignalPromise.promise.then(okSignal => {
|
|
19
|
-
okSignal.disconnect(handleOk, this);
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
}, [selectedValue]);
|
|
23
16
|
useEffect(() => {
|
|
24
17
|
var _a, _b;
|
|
25
18
|
const layerParams = layer.parameters;
|
|
26
19
|
const value = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(selectableAttributesAndValues)[0];
|
|
27
20
|
setSelectedValue(value);
|
|
28
21
|
}, [selectableAttributesAndValues]);
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
selectedValueRef.current = selectedValue;
|
|
31
|
-
}, [selectedValue]);
|
|
32
22
|
const handleOk = () => {
|
|
33
23
|
if (!layer.parameters) {
|
|
34
24
|
return;
|
|
35
25
|
}
|
|
36
|
-
const colorExpr = ['get',
|
|
26
|
+
const colorExpr = ['get', selectedValueRef.current];
|
|
37
27
|
const newStyle = Object.assign({}, layer.parameters.color);
|
|
38
28
|
newStyle['fill-color'] = colorExpr;
|
|
39
29
|
newStyle['stroke-color'] = colorExpr;
|
|
@@ -42,14 +32,23 @@ const Canonical = ({ model, state, okSignalPromise, cancel, layerId, selectableA
|
|
|
42
32
|
renderType: 'Canonical',
|
|
43
33
|
value: selectedValueRef.current,
|
|
44
34
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
saveSymbology({
|
|
36
|
+
model,
|
|
37
|
+
layerId,
|
|
38
|
+
isStorySegmentOverride,
|
|
39
|
+
segmentId,
|
|
40
|
+
payload: {
|
|
41
|
+
symbologyState,
|
|
42
|
+
color: newStyle,
|
|
43
|
+
},
|
|
44
|
+
mutateLayerBeforeSave: targetLayer => {
|
|
45
|
+
if (targetLayer.type === 'HeatmapLayer') {
|
|
46
|
+
targetLayer.type = 'VectorLayer';
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
});
|
|
52
50
|
};
|
|
51
|
+
useOkSignal(okSignalPromise, handleOk);
|
|
53
52
|
const body = (() => {
|
|
54
53
|
var _a;
|
|
55
54
|
if (((_a = Object.keys(selectableAttributesAndValues)) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import ColorRampControls from "../../components/color_ramp/ColorRampControls";
|
|
3
3
|
import StopContainer from "../../components/color_stops/StopContainer";
|
|
4
|
-
import {
|
|
4
|
+
import { useOkSignal } from "../../hooks/useOkSignal";
|
|
5
|
+
import { Utils, VectorUtils, saveSymbology, } from "../../symbologyUtils";
|
|
5
6
|
import ValueSelect from "../components/ValueSelect";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const colorRampOptionsRef = useRef();
|
|
7
|
+
import { useLatest } from "../../../../shared/hooks/useLatest";
|
|
8
|
+
import { useEffectiveSymbologyParams } from '../../hooks/useEffectiveSymbologyParams';
|
|
9
|
+
const Categorized = ({ model, okSignalPromise, layerId, symbologyTab, selectableAttributesAndValues, isStorySegmentOverride, segmentId, }) => {
|
|
10
10
|
const [selectedAttribute, setSelectedAttribute] = useState('');
|
|
11
11
|
const [stopRows, setStopRows] = useState([]);
|
|
12
12
|
const [colorRampOptions, setColorRampOptions] = useState();
|
|
@@ -16,34 +16,35 @@ const Categorized = ({ model, state, okSignalPromise, cancel, layerId, symbology
|
|
|
16
16
|
strokeWidth: 1.25,
|
|
17
17
|
radius: 5,
|
|
18
18
|
});
|
|
19
|
-
const manualStyleRef =
|
|
19
|
+
const manualStyleRef = useLatest(manualStyle);
|
|
20
20
|
const [reverseRamp, setReverseRamp] = useState(false);
|
|
21
|
+
const selectedAttributeRef = useLatest(selectedAttribute);
|
|
22
|
+
const stopRowsRef = useLatest(stopRows);
|
|
23
|
+
const colorRampOptionsRef = useLatest(colorRampOptions);
|
|
21
24
|
if (!layerId) {
|
|
22
25
|
return;
|
|
23
26
|
}
|
|
24
27
|
const layer = model.getLayer(layerId);
|
|
25
|
-
|
|
28
|
+
const params = useEffectiveSymbologyParams({
|
|
29
|
+
model,
|
|
30
|
+
layerId: layerId,
|
|
31
|
+
layer,
|
|
32
|
+
isStorySegmentOverride,
|
|
33
|
+
segmentId,
|
|
34
|
+
});
|
|
35
|
+
if (!params) {
|
|
26
36
|
return;
|
|
27
37
|
}
|
|
28
38
|
useEffect(() => {
|
|
29
|
-
const valueColorPairs = VectorUtils.buildColorInfo(
|
|
39
|
+
const valueColorPairs = VectorUtils.buildColorInfo(params);
|
|
30
40
|
setStopRows(valueColorPairs);
|
|
31
|
-
okSignalPromise.promise.then(okSignal => {
|
|
32
|
-
okSignal.connect(handleOk, this);
|
|
33
|
-
});
|
|
34
|
-
return () => {
|
|
35
|
-
okSignalPromise.promise.then(okSignal => {
|
|
36
|
-
okSignal.disconnect(handleOk, this);
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
41
|
}, []);
|
|
40
42
|
useEffect(() => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const circleStrokeColor = layer.parameters.color['circle-stroke-color'];
|
|
43
|
+
if (params.color) {
|
|
44
|
+
const fillColor = params.color['fill-color'];
|
|
45
|
+
const circleFillColor = params.color['circle-fill-color'];
|
|
46
|
+
const strokeColor = params.color['stroke-color'];
|
|
47
|
+
const circleStrokeColor = params.color['circle-stroke-color'];
|
|
47
48
|
const isSimpleColor = (val) => typeof val === 'string' && /^#?[0-9A-Fa-f]{3,8}$/.test(val);
|
|
48
49
|
setManualStyle({
|
|
49
50
|
fillColor: isSimpleColor(fillColor)
|
|
@@ -56,28 +57,19 @@ const Categorized = ({ model, state, okSignalPromise, cancel, layerId, symbology
|
|
|
56
57
|
: isSimpleColor(circleStrokeColor)
|
|
57
58
|
? circleStrokeColor
|
|
58
59
|
: '#3399CC',
|
|
59
|
-
strokeWidth:
|
|
60
|
-
|
|
60
|
+
strokeWidth: params.color['stroke-width'] ||
|
|
61
|
+
params.color['circle-stroke-width'] ||
|
|
61
62
|
1.25,
|
|
62
|
-
radius:
|
|
63
|
+
radius: params.color['circle-radius'] || 5,
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
66
|
}, [layerId]);
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
manualStyleRef.current = manualStyle;
|
|
68
|
-
}, [manualStyle]);
|
|
69
67
|
useEffect(() => {
|
|
70
68
|
var _a, _b;
|
|
71
69
|
// We only want number values here
|
|
72
|
-
const
|
|
73
|
-
const attribute = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(selectableAttributesAndValues)[0];
|
|
70
|
+
const attribute = (_b = (_a = params.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(selectableAttributesAndValues)[0];
|
|
74
71
|
setSelectedAttribute(attribute);
|
|
75
72
|
}, [selectableAttributesAndValues]);
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
selectedAttributeRef.current = selectedAttribute;
|
|
78
|
-
stopRowsRef.current = stopRows;
|
|
79
|
-
colorRampOptionsRef.current = colorRampOptions;
|
|
80
|
-
}, [selectedAttribute, stopRows, colorRampOptions]);
|
|
81
73
|
const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp, setIsLoading) => {
|
|
82
74
|
setColorRampOptions({
|
|
83
75
|
selectedFunction: '',
|
|
@@ -91,10 +83,7 @@ const Categorized = ({ model, state, okSignalPromise, cancel, layerId, symbology
|
|
|
91
83
|
};
|
|
92
84
|
const handleOk = () => {
|
|
93
85
|
var _a;
|
|
94
|
-
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const newStyle = Object.assign({}, layer.parameters.color);
|
|
86
|
+
const newStyle = Object.assign({}, params.color);
|
|
98
87
|
if (stopRowsRef.current && stopRowsRef.current.length > 0) {
|
|
99
88
|
// Classification applied (for color)
|
|
100
89
|
const expr = ['case'];
|
|
@@ -122,22 +111,31 @@ const Categorized = ({ model, state, okSignalPromise, cancel, layerId, symbology
|
|
|
122
111
|
renderType: 'Categorized',
|
|
123
112
|
value: selectedAttributeRef.current,
|
|
124
113
|
colorRamp: (_a = colorRampOptionsRef.current) === null || _a === void 0 ? void 0 : _a.selectedRamp,
|
|
125
|
-
symbologyTab,
|
|
114
|
+
method: symbologyTab,
|
|
126
115
|
reverse: reverseRamp,
|
|
127
116
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
saveSymbology({
|
|
118
|
+
model,
|
|
119
|
+
layerId,
|
|
120
|
+
isStorySegmentOverride,
|
|
121
|
+
segmentId,
|
|
122
|
+
payload: {
|
|
123
|
+
symbologyState,
|
|
124
|
+
color: newStyle,
|
|
125
|
+
},
|
|
126
|
+
mutateLayerBeforeSave: targetLayer => {
|
|
127
|
+
if (targetLayer.type === 'HeatmapLayer') {
|
|
128
|
+
targetLayer.type = 'VectorLayer';
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
135
132
|
};
|
|
133
|
+
useOkSignal(okSignalPromise, handleOk);
|
|
136
134
|
const handleReset = (method) => {
|
|
137
135
|
if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
138
136
|
return;
|
|
139
137
|
}
|
|
140
|
-
const newStyle = Object.assign({},
|
|
138
|
+
const newStyle = Object.assign({}, params.color);
|
|
141
139
|
if (method === 'color') {
|
|
142
140
|
delete newStyle['fill-color'];
|
|
143
141
|
delete newStyle['stroke-color'];
|
|
@@ -190,7 +188,8 @@ const Categorized = ({ model, state, okSignalPromise, cancel, layerId, symbology
|
|
|
190
188
|
React.createElement("input", { type: "checkbox", checked: reverseRamp, onChange: e => setReverseRamp(e.target.checked) }),
|
|
191
189
|
"Reverse Color Ramp"))),
|
|
192
190
|
React.createElement("div", { className: "jp-gis-layer-symbology-container" },
|
|
193
|
-
|
|
191
|
+
"//! only needs symbology state",
|
|
192
|
+
React.createElement(ColorRampControls, { layerParams: params, modeOptions: [], classifyFunc: buildColorInfoFromClassification, showModeRow: false, showRampSelector: symbologyTab === 'color' }),
|
|
194
193
|
React.createElement(StopContainer, { selectedMethod: '', stopRows: stopRows, setStopRows: setStopRows }))));
|
|
195
194
|
}
|
|
196
195
|
})();
|