Skip to content

Commit a54c7e4

Browse files
committed
Resolving conflicts again
1 parent 612d0fa commit a54c7e4

File tree

17 files changed

+418
-250
lines changed

17 files changed

+418
-250
lines changed

packages/base/src/commands/index.ts

Lines changed: 6 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,7 @@ export function addCommands(
508508
label: trans.__('Rename Layer'),
509509
execute: async () => {
510510
const model = tracker.currentWidget?.model;
511-
await Private.renameSelectedItem(model, 'layer', (layerId, newName) => {
512-
const layer = model?.getLayer(layerId);
513-
if (layer) {
514-
layer.name = newName;
515-
model?.sharedModel.updateLayer(layerId, layer);
516-
}
517-
});
511+
await Private.renameSelectedItem(model, 'layer');
518512
},
519513
});
520514

@@ -532,9 +526,7 @@ export function addCommands(
532526
label: trans.__('Rename Group'),
533527
execute: async () => {
534528
const model = tracker.currentWidget?.model;
535-
await Private.renameSelectedItem(model, 'group', (groupName, newName) => {
536-
model?.renameLayerGroup(groupName, newName);
537-
});
529+
await Private.renameSelectedItem(model, 'group');
538530
},
539531
});
540532

@@ -635,13 +627,7 @@ export function addCommands(
635627
label: trans.__('Rename Source'),
636628
execute: async () => {
637629
const model = tracker.currentWidget?.model;
638-
await Private.renameSelectedItem(model, 'source', (sourceId, newName) => {
639-
const source = model?.getSource(sourceId);
640-
if (source) {
641-
source.name = newName;
642-
model?.sharedModel.updateSource(sourceId, source);
643-
}
644-
});
630+
await Private.renameSelectedItem(model, 'source');
645631
},
646632
});
647633

@@ -1146,39 +1132,6 @@ namespace Private {
11461132
};
11471133
}
11481134

