Skip to content

Commit d9a8a11

Browse files
committed
Refactor color ramp components to use ClassificationMode type for improved type safety
1 parent df05094 commit d9a8a11

File tree

6 files changed

+63
-27
lines changed

6 files changed

+63
-27
lines changed

packages/base/src/dialogs/symbology/components/color_ramp/ColorRamp.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import { Button } from '@jupyterlab/ui-components';
33
import React, { useEffect, useState } from 'react';
44

55
import { LoadingIcon } from '@/src/shared/components/loading';
6+
import { ClassificationMode } from '@/src/types';
67
import CanvasSelectComponent from './CanvasSelectComponent';
78
import ModeSelectRow from './ModeSelectRow';
89

910
interface IColorRampProps {
10-
modeOptions: string[];
11+
modeOptions: ClassificationMode[];
1112
layerParams: IDict;
1213
classifyFunc: (
13-
selectedMode: string,
14-
numberOfShades: string,
14+
selectedMode: ClassificationMode | undefined,
15+
numberOfShades: number | undefined,
1516
selectedRamp: string,
1617
setIsLoading: (isLoading: boolean) => void,
1718
) => void;
@@ -21,8 +22,8 @@ interface IColorRampProps {
2122

2223
export type ColorRampOptions = {
2324
selectedRamp: string;
24-
numberOfShades: string;
25-
selectedMode: string;
25+
numberOfShades: number | undefined;
26+
selectedMode: ClassificationMode | undefined;
2627
};
2728

2829
const ColorRamp: React.FC<IColorRampProps> = ({
@@ -33,12 +34,14 @@ const ColorRamp: React.FC<IColorRampProps> = ({
3334
showRampSelector,
3435
}) => {
3536
const [selectedRamp, setSelectedRamp] = useState('');
36-
const [selectedMode, setSelectedMode] = useState<string>('');
37-
const [numberOfShades, setNumberOfShades] = useState<string>('');
37+
const [selectedMode, setSelectedMode] = useState<
38+
ClassificationMode | undefined
39+
>();
40+
const [numberOfShades, setNumberOfShades] = useState<number | undefined>();
3841
const [isLoading, setIsLoading] = useState<boolean>(false);
3942

4043
useEffect(() => {
41-
if (selectedRamp === '' && selectedMode === '' && numberOfShades === '') {
44+
if (selectedRamp === '') {
4245
populateOptions();
4346
}
4447
}, [layerParams]);
@@ -52,7 +55,7 @@ const ColorRamp: React.FC<IColorRampProps> = ({
5255
colorRamp = layerParams.symbologyState.colorRamp;
5356
}
5457
setNumberOfShades(nClasses ? nClasses : '9');
55-
setSelectedMode(singleBandMode ? singleBandMode : 'equal interval');
58+
setSelectedMode((singleBandMode as ClassificationMode) ?? 'equal interval');
5659
setSelectedRamp(colorRamp ? colorRamp : 'viridis');
5760
};
5861

packages/base/src/dialogs/symbology/components/color_ramp/ModeSelectRow.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import React from 'react';
2+
3+
import { ClassificationMode } from '@/src/types';
24
interface IModeSelectRowProps {
3-
numberOfShades: string;
4-
setNumberOfShades: (value: string) => void;
5-
selectedMode: string;
6-
setSelectedMode: (value: string) => void;
7-
modeOptions: string[];
5+
numberOfShades: number | undefined;
6+
setNumberOfShades: (value: number | undefined) => void;
7+
selectedMode: ClassificationMode | undefined;
8+
setSelectedMode: (value: ClassificationMode | undefined) => void;
9+
modeOptions: ClassificationMode[];
810
}
911
const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
1012
numberOfShades,
@@ -21,8 +23,11 @@ const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
2123
className="jp-mod-styled"
2224
name="class-number-input"
2325
type="number"
24-
value={selectedMode === 'continuous' ? 52 : numberOfShades}
25-
onChange={event => setNumberOfShades(event.target.value)}
26+
value={selectedMode === 'continuous' ? 52 : (numberOfShades ?? '')}
27+
onChange={event => {
28+
const value = event.target.value;
29+
setNumberOfShades(value === '' ? undefined : Number(value));
30+
}}
2631
disabled={selectedMode === 'continuous'}
2732
/>
2833
</div>
@@ -34,10 +39,12 @@ const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
3439
id="mode-select"
3540
className="jp-mod-styled"
3641
value={selectedMode}
37-
onChange={event => setSelectedMode(event.target.value)}
42+
onChange={event =>
43+
setSelectedMode(event.target.value as ClassificationMode)
44+
}
3845
>
3946
{modeOptions.map(mode => (
40-
<option key={mode} value={mode} selected={selectedMode === mode}>
47+
<option key={mode} value={mode}>
4148
{mode}
4249
</option>
4350
))}

packages/base/src/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Utils } from '@/src/dialogs/symbology/symbologyUtils';
2020
import BandRow from '@/src/dialogs/symbology/tiff_layer/components/BandRow';
2121
import { LoadingOverlay } from '@/src/shared/components/loading';
2222
import { GlobalStateDbManager } from '@/src/store';
23+
import { ClassificationMode } from '@/src/types';
2324

2425
export type InterpolationType = 'discrete' | 'linear' | 'exact';
2526

@@ -38,7 +39,11 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
3839
}
3940

4041
const functions = ['discrete', 'linear', 'exact'];
41-
const modeOptions = ['continuous', 'equal interval', 'quantile'];
42+
const modeOptions = [
43+
'continuous',
44+
'equal interval',
45+
'quantile',
46+
] as ClassificationMode[];
4247

4348
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
4449

@@ -282,8 +287,8 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
282287
};
283288

284289
const buildColorInfoFromClassification = async (
285-
selectedMode: string,
286-
numberOfShades: string,
290+
selectedMode: ClassificationMode | undefined,
291+
numberOfShades: number | undefined,
287292
selectedRamp: string,
288293
setIsLoading: (isLoading: boolean) => void,
289294
) => {
@@ -299,6 +304,10 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
299304
const currentBand = bandRows[selectedBand - 1];
300305
const source = model.getSource(layer?.parameters?.source);
301306
const sourceInfo = source?.parameters?.urls[0];
307+
if (!numberOfShades) {
308+
console.warn('No number of shades provided');
309+
return;
310+
}
302311
const nClasses = selectedMode === 'continuous' ? 52 : +numberOfShades;
303312

304313
setIsLoading(true);

packages/base/src/dialogs/symbology/vector_layer/types/Categorized.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '@/src/dialogs/symbology/symbologyDialog';
1212
import { Utils, VectorUtils } from '@/src/dialogs/symbology/symbologyUtils';
1313
import ValueSelect from '@/src/dialogs/symbology/vector_layer/components/ValueSelect';
14-
import { SymbologyTab } from '@/src/types';
14+
import { SymbologyTab, ClassificationMode } from '@/src/types';
1515

1616
const Categorized: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
1717
model,
@@ -117,8 +117,8 @@ const Categorized: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
117117
}, [selectedAttribute, stopRows, colorRampOptions]);
118118

119119
const buildColorInfoFromClassification = (
120-
selectedMode: string,
121-
numberOfShades: string,
120+
selectedMode: ClassificationMode | undefined,
121+
numberOfShades: number | undefined,
122122
selectedRamp: string,
123123
setIsLoading: (isLoading: boolean) => void,
124124
) => {

packages/base/src/dialogs/symbology/vector_layer/types/Graduated.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '@/src/dialogs/symbology/symbologyDialog';
1414
import { Utils, VectorUtils } from '@/src/dialogs/symbology/symbologyUtils';
1515
import ValueSelect from '@/src/dialogs/symbology/vector_layer/components/ValueSelect';
16+
import { ClassificationMode } from '@/src/types';
1617

1718
const Graduated: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
1819
model,
@@ -29,7 +30,7 @@ const Graduated: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
2930
'jenks',
3031
'pretty',
3132
'logarithmic',
32-
];
33+
] as ClassificationMode[];
3334

3435
const selectableAttributeRef = useRef<string>();
3536
const symbologyTabRef = useRef<string>();
@@ -215,8 +216,8 @@ const Graduated: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
215216
};
216217

217218
const buildColorInfoFromClassification = (
218-
selectedMode: string,
219-
numberOfShades: string,
219+
selectedMode: ClassificationMode | undefined,
220+
numberOfShades: number | undefined,
220221
selectedRamp: string,
221222
) => {
222223
setColorRampOptions({
@@ -229,6 +230,11 @@ const Graduated: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
229230

230231
const values = Array.from(selectableAttributesAndValues[selectedAttribute]);
231232

233+
if (!numberOfShades) {
234+
console.warn('No number of shades provided');
235+
return;
236+
}
237+
232238
switch (selectedMode) {
233239
case 'quantile':
234240
stops = VectorClassifications.calculateQuantileBreaks(

packages/base/src/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,14 @@ declare global {
4040
jupytergisMaps: { [name: string]: Map };
4141
}
4242
}
43+
44+
const classificationModes = [
45+
'quantile',
46+
'equal interval',
47+
'jenks',
48+
'pretty',
49+
'logarithmic',
50+
'continuous',
51+
] as const;
52+
53+
export type ClassificationMode = (typeof classificationModes)[number];

0 commit comments

Comments
 (0)