@jupytergis/base 0.1.5 → 0.1.7
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/classificationModes.d.ts +13 -0
- package/lib/classificationModes.js +326 -0
- package/lib/commands.js +1 -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 +115 -59
- 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/objectform/vectorlayerform.js +1 -0
- package/lib/formbuilder/objectform/webGlLayerForm.js +1 -0
- package/lib/index.d.ts +6 -4
- package/lib/index.js +6 -4
- package/lib/mainview/mainView.d.ts +3 -1
- package/lib/mainview/mainView.js +66 -18
- package/lib/store.d.ts +9 -0
- package/lib/store.js +25 -0
- package/lib/toolbar/widget.d.ts +2 -2
- package/lib/toolbar/widget.js +5 -5
- package/lib/types.d.ts +14 -0
- package/package.json +16 -17
- 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
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface IColorMap {
|
|
3
|
+
name: string;
|
|
4
|
+
colors: string[];
|
|
5
|
+
}
|
|
6
|
+
interface ICanvasSelectComponentProps {
|
|
7
|
+
selectedRamp: string;
|
|
8
|
+
setSelected: (item: any) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const CanvasSelectComponent: ({ selectedRamp, setSelected }: ICanvasSelectComponentProps) => React.JSX.Element;
|
|
11
|
+
export default CanvasSelectComponent;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Button } from '@jupyterlab/ui-components';
|
|
2
|
+
import colormap from 'colormap';
|
|
3
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import ColorRampEntry from './ColorRampEntry';
|
|
5
|
+
const CanvasSelectComponent = ({ selectedRamp, setSelected }) => {
|
|
6
|
+
const colorRampNames = [
|
|
7
|
+
'jet',
|
|
8
|
+
// 'hsv', 11 steps min
|
|
9
|
+
'hot',
|
|
10
|
+
'cool',
|
|
11
|
+
'spring',
|
|
12
|
+
'summer',
|
|
13
|
+
'autumn',
|
|
14
|
+
'winter',
|
|
15
|
+
'bone',
|
|
16
|
+
'copper',
|
|
17
|
+
'greys',
|
|
18
|
+
'YiGnBu',
|
|
19
|
+
'greens',
|
|
20
|
+
'YiOrRd',
|
|
21
|
+
'bluered',
|
|
22
|
+
'RdBu',
|
|
23
|
+
// 'picnic', 11 steps min
|
|
24
|
+
'rainbow',
|
|
25
|
+
'portland',
|
|
26
|
+
'blackbody',
|
|
27
|
+
'earth',
|
|
28
|
+
'electric',
|
|
29
|
+
'viridis',
|
|
30
|
+
'inferno',
|
|
31
|
+
'magma',
|
|
32
|
+
'plasma',
|
|
33
|
+
'warm',
|
|
34
|
+
// 'rainbow-soft', 11 steps min
|
|
35
|
+
'bathymetry',
|
|
36
|
+
'cdom',
|
|
37
|
+
'chlorophyll',
|
|
38
|
+
'density',
|
|
39
|
+
'freesurface-blue',
|
|
40
|
+
'freesurface-red',
|
|
41
|
+
'oxygen',
|
|
42
|
+
'par',
|
|
43
|
+
'phase',
|
|
44
|
+
'salinity',
|
|
45
|
+
'temperature',
|
|
46
|
+
'turbidity',
|
|
47
|
+
'velocity-blue',
|
|
48
|
+
'velocity-green'
|
|
49
|
+
// 'cubehelix' 16 steps min
|
|
50
|
+
];
|
|
51
|
+
const containerRef = useRef(null);
|
|
52
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
53
|
+
const [colorMaps, setColorMaps] = useState([]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const colorMapList = [];
|
|
56
|
+
colorRampNames.forEach(name => {
|
|
57
|
+
const colorRamp = colormap({
|
|
58
|
+
colormap: name,
|
|
59
|
+
nshades: 255,
|
|
60
|
+
format: 'rgbaString'
|
|
61
|
+
});
|
|
62
|
+
const colorMap = { name: name, colors: colorRamp };
|
|
63
|
+
colorMapList.push(colorMap);
|
|
64
|
+
setColorMaps(colorMapList);
|
|
65
|
+
});
|
|
66
|
+
}, []);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (colorMaps.length > 0) {
|
|
69
|
+
updateCanvas(selectedRamp);
|
|
70
|
+
}
|
|
71
|
+
}, [selectedRamp]);
|
|
72
|
+
const toggleDropdown = () => {
|
|
73
|
+
setIsOpen(!isOpen);
|
|
74
|
+
};
|
|
75
|
+
const selectItem = (item) => {
|
|
76
|
+
setSelected(item);
|
|
77
|
+
setIsOpen(false);
|
|
78
|
+
updateCanvas(item);
|
|
79
|
+
};
|
|
80
|
+
const handleOutsideClick = (event) => {
|
|
81
|
+
if (!containerRef.current) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (!containerRef.current.contains(event.target)) {
|
|
85
|
+
setIsOpen(false);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const updateCanvas = (rampName) => {
|
|
89
|
+
// update canvas for displayed color ramp
|
|
90
|
+
const canvas = document.getElementById('cv');
|
|
91
|
+
if (!canvas) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
canvas.style.visibility = 'hidden';
|
|
95
|
+
const ctx = canvas.getContext('2d');
|
|
96
|
+
if (!ctx) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const ramp = colorMaps.filter(c => c.name === rampName);
|
|
100
|
+
for (let i = 0; i <= 255; i++) {
|
|
101
|
+
ctx.beginPath();
|
|
102
|
+
const color = ramp[0].colors[i];
|
|
103
|
+
ctx.fillStyle = color;
|
|
104
|
+
ctx.fillRect(i * 2, 0, 2, 50);
|
|
105
|
+
}
|
|
106
|
+
canvas.style.visibility = 'initial';
|
|
107
|
+
};
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
document.addEventListener('mousedown', handleOutsideClick);
|
|
110
|
+
return () => {
|
|
111
|
+
document.removeEventListener('mousedown', handleOutsideClick);
|
|
112
|
+
};
|
|
113
|
+
}, []);
|
|
114
|
+
return (React.createElement("div", { ref: containerRef, className: "jp-gis-canvas-button-wrapper" },
|
|
115
|
+
React.createElement(Button, { id: "jp-gis-canvas-button", onClick: toggleDropdown, className: "jp-Dialog-button jp-gis-canvas-button" },
|
|
116
|
+
React.createElement("canvas", { id: "cv", className: "jp-gis-color-canvas-display", height: "30" })),
|
|
117
|
+
React.createElement("div", { className: `jp-gis-color-ramp-dropdown ${isOpen ? 'jp-gis-open' : ''}` }, colorMaps.map((item, index) => (React.createElement(ColorRampEntry, { index: index, colorMap: item, onClick: selectItem }))))));
|
|
118
|
+
};
|
|
119
|
+
export default CanvasSelectComponent;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IDict } from '@jupytergis/schema';
|
|
3
|
+
interface IColorRampProps {
|
|
4
|
+
modeOptions: string[];
|
|
5
|
+
layerParams: IDict;
|
|
6
|
+
classifyFunc: (selectedMode: string, numberOfShades: string, selectedRamp: string, setIsLoading: (isLoading: boolean) => void) => void;
|
|
7
|
+
showModeRow: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type ColorRampOptions = {
|
|
10
|
+
selectedRamp: string;
|
|
11
|
+
numberOfShades: string;
|
|
12
|
+
selectedMode: string;
|
|
13
|
+
};
|
|
14
|
+
declare const ColorRamp: ({ layerParams, modeOptions, classifyFunc, showModeRow }: IColorRampProps) => React.JSX.Element;
|
|
15
|
+
export default ColorRamp;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Button } from '@jupyterlab/ui-components';
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import CanvasSelectComponent from './CanvasSelectComponent';
|
|
4
|
+
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
|
|
5
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
6
|
+
import ModeSelectRow from './ModeSelectRow';
|
|
7
|
+
const ColorRamp = ({ layerParams, modeOptions, classifyFunc, showModeRow }) => {
|
|
8
|
+
const [selectedRamp, setSelectedRamp] = useState('');
|
|
9
|
+
const [selectedMode, setSelectedMode] = useState('');
|
|
10
|
+
const [numberOfShades, setNumberOfShades] = useState('');
|
|
11
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
populateOptions();
|
|
14
|
+
}, []);
|
|
15
|
+
const populateOptions = async () => {
|
|
16
|
+
let nClasses, singleBandMode, colorRamp;
|
|
17
|
+
if (layerParams.symbologyState) {
|
|
18
|
+
nClasses = layerParams.symbologyState.nClasses;
|
|
19
|
+
singleBandMode = layerParams.symbologyState.mode;
|
|
20
|
+
colorRamp = layerParams.symbologyState.colorRamp;
|
|
21
|
+
}
|
|
22
|
+
setNumberOfShades(nClasses ? nClasses : '9');
|
|
23
|
+
setSelectedMode(singleBandMode ? singleBandMode : 'equal interval');
|
|
24
|
+
setSelectedRamp(colorRamp ? colorRamp : 'cool');
|
|
25
|
+
};
|
|
26
|
+
return (React.createElement("div", { className: "jp-gis-color-ramp-container" },
|
|
27
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
28
|
+
React.createElement("label", { htmlFor: "color-ramp-select" }, "Color Ramp:"),
|
|
29
|
+
React.createElement(CanvasSelectComponent, { selectedRamp: selectedRamp, setSelected: setSelectedRamp })),
|
|
30
|
+
showModeRow && (React.createElement(ModeSelectRow, { modeOptions: modeOptions, numberOfShades: numberOfShades, setNumberOfShades: setNumberOfShades, selectedMode: selectedMode, setSelectedMode: setSelectedMode })),
|
|
31
|
+
isLoading ? (React.createElement(FontAwesomeIcon, { icon: faSpinner, className: "jp-gis-loading-spinner" })) : (React.createElement(Button, { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: () => classifyFunc(selectedMode, numberOfShades, selectedRamp, setIsLoading) }, "Classify"))));
|
|
32
|
+
};
|
|
33
|
+
export default ColorRamp;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IColorMap } from './CanvasSelectComponent';
|
|
3
|
+
interface IColorRampEntryProps {
|
|
4
|
+
index: number;
|
|
5
|
+
colorMap: IColorMap;
|
|
6
|
+
onClick: (item: any) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const ColorRampEntry: ({ index, colorMap, onClick }: IColorRampEntryProps) => React.JSX.Element;
|
|
9
|
+
export default ColorRampEntry;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
const ColorRampEntry = ({ index, colorMap, onClick }) => {
|
|
3
|
+
const canvasHeight = 30;
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const canvas = document.getElementById(`cv-${index}`);
|
|
6
|
+
if (!canvas) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const ctx = canvas.getContext('2d');
|
|
10
|
+
if (!ctx) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
for (let i = 0; i <= 255; i++) {
|
|
14
|
+
ctx.beginPath();
|
|
15
|
+
const color = colorMap.colors[i];
|
|
16
|
+
ctx.fillStyle = color;
|
|
17
|
+
ctx.fillRect(i * 2, 0, 2, canvasHeight);
|
|
18
|
+
}
|
|
19
|
+
}, []);
|
|
20
|
+
return (React.createElement("div", { key: colorMap.name, onClick: () => onClick(colorMap.name), className: "jp-gis-color-ramp-entry" },
|
|
21
|
+
React.createElement("span", { className: "jp-gis-color-label" }, colorMap.name),
|
|
22
|
+
React.createElement("canvas", { id: `cv-${index}`, height: canvasHeight, className: "jp-gis-color-canvas" })));
|
|
23
|
+
};
|
|
24
|
+
export default ColorRampEntry;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface IModeSelectRowProps {
|
|
3
|
+
numberOfShades: string;
|
|
4
|
+
setNumberOfShades: (value: string) => void;
|
|
5
|
+
selectedMode: string;
|
|
6
|
+
setSelectedMode: (value: string) => void;
|
|
7
|
+
modeOptions: string[];
|
|
8
|
+
}
|
|
9
|
+
declare const ModeSelectRow: ({ numberOfShades, setNumberOfShades, selectedMode, setSelectedMode, modeOptions }: IModeSelectRowProps) => React.JSX.Element;
|
|
10
|
+
export default ModeSelectRow;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
const ModeSelectRow = ({ numberOfShades, setNumberOfShades, selectedMode, setSelectedMode, modeOptions }) => {
|
|
3
|
+
return (React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
4
|
+
React.createElement("div", { className: "jp-gis-color-ramp-div" },
|
|
5
|
+
React.createElement("label", { htmlFor: "class-number-input" }, "Classes:"),
|
|
6
|
+
React.createElement("input", { className: "jp-mod-styled", name: "class-number-input", type: "number", value: selectedMode === 'continuous' ? 52 : numberOfShades, onChange: event => setNumberOfShades(event.target.value), disabled: selectedMode === 'continuous' })),
|
|
7
|
+
React.createElement("div", { className: "jp-gis-color-ramp-div" },
|
|
8
|
+
React.createElement("label", { htmlFor: "mode-select" }, "Mode:"),
|
|
9
|
+
React.createElement("select", { name: "mode-select", onChange: event => setSelectedMode(event.target.value) }, modeOptions.map(mode => (React.createElement("option", { className: "jp-mod-styled", value: mode, selected: selectedMode === mode }, mode)))))));
|
|
10
|
+
};
|
|
11
|
+
export default ModeSelectRow;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IStopRow } from '../../symbologyDialog';
|
|
3
|
+
interface IStopContainerProps {
|
|
4
|
+
selectedMethod: string;
|
|
5
|
+
stopRows: IStopRow[];
|
|
6
|
+
setStopRows: (stops: IStopRow[]) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const StopContainer: ({ selectedMethod, stopRows, setStopRows }: IStopContainerProps) => React.JSX.Element;
|
|
9
|
+
export default StopContainer;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button } from '@jupyterlab/ui-components';
|
|
3
|
+
import StopRow from './StopRow';
|
|
4
|
+
const StopContainer = ({ selectedMethod, stopRows, setStopRows }) => {
|
|
5
|
+
const addStopRow = () => {
|
|
6
|
+
setStopRows([
|
|
7
|
+
{
|
|
8
|
+
stop: 0,
|
|
9
|
+
output: [0, 0, 0, 1]
|
|
10
|
+
},
|
|
11
|
+
...stopRows
|
|
12
|
+
]);
|
|
13
|
+
};
|
|
14
|
+
const deleteStopRow = (index) => {
|
|
15
|
+
const newFilters = [...stopRows];
|
|
16
|
+
newFilters.splice(index, 1);
|
|
17
|
+
setStopRows(newFilters);
|
|
18
|
+
};
|
|
19
|
+
return (React.createElement(React.Fragment, null,
|
|
20
|
+
React.createElement("div", { className: "jp-gis-stop-container" },
|
|
21
|
+
React.createElement("div", { className: "jp-gis-stop-labels", style: { display: 'flex', gap: 6 } },
|
|
22
|
+
React.createElement("span", { style: { flex: '0 0 18%' } }, "Value"),
|
|
23
|
+
React.createElement("span", null, "Output Value")),
|
|
24
|
+
stopRows.map((stop, index) => (React.createElement(StopRow, { key: `${index}-${stop.output}`, index: index, value: stop.stop, outputValue: stop.output, stopRows: stopRows, setStopRows: setStopRows, deleteRow: () => deleteStopRow(index), useNumber: selectedMethod === 'radius' ? true : false })))),
|
|
25
|
+
React.createElement("div", { className: "jp-gis-symbology-button-container" },
|
|
26
|
+
React.createElement(Button, { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: addStopRow }, "Add Stop"))));
|
|
27
|
+
};
|
|
28
|
+
export default StopContainer;
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
|
2
2
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
3
3
|
import { Button } from '@jupyterlab/ui-components';
|
|
4
|
-
import React from 'react';
|
|
4
|
+
import React, { useEffect, useRef } from 'react';
|
|
5
5
|
const StopRow = ({ index, value, outputValue, stopRows, setStopRows, deleteRow, useNumber }) => {
|
|
6
|
+
const inputRef = useRef(null);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
var _a;
|
|
9
|
+
if (inputRef.current === document.activeElement) {
|
|
10
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
11
|
+
}
|
|
12
|
+
}, [stopRows]);
|
|
6
13
|
const rgbArrToHex = (rgbArr) => {
|
|
7
14
|
if (!Array.isArray(rgbArr)) {
|
|
8
15
|
return;
|
|
@@ -56,7 +63,7 @@ const StopRow = ({ index, value, outputValue, stopRows, setStopRows, deleteRow,
|
|
|
56
63
|
};
|
|
57
64
|
return (React.createElement("div", { className: "jp-gis-color-row" },
|
|
58
65
|
React.createElement("input", { id: `jp-gis-color-value-${index}`, type: "number", value: value, onChange: handleStopChange, onBlur: handleBlur, className: "jp-mod-styled jp-gis-color-row-value-input" }),
|
|
59
|
-
useNumber ? (React.createElement("input", { type: "number", value: outputValue, onChange: handleOutputChange, className: "jp-mod-styled jp-gis-color-row-output-input" })) : (React.createElement("input", { id: `jp-gis-color-color-${index}`, value: rgbArrToHex(outputValue), type: "color", onChange: handleOutputChange, className: "jp-mod-styled jp-gis-color-row-output-input" })),
|
|
66
|
+
useNumber ? (React.createElement("input", { type: "number", ref: inputRef, value: outputValue, onChange: handleOutputChange, className: "jp-mod-styled jp-gis-color-row-output-input" })) : (React.createElement("input", { id: `jp-gis-color-color-${index}`, ref: inputRef, value: rgbArrToHex(outputValue), type: "color", onChange: handleOutputChange, className: "jp-mod-styled jp-gis-color-row-output-input" })),
|
|
60
67
|
React.createElement(Button, { id: `jp-gis-remove-color-${index}`, className: "jp-Button jp-gis-filter-icon" },
|
|
61
68
|
React.createElement(FontAwesomeIcon, { icon: faTrash, onClick: deleteRow }))));
|
|
62
69
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IJupyterGISModel } from '@jupytergis/schema';
|
|
2
|
+
interface IUseGetPropertiesProps {
|
|
3
|
+
layerId?: string;
|
|
4
|
+
model: IJupyterGISModel;
|
|
5
|
+
}
|
|
6
|
+
interface IUseGetPropertiesResult {
|
|
7
|
+
featureProps: Record<string, Set<any>>;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
error?: Error;
|
|
10
|
+
}
|
|
11
|
+
export declare const useGetProperties: ({ layerId, model }: IUseGetPropertiesProps) => IUseGetPropertiesResult;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// import { GeoJSONFeature } from 'geojson';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
export const useGetProperties = ({ layerId, model }) => {
|
|
4
|
+
const [featureProps, setFeatureProps] = useState({});
|
|
5
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
6
|
+
const [error, setError] = useState(undefined);
|
|
7
|
+
const getProperties = async () => {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
if (!layerId) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const layer = model.getLayer(layerId);
|
|
14
|
+
const source = model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
|
|
15
|
+
if (!source) {
|
|
16
|
+
throw new Error('Source not found');
|
|
17
|
+
}
|
|
18
|
+
const data = await model.readGeoJSON((_b = source.parameters) === null || _b === void 0 ? void 0 : _b.path);
|
|
19
|
+
if (!data) {
|
|
20
|
+
throw new Error('Failed to read GeoJSON data');
|
|
21
|
+
}
|
|
22
|
+
const result = {};
|
|
23
|
+
data.features.forEach((feature) => {
|
|
24
|
+
if (feature.properties) {
|
|
25
|
+
Object.entries(feature.properties).forEach(([key, value]) => {
|
|
26
|
+
if (typeof value !== 'string') {
|
|
27
|
+
if (!(key in result)) {
|
|
28
|
+
result[key] = new Set();
|
|
29
|
+
}
|
|
30
|
+
result[key].add(value);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
setFeatureProps(result);
|
|
36
|
+
setIsLoading(false);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
setError(err);
|
|
40
|
+
setIsLoading(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
getProperties();
|
|
45
|
+
}, [model, layerId]);
|
|
46
|
+
return { featureProps, isLoading, error };
|
|
47
|
+
};
|
|
@@ -2,8 +2,8 @@ import { Dialog } from '@jupyterlab/apputils';
|
|
|
2
2
|
import { PromiseDelegate } from '@lumino/coreutils';
|
|
3
3
|
import { Signal } from '@lumino/signaling';
|
|
4
4
|
import React, { useEffect, useState } from 'react';
|
|
5
|
-
import
|
|
6
|
-
import VectorRendering from './
|
|
5
|
+
import TiffRendering from './tiff_layer/TiffRendering';
|
|
6
|
+
import VectorRendering from './vector_layer/VectorRendering';
|
|
7
7
|
const SymbologyDialog = ({ context, state, okSignalPromise, cancel }) => {
|
|
8
8
|
const [selectedLayer, setSelectedLayer] = useState(null);
|
|
9
9
|
const [componentToRender, setComponentToRender] = useState(null);
|
|
@@ -39,7 +39,7 @@ const SymbologyDialog = ({ context, state, okSignalPromise, cancel }) => {
|
|
|
39
39
|
LayerSymbology = (React.createElement(VectorRendering, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: selectedLayer }));
|
|
40
40
|
break;
|
|
41
41
|
case 'WebGlLayer':
|
|
42
|
-
LayerSymbology = (React.createElement(
|
|
42
|
+
LayerSymbology = (React.createElement(TiffRendering, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: selectedLayer }));
|
|
43
43
|
break;
|
|
44
44
|
default:
|
|
45
45
|
LayerSymbology = React.createElement("div", null, "Layer Type Not Supported");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IJGISLayer } from '@jupytergis/schema';
|
|
2
|
+
import { IStopRow } from './symbologyDialog';
|
|
3
|
+
export declare namespace VectorUtils {
|
|
4
|
+
const buildColorInfo: (layer: IJGISLayer) => IStopRow[];
|
|
5
|
+
const buildRadiusInfo: (layer: IJGISLayer) => IStopRow[];
|
|
6
|
+
}
|
|
7
|
+
export declare namespace Utils {
|
|
8
|
+
const getValueColorPairs: (stops: number[], selectedRamp: string, nClasses: number) => IStopRow[];
|
|
9
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import colormap from 'colormap';
|
|
2
|
+
export var VectorUtils;
|
|
3
|
+
(function (VectorUtils) {
|
|
4
|
+
VectorUtils.buildColorInfo = (layer) => {
|
|
5
|
+
var _a;
|
|
6
|
+
// This it to parse a color object on the layer
|
|
7
|
+
if (!((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.color)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const color = layer.parameters.color;
|
|
11
|
+
// If color is a string we don't need to parse
|
|
12
|
+
if (typeof color === 'string') {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const prefix = layer.parameters.type === 'circle' ? 'circle-' : '';
|
|
16
|
+
if (!color[`${prefix}fill-color`]) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const valueColorPairs = [];
|
|
20
|
+
// So if it's not a string then it's an array and we parse
|
|
21
|
+
// Color[0] is the operator used for the color expression
|
|
22
|
+
switch (color[`${prefix}fill-color`][0]) {
|
|
23
|
+
case 'interpolate':
|
|
24
|
+
// First element is interpolate for linear selection
|
|
25
|
+
// Second element is type of interpolation (ie linear)
|
|
26
|
+
// Third is input value that stop values are compared with
|
|
27
|
+
// Fourth and on is value:color pairs
|
|
28
|
+
for (let i = 3; i < color[`${prefix}fill-color`].length; i += 2) {
|
|
29
|
+
const obj = {
|
|
30
|
+
stop: color[`${prefix}fill-color`][i],
|
|
31
|
+
output: color[`${prefix}fill-color`][i + 1]
|
|
32
|
+
};
|
|
33
|
+
valueColorPairs.push(obj);
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
case 'case':
|
|
37
|
+
for (let i = 1; i < color[`${prefix}fill-color`].length - 1; i += 2) {
|
|
38
|
+
const obj = {
|
|
39
|
+
stop: color[`${prefix}fill-color`][i][2],
|
|
40
|
+
output: color[`${prefix}fill-color`][i + 1]
|
|
41
|
+
};
|
|
42
|
+
valueColorPairs.push(obj);
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
return valueColorPairs;
|
|
47
|
+
};
|
|
48
|
+
VectorUtils.buildRadiusInfo = (layer) => {
|
|
49
|
+
var _a;
|
|
50
|
+
if (!((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.color)) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const color = layer.parameters.color;
|
|
54
|
+
// If color is a string we don't need to parse
|
|
55
|
+
if (typeof color === 'string') {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const stopOutputPairs = [];
|
|
59
|
+
for (let i = 3; i < color['circle-radius'].length; i += 2) {
|
|
60
|
+
const obj = {
|
|
61
|
+
stop: color['circle-radius'][i],
|
|
62
|
+
output: color['circle-radius'][i + 1]
|
|
63
|
+
};
|
|
64
|
+
stopOutputPairs.push(obj);
|
|
65
|
+
}
|
|
66
|
+
return stopOutputPairs;
|
|
67
|
+
};
|
|
68
|
+
})(VectorUtils || (VectorUtils = {}));
|
|
69
|
+
export var Utils;
|
|
70
|
+
(function (Utils) {
|
|
71
|
+
Utils.getValueColorPairs = (stops, selectedRamp, nClasses) => {
|
|
72
|
+
let colorMap = colormap({
|
|
73
|
+
colormap: selectedRamp,
|
|
74
|
+
nshades: nClasses > 9 ? nClasses : 9,
|
|
75
|
+
format: 'rgba'
|
|
76
|
+
});
|
|
77
|
+
const valueColorPairs = [];
|
|
78
|
+
// colormap requires 9 classes to generate the ramp
|
|
79
|
+
// so we do some tomfoolery to make it work with less than 9 stops
|
|
80
|
+
if (nClasses < 9) {
|
|
81
|
+
const midIndex = Math.floor(nClasses / 2);
|
|
82
|
+
// Get the first n/2 elements from the second array
|
|
83
|
+
const firstPart = colorMap.slice(0, midIndex);
|
|
84
|
+
// Get the last n/2 elements from the second array
|
|
85
|
+
const secondPart = colorMap.slice(colorMap.length - (stops.length - firstPart.length));
|
|
86
|
+
// Create the new array by combining the first and last parts
|
|
87
|
+
colorMap = firstPart.concat(secondPart);
|
|
88
|
+
}
|
|
89
|
+
for (let i = 0; i < nClasses; i++) {
|
|
90
|
+
valueColorPairs.push({ stop: stops[i], output: colorMap[i] });
|
|
91
|
+
}
|
|
92
|
+
return valueColorPairs;
|
|
93
|
+
};
|
|
94
|
+
})(Utils || (Utils = {}));
|
package/lib/dialogs/{components/symbology/BandRendering.js → symbology/tiff_layer/TiffRendering.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import SingleBandPseudoColor from './SingleBandPseudoColor';
|
|
3
|
-
const
|
|
2
|
+
import SingleBandPseudoColor from './types/SingleBandPseudoColor';
|
|
3
|
+
const TiffRendering = ({ context, state, okSignalPromise, cancel, layerId }) => {
|
|
4
4
|
const renderTypes = ['Singleband Pseudocolor', 'Multiband Color'];
|
|
5
5
|
const [selectedRenderType, setSelectedRenderType] = useState('Singleband Pseudocolor');
|
|
6
6
|
const [componentToRender, setComponentToRender] = useState(null);
|
|
@@ -26,4 +26,4 @@ const BandRendering = ({ context, state, okSignalPromise, cancel, layerId }) =>
|
|
|
26
26
|
} }, renderTypes.map((func, funcIndex) => (React.createElement("option", { key: func, value: func }, func))))),
|
|
27
27
|
componentToRender));
|
|
28
28
|
};
|
|
29
|
-
export default
|
|
29
|
+
export default TiffRendering;
|
package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.d.ts
RENAMED
|
@@ -11,6 +11,14 @@ export interface IBandRow {
|
|
|
11
11
|
stdDev: number;
|
|
12
12
|
};
|
|
13
13
|
metadata: IDict;
|
|
14
|
+
histogram: IBandHistogram;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
export interface IBandHistogram {
|
|
17
|
+
buckets: number[];
|
|
18
|
+
count: number;
|
|
19
|
+
max: number;
|
|
20
|
+
min: number;
|
|
21
|
+
}
|
|
22
|
+
export type InterpolationType = 'discrete' | 'linear' | 'exact';
|
|
23
|
+
declare const SingleBandPseudoColor: ({ context, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
|
|
16
24
|
export default SingleBandPseudoColor;
|