Skip to content
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
115471f
Refactor getFeature stuff
gjmooney Jan 28, 2025
af263c1
Add toolbar item
gjmooney Jan 27, 2025
a479217
Add temporal boolean
gjmooney Jan 27, 2025
b8bca56
Start adding time slider thing
gjmooney Jan 27, 2025
d29e911
Continue
gjmooney Jan 27, 2025
fbfdda8
New example
gjmooney Jan 28, 2025
7b664f4
wip
gjmooney Jan 28, 2025
03232fe
Add date-fns and examples
gjmooney Jan 28, 2025
afe6f13
wip
gjmooney Jan 28, 2025
548bc9b
Saving
gjmooney Jan 30, 2025
b180058
I think it works
gjmooney Jan 30, 2025
0424132
wip
gjmooney Jan 31, 2025
15e8beb
Still works
gjmooney Jan 31, 2025
9781137
Clean up slider
gjmooney Jan 31, 2025
d4ada57
Add CSS class
gjmooney Jan 31, 2025
b4dad2a
Emit signal on feature select
gjmooney Jan 31, 2025
4b8f658
Examples
gjmooney Jan 31, 2025
3a2963b
Use awareness to hold time boolean
gjmooney Jan 31, 2025
c7f7506
UI tweak
gjmooney Jan 31, 2025
c96d624
UI rework
gjmooney Feb 4, 2025
08890e9
Refactor filters logic
gjmooney Feb 4, 2025
072f27d
Make the icon toggleable
gjmooney Feb 4, 2025
ca26e3d
Refactor adding filter in slider component
gjmooney Feb 4, 2025
632f4c3
Do time filtering in memory
gjmooney Feb 4, 2025
f3dde9c
Save
gjmooney Feb 5, 2025
f2d806c
CSS
gjmooney Feb 5, 2025
4b01226
Clean up
gjmooney Feb 6, 2025
5f9fc47
Fix state check
gjmooney Feb 6, 2025
da91784
Add FPS control
gjmooney Feb 6, 2025
cdbe69b
Update commands
gjmooney Feb 6, 2025
edd983e
yarrr
gjmooney Feb 6, 2025
3f46642
Fix layer selecting
gjmooney Feb 7, 2025
a8256f6
Only display steps that make sense
gjmooney Feb 7, 2025
01bc28b
Enable/Disabel toolbar button based on selection
gjmooney Feb 7, 2025
1819596
Clean up
gjmooney Feb 7, 2025
1e1ca40
Fix CSS for mainview
gjmooney Feb 7, 2025
5557413
Add raster layer check
gjmooney Feb 7, 2025
3e9ee24
Clean up
gjmooney Feb 7, 2025
7075d65
Actually use state
gjmooney Feb 7, 2025
b38fc6b
Clear filter when closing
gjmooney Feb 7, 2025
d833d68
Fix animate in lite
gjmooney Feb 7, 2025
d8c99a4
Add borders
gjmooney Feb 7, 2025
91bea01
Remove status bar border and restore screenshots
gjmooney Feb 10, 2025
ff9d5c4
Remove filter from example
gjmooney Feb 10, 2025
9cf7bb7
Select default feature
gjmooney Feb 10, 2025
67cdc5d
Pass commands to mainview
gjmooney Feb 10, 2025
45c8c51
Close on layer deleteion or type change
gjmooney Feb 10, 2025
a8ec175
Set default step correctly
gjmooney Feb 10, 2025
fede96c
Suggestions
gjmooney Feb 11, 2025
6830760
Heatmap wip
gjmooney Feb 11, 2025
bd8e83a
Remove feature from schema
gjmooney Feb 11, 2025
1d538b6
Enable for heatmap layers
gjmooney Feb 11, 2025
95cf5bc
Close
gjmooney Feb 11, 2025
e392085
Heatmaps work?
gjmooney Feb 12, 2025
685134d
Tweak
gjmooney Feb 12, 2025
7b56775
State restore wip
gjmooney Feb 12, 2025
69b4126
Set filter states in mainview
gjmooney Feb 12, 2025
2723642
Fixed
gjmooney Feb 12, 2025
a3000e2
Clean up
gjmooney Feb 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 35 additions & 92 deletions examples/earthquakes.jGIS
Original file line number Diff line number Diff line change
@@ -1,117 +1,67 @@
{
"layerTree": [
"0959c04f-a841-4fa2-8b44-d262e89e4c9a",
"b116b76f-e040-4908-9098-a6fbea7ca5bc"
"8de7c2c0-6024-4716-b542-031a89fb87f9",
"3e21d680-406f-4099-bd9e-3a4edb9a2c8b"
],
"layers": {
"0959c04f-a841-4fa2-8b44-d262e89e4c9a": {
"name": "OpenStreetMap.Mapnik Layer",
"parameters": {
"source": "a7ed9785-8797-4d6d-a6a9-062ce78ba7ba"
"3e21d680-406f-4099-bd9e-3a4edb9a2c8b": {
"filters": {
"appliedFilters": [],
"logicalOp": "all"
},
"type": "RasterLayer",
"visible": true
},
"b116b76f-e040-4908-9098-a6fbea7ca5bc": {
"name": "earthquakes",
"name": "Custom GeoJSON Layer",
"parameters": {
"color": {
"circle-fill-color": [
"case",
[
"==",
[
"get",
"tsunami"
],
0.0
],
[
125.0,
0.0,
179.0,
1.0
],
[
"==",
[
"get",
"tsunami"
],
1.0
],
[
147.0,
255.0,
0.0,
1.0
],
[
0.0,
0.0,
0.0,
0.0
]
],
"circle-radius": [
"interpolate",
[
"linear"
],
[
"get",
"mag"
],
1.0,
1.0,
2.0,
2.0,
3.0,
3.0,
4.0,
4.0,
5.0,
5.0,
6.0,
6.0
],
"circle-stroke-color": "#3399CC",
"circle-fill-color": "#f66151",
"circle-radius": 5.0,
"circle-stroke-color": "#62a0ea",
"circle-stroke-line-cap": "round",
"circle-stroke-line-join": "round",
"circle-stroke-width": 1.25
},
"opacity": 1.0,
"source": "dc048820-75cd-4b8d-a1fb-91642901cd82",
"source": "348d85fa-3a71-447f-8a64-e283ec47cc7c",
"symbologyState": {
"colorRamp": "cool",
"mode": "",
"nClasses": "",
"renderType": "Categorized",
"value": "tsunami"
"renderType": "Single Symbol"
},
"type": "circle"
},
"type": "VectorLayer",
"visible": true
},
"8de7c2c0-6024-4716-b542-031a89fb87f9": {
"name": "OpenStreetMap.Mapnik Layer",
"parameters": {
"source": "b2ea427a-a51b-43ad-ae72-02cd900736d5"
},
"type": "RasterLayer",
"visible": true
}
},
"metadata": {},
"options": {
"bearing": 0.0,
"extent": [
-14291047.530673811,
-3536164.7121253638,
-9426274.876637986,
9088825.15152122
-14723872.80667293,
-4835119.4874388315,
-1931504.9042952778,
13305887.78837996
],
"latitude": 24.187972965810673,
"longitude": -106.52816608439294,
"latitude": 35.52446437432016,
"longitude": -74.80890180273175,
"pitch": 0.0,
"projection": "EPSG:3857",
"zoom": 3.8783091860507373
"zoom": 2.6670105136699993
},
"sources": {
"a7ed9785-8797-4d6d-a6a9-062ce78ba7ba": {
"348d85fa-3a71-447f-8a64-e283ec47cc7c": {
"name": "Custom GeoJSON Layer Source",
"parameters": {
"path": "../../examples/eq.json"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious to know why the path changed, we may have a bug somewhere around the file selector. This path change makes it fail when I try to load that file in JupyterLite, it should stay:

Suggested change
"path": "../../examples/eq.json"
"path": "eq.json"

},
"type": "GeoJSONSource"
},
"b2ea427a-a51b-43ad-ae72-02cd900736d5": {
"name": "OpenStreetMap.Mapnik",
"parameters": {
"attribution": "(C) OpenStreetMap contributors",
Expand All @@ -122,13 +72,6 @@
"urlParameters": {}
},
"type": "RasterSource"
},
"dc048820-75cd-4b8d-a1fb-91642901cd82": {
"name": "Custom GeoJSON Layer Source",
"parameters": {
"path": "eq.json"
},
"type": "GeoJSONSource"
}
}
}
1 change: 1 addition & 0 deletions packages/base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"ajv": "^8.14.0",
"colormap": "^2.3.2",
"d3-color": "^3.1.0",
"date-fns": "^4.1.0",
"gdal3.js": "^2.8.1",
"geojson-vt": "^4.0.2",
"geotiff": "^2.1.3",
Expand Down
42 changes: 42 additions & 0 deletions packages/base/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,48 @@ export function addCommands(
...icons.get(CommandIDs.identify)
});

commands.addCommand(CommandIDs.temporalController, {
label: trans.__('Temporal Controller'),
isToggled: () => {
return tracker.currentWidget?.model.isTemporalControllerActive || false;
},
isEnabled: () => {
const model = tracker.currentWidget?.model;
if (!model) {
return false;
}

const selectedLayers = model.localState?.selected?.value;

// No selection / too many selections / selection is a source /selection is not a vector layer
if (
!selectedLayers ||
Object.keys(selectedLayers).length !== 1 ||
model.getSource(Object.keys(selectedLayers)[0]) ||
model.getLayer(Object.keys(selectedLayers)[0])?.type !== 'VectorLayer'
) {
if (model.isTemporalControllerActive) {
model.toggleTemporalController();
commands.notifyCommandChanged(CommandIDs.temporalController);
}

return false;
}

return true;
},
execute: () => {
const current = tracker.currentWidget;
if (!current) {
return;
}

current.model.toggleTemporalController();
commands.notifyCommandChanged(CommandIDs.temporalController);
},
...icons.get(CommandIDs.temporalController)
});

/**
* SOURCES and LAYERS creation commands.
*/
Expand Down
4 changes: 3 additions & 1 deletion packages/base/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export namespace CommandIDs {
export const undo = 'jupytergis:undo';
export const symbology = 'jupytergis:symbology';
export const identify = 'jupytergis:identify';
export const temporalController = 'jupytergis:temporalController';

// Layers and sources creation commands
export const openLayerBrowser = 'jupytergis:openLayerBrowser';
Expand Down Expand Up @@ -99,7 +100,8 @@ const iconObject = {
[CommandIDs.newShapefileLayer]: { iconClass: 'fa fa-file' },
[CommandIDs.newGeoTiffEntry]: { iconClass: 'fa fa-image' },
[CommandIDs.symbology]: { iconClass: 'fa fa-brush' },
[CommandIDs.identify]: { iconClass: 'fa fa-info' }
[CommandIDs.identify]: { iconClass: 'fa fa-info' },
[CommandIDs.temporalController]: { iconClass: 'fa fa-clock' }
};

/**
Expand Down
16 changes: 7 additions & 9 deletions packages/base/src/dialogs/symbology/hooks/useGetProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface IUseGetPropertiesProps {
}

interface IUseGetPropertiesResult {
featureProps: Record<string, Set<any>>;
featureProperties: Record<string, Set<any>>;
isLoading: boolean;
error?: Error;
}
Expand All @@ -19,7 +19,7 @@ export const useGetProperties = ({
layerId,
model
}: IUseGetPropertiesProps): IUseGetPropertiesResult => {
const [featureProps, setFeatureProps] = useState<any>({});
const [featureProperties, setFeatureProperties] = useState<any>({});
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | undefined>(undefined);

Expand Down Expand Up @@ -51,17 +51,15 @@ export const useGetProperties = ({
data.features.forEach((feature: GeoJSONFeature1) => {
if (feature.properties) {
Object.entries(feature.properties).forEach(([key, value]) => {
if (typeof value !== 'string') {
if (!(key in result)) {
result[key] = new Set();
}
result[key].add(value);
if (!(key in result)) {
result[key] = new Set();
}
result[key].add(value);
});
}
});

setFeatureProps(result);
setFeatureProperties(result);
setIsLoading(false);
} catch (err) {
setError(err as Error);
Expand All @@ -73,5 +71,5 @@ export const useGetProperties = ({
getProperties();
}, [model, layerId]);

return { featureProps, isLoading, error };
return { featureProperties, isLoading, error };
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IVectorLayer } from '@jupytergis/schema';
import { ReadonlyJSONObject } from '@lumino/coreutils';
import { ExpressionValue } from 'ol/expr/expression';
import React, { useEffect, useRef, useState } from 'react';
import { getNumericFeatures } from '../../../../tools';
import ColorRamp from '../../components/color_ramp/ColorRamp';
import StopContainer from '../../components/color_stops/StopContainer';
import { useGetProperties } from '../../hooks/useGetProperties';
Expand All @@ -25,6 +26,7 @@ const Categorized = ({
const [colorRampOptions, setColorRampOptions] = useState<
ReadonlyJSONObject | undefined
>();
const [features, setFeatures] = useState<Record<string, Set<number>>>({});

if (!layerId) {
return;
Expand All @@ -33,7 +35,7 @@ const Categorized = ({
if (!layer?.parameters) {
return;
}
const { featureProps } = useGetProperties({
const { featureProperties } = useGetProperties({
layerId,
model: model
});
Expand All @@ -55,22 +57,23 @@ const Categorized = ({
}, []);

useEffect(() => {
populateOptions();
}, [featureProps]);
// We only want number values here
const numericFeatures = getNumericFeatures(featureProperties);

useEffect(() => {
selectedValueRef.current = selectedValue;
stopRowsRef.current = stopRows;
colorRampOptionsRef.current = colorRampOptions;
}, [selectedValue, stopRows, colorRampOptions]);
setFeatures(numericFeatures);

const populateOptions = async () => {
const layerParams = layer.parameters as IVectorLayer;
const value =
layerParams.symbologyState?.value ?? Object.keys(featureProps)[0];
layerParams.symbologyState?.value ?? Object.keys(numericFeatures)[0];

setSelectedValue(value);
};
}, [featureProperties]);

useEffect(() => {
selectedValueRef.current = selectedValue;
stopRowsRef.current = stopRows;
colorRampOptionsRef.current = colorRampOptions;
}, [selectedValue, stopRows, colorRampOptions]);

const buildColorInfoFromClassification = (
selectedMode: string,
Expand All @@ -85,7 +88,7 @@ const Categorized = ({
selectedMode: ''
});

const stops = Array.from(featureProps[selectedValue]).sort((a, b) => a - b);
const stops = Array.from(features[selectedValue]).sort((a, b) => a - b);

const valueColorPairs = Utils.getValueColorPairs(
stops,
Expand Down Expand Up @@ -145,7 +148,7 @@ const Categorized = ({
return (
<div className="jp-gis-layer-symbology-container">
<ValueSelect
featureProperties={featureProps}
featureProperties={features}
selectedValue={selectedValue}
setSelectedValue={setSelectedValue}
/>
Expand Down
Loading
Loading