1149-
export async function getUserInputForRename(
1150-
text: HTMLElement,
1151-
input: HTMLInputElement,
1152-
original: string,
1153-
): Promise<string> {
1154-
const parent = text.parentElement as HTMLElement;
1155-
parent.replaceChild(input, text);
1156-
input.value = original;
1157-
input.select();
1158-
input.focus();
1159-
1160-
return new Promise<string>(resolve => {
1161-
input.addEventListener('blur', () => {
1162-
parent.replaceChild(text, input);
1163-
resolve(input.value);
1164-
});
1165-
1166-
input.addEventListener('keydown', (event: KeyboardEvent) => {
1167-
if (event.key === 'Enter') {
1168-
event.stopPropagation();
1169-
event.preventDefault();
1170-
input.blur();
1171-
} else if (event.key === 'Escape') {
1172-
event.stopPropagation();
1173-
event.preventDefault();
1174-
input.value = original;
1175-
input.blur();
1176-
text.focus();
1177-
}
1178-
});
1179-
});
1180-
}
1181-
11821135
export function removeSelectedItems(
11831136
model: IJupyterGISModel | undefined,
11841137
itemTypeToRemove: SelectionType,
@@ -1201,11 +1154,10 @@ namespace Private {
12011154
export async function renameSelectedItem(
12021155
model: IJupyterGISModel | undefined,
12031156
itemType: SelectionType,
1204-
callback: (itemId: string, newName: string) => void,
12051157
) {
12061158
const selectedItems = model?.localState?.selected.value;
12071159

1208-
if (!selectedItems) {
1160+
if (!selectedItems || !model) {
12091161
console.error(`No ${itemType} selected`);
12101162
return;
12111163
}
@@ -1224,34 +1176,8 @@ namespace Private {
12241176
return;
12251177
}
12261178

1227-
const nodeId = selectedItems[itemId].selectedNodeId;
1228-
if (!nodeId) {
1229-
return;
1230-
}
1231-
1232-
const node = document.getElementById(nodeId);
1233-
if (!node) {
1234-
console.warn(`Node with ID ${nodeId} not found`);
1235-
return;
1236-
}
1237-
1238-
const edit = document.createElement('input');
1239-
edit.classList.add('jp-gis-left-panel-input');
1240-
const originalName = node.innerText;
1241-
const newName = await Private.getUserInputForRename(
1242-
node,
1243-
edit,
1244-
originalName,
1245-
);
1246-
1247-
if (!newName) {
1248-
console.warn('New name cannot be empty');
1249-
return;
1250-
}
1251-
1252-
if (newName !== originalName) {
1253-
callback(itemId, newName);
1254-
}
1179+
// Set editing state - component will show inline input
1180+
model.setEditingItem(itemType, itemId);
12551181
}
12561182

12571183
export function executeConsole(tracker: JupyterGISTracker): void {

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

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,21 @@ import React, { useEffect, useState } from 'react';
2323

2424
import { COLOR_RAMP_DEFINITIONS } from '@/src/dialogs/symbology/colorRamps';
2525
import { LoadingIcon } from '@/src/shared/components/loading';
26-
import { COLOR_RAMP_DEFAULTS, ColorRampName } from '@/src/types';
26+
import {
27+
COLOR_RAMP_DEFAULTS,
28+
ColorRampName,
29+
ClassificationMode,
30+
} from '@/src/types';
2731
import ColorRampSelector from './ColorRampSelector';
2832
import { ColorRampValueControls } from './ColorRampValueControls';
2933
import ModeSelectRow from './ModeSelectRow';
3034

3135
interface IColorRampControlsProps {
32-
modeOptions: string[];
36+
modeOptions: ClassificationMode[];
3337
layerParams: IDict;
3438
classifyFunc: (
35-
selectedMode: string,
36-
numberOfShades: string,
39+
selectedMode: ClassificationMode,
40+
numberOfShades: number,
3741
selectedRamp: ColorRampName,
3842
reverseRamp: boolean,
3943
setIsLoading: (isLoading: boolean) => void,
@@ -53,15 +57,17 @@ interface IColorRampControlsProps {
5357
}
5458

5559
export type ColorRampControlsOptions = {
56-
selectedRamp: string;
57-
numberOfShades: string;
58-
selectedMode: string;
60+
selectedRamp: ColorRampName;
61+
numberOfShades: number;
62+
selectedMode: ClassificationMode;
5963
minValue: number;
6064
maxValue: number;
6165
criticalValue?: number;
6266
reverseRamp: boolean;
6367
};
6468

69+
const isValidNumberOfShades = (value: number) => !isNaN(value) && value > 0;
70+
6571
const ColorRampControls: React.FC<IColorRampControlsProps> = ({
6672
layerParams,
6773
modeOptions,
@@ -74,18 +80,23 @@ const ColorRampControls: React.FC<IColorRampControlsProps> = ({
7480
}) => {
7581
const [selectedRamp, setSelectedRamp] = useState<ColorRampName>('viridis');
7682
const [reverseRamp, setReverseRamp] = useState<boolean>(false);
77-
const [selectedMode, setSelectedMode] = useState('');
78-
const [numberOfShades, setNumberOfShades] = useState('');
83+
const [selectedMode, setSelectedMode] =
84+
useState<ClassificationMode>('equal interval');
85+
const [numberOfShades, setNumberOfShades] = useState<number>(9);
7986
const [minValue, setMinValue] = useState<number | undefined>(dataMin);
8087
const [maxValue, setMaxValue] = useState<number | undefined>(dataMax);
8188
const [isLoading, setIsLoading] = useState(false);
8289
const [warning, setWarning] = useState<string | null>(null);
8390

8491
useEffect(() => {
85-
if (selectedMode === '' && numberOfShades === '') {
92+
if (layerParams.symbologyState) {
8693
initializeState();
8794
}
88-
}, [layerParams]);
95+
}, [
96+
layerParams.symbologyState?.nClasses,
97+
layerParams.symbologyState?.mode,
98+
layerParams.symbologyState?.colorRamp,
99+
]);
89100

90101
useEffect(() => {
91102
setMinValue(layerParams.symbologyState?.min ?? dataMin);
@@ -97,10 +108,9 @@ const ColorRampControls: React.FC<IColorRampControlsProps> = ({
97108
return;
98109
}
99110

100-
const defaultClasses =
101-
COLOR_RAMP_DEFAULTS[selectedRamp as ColorRampName] ?? 9;
111+
const defaultClasses = COLOR_RAMP_DEFAULTS[selectedRamp] ?? 9;
102112

103-
setNumberOfShades(defaultClasses.toString());
113+
setNumberOfShades(defaultClasses);
104114
setWarning(null);
105115
}, [selectedRamp]);
106116

@@ -109,8 +119,8 @@ const ColorRampControls: React.FC<IColorRampControlsProps> = ({
109119
return;
110120
}
111121

112-
const minRequired = COLOR_RAMP_DEFAULTS[selectedRamp as ColorRampName];
113-
const shades = parseInt(numberOfShades, 10);
122+
const minRequired = COLOR_RAMP_DEFAULTS[selectedRamp];
123+
const shades = numberOfShades;
114124
const rampLabel = selectedRamp
115125
.split('-')
116126
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
@@ -133,11 +143,12 @@ const ColorRampControls: React.FC<IColorRampControlsProps> = ({
133143
colorRamp = layerParams.symbologyState.colorRamp;
134144
reverseRamp = layerParams.symbologyState.reverse;
135145
}
146+
136147
const defaultRamp = colorRamp ?? 'viridis';
137148
const defaultClasses =
138149
nClasses ?? COLOR_RAMP_DEFAULTS[defaultRamp as ColorRampName] ?? 9;
139150

140-
setNumberOfShades(defaultClasses.toString());
151+
setNumberOfShades(defaultClasses);
141152
setSelectedMode(singleBandMode ?? 'equal interval');
142153
setSelectedRamp(defaultRamp);
143154
setReverseRamp(reverseRamp ?? false);
@@ -235,7 +246,11 @@ const ColorRampControls: React.FC<IColorRampControlsProps> = ({
235246
<Button
236247
className="jp-Dialog-button jp-mod-accept jp-mod-styled"
237248
disabled={
238-
minValue === undefined || maxValue === undefined || !!warning
249+
!isValidNumberOfShades(numberOfShades) ||
250+
!selectedMode ||
251+
minValue === undefined ||
252+
maxValue === undefined ||
253+
!!warning
239254
}
240255
onClick={() => {
241256
if (minValue === undefined || maxValue === undefined) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import { Button } from '@jupyterlab/ui-components';
1515
import React, { useEffect, useRef, useState } from 'react';
1616

1717
import { useColorMapList } from '@/src/dialogs/symbology/colorRampUtils';
18-
import { IColorMap } from '@/src/types';
18+
import { ColorRampName, IColorMap } from '@/src/types';
1919
import ColorRampSelectorEntry from './ColorRampSelectorEntry';
2020

2121
interface IColorRampSelectorProps {
22-
selectedRamp: string;
22+
selectedRamp: ColorRampName;
2323
setSelected: (item: any) => void;
2424
reverse: boolean;
2525
setReverse: React.Dispatch<React.SetStateAction<boolean>>;

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

Lines changed: 17 additions & 8 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;
6+
setNumberOfShades: React.Dispatch<React.SetStateAction<number>>;
7+
selectedMode: ClassificationMode;
8+
setSelectedMode: React.Dispatch<React.SetStateAction<ClassificationMode>>;
9+
modeOptions: ClassificationMode[];
810
}
911
const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
1012
numberOfShades,
@@ -22,7 +24,12 @@ const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
2224
name="class-number-input"
2325
type="number"
2426
value={selectedMode === 'continuous' ? 52 : numberOfShades}
25-
onChange={event => setNumberOfShades(event.target.value)}
27+
onChange={event => {
28+
const value = Number(event.target.value);
29+
if (!isNaN(value) && value > 0) {
30+
setNumberOfShades(value);
31+
}
32+
}}
2633
disabled={selectedMode === 'continuous'}
2734
/>
2835
</div>
@@ -34,10 +41,12 @@ const ModeSelectRow: React.FC<IModeSelectRowProps> = ({
3441
id="mode-select"
3542
className="jp-mod-styled"
3643
value={selectedMode}
37-
onChange={event => setSelectedMode(event.target.value)}
44+
onChange={event =>
45+
setSelectedMode(event.target.value as ClassificationMode)
46+
}
3847
>
3948
{modeOptions.map(mode => (
40-
<option key={mode} value={mode} selected={selectedMode === mode}>
49+
<option key={mode} value={mode}>
4150
{mode}
4251
</option>
4352
))}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +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 { ColorRampName } from '@/src/types';
23+
import { ColorRampName, ClassificationMode } from '@/src/types';
2424

2525
export type InterpolationType = 'discrete' | 'linear' | 'exact';
2626

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

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

4448
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
4549

@@ -305,8 +309,8 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
305309
};
306310

307311
const buildColorInfoFromClassification = async (
308-
selectedMode: string,
309-
numberOfShades: string,
312+
selectedMode: ClassificationMode,
313+
numberOfShades: number,
310314
selectedRamp: ColorRampName,
311315
reverseRamp: boolean,
312316
setIsLoading: (isLoading: boolean) => void,
@@ -327,7 +331,7 @@ const SingleBandPseudoColor: React.FC<ISymbologyDialogProps> = ({
327331

328332
const source = model.getSource(layer?.parameters?.source);
329333
const sourceInfo = source?.parameters?.urls[0];
330-
const nClasses = selectedMode === 'continuous' ? 52 : +numberOfShades;
334+
const nClasses = selectedMode === 'continuous' ? 52 : numberOfShades;
331335

332336
setIsLoading(true);
333337
switch (selectedMode) {

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ import { IVectorLayer } from '@jupytergis/schema';
22
import { ExpressionValue } from 'ol/expr/expression';
33
import React, { useEffect, useRef, useState } from 'react';
44

5-
import ColorRampControls, { ColorRampControlsOptions } from '@/src/dialogs/symbology/components/color_ramp/ColorRampControls';
5+
import ColorRampControls, {
6+
ColorRampControlsOptions,
7+
} from '@/src/dialogs/symbology/components/color_ramp/ColorRampControls';
68
import StopContainer from '@/src/dialogs/symbology/components/color_stops/StopContainer';
79
import {
810
IStopRow,
911
ISymbologyTabbedDialogWithAttributesProps,
1012
} from '@/src/dialogs/symbology/symbologyDialog';
1113
import { Utils, VectorUtils } from '@/src/dialogs/symbology/symbologyUtils';
1214
import ValueSelect from '@/src/dialogs/symbology/vector_layer/components/ValueSelect';
13-
import { ColorRampName, SymbologyTab } from '@/src/types';
15+
import { ColorRampName, ClassificationMode, SymbologyTab } from '@/src/types';
1416

1517
const Categorized: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
1618
model,
@@ -126,8 +128,8 @@ const Categorized: React.FC<ISymbologyTabbedDialogWithAttributesProps> = ({
126128
}, [selectedAttribute, stopRows, colorRampOptions]);
127129

128130
const buildColorInfoFromClassification = (
129-
selectedMode: string,
130-
numberOfShades: string,
131+
selectedMode: ClassificationMode,
132+
numberOfShades: number,
131133
selectedRamp: ColorRampName,
132134
reverseRamp: boolean,
133135
setIsLoading: (isLoading: boolean) => void,

0 commit comments

Comments
 (0)