@jupytergis/base 0.2.1 → 0.4.0

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.
Files changed (95) hide show
  1. package/lib/annotations/components/Annotation.js +2 -2
  2. package/lib/annotations/model.d.ts +6 -7
  3. package/lib/annotations/model.js +15 -15
  4. package/lib/commands.d.ts +2 -3
  5. package/lib/commands.js +146 -62
  6. package/lib/constants.d.ts +3 -0
  7. package/lib/constants.js +5 -1
  8. package/lib/dialogs/formdialog.d.ts +5 -0
  9. package/lib/dialogs/formdialog.js +2 -2
  10. package/lib/dialogs/layerBrowserDialog.d.ts +4 -5
  11. package/lib/dialogs/layerBrowserDialog.js +9 -9
  12. package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.js +2 -1
  13. package/lib/dialogs/symbology/hooks/useGetBandInfo.d.ts +26 -0
  14. package/lib/dialogs/symbology/hooks/useGetBandInfo.js +64 -0
  15. package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +1 -1
  16. package/lib/dialogs/symbology/hooks/useGetProperties.js +12 -9
  17. package/lib/dialogs/symbology/symbologyDialog.d.ts +2 -3
  18. package/lib/dialogs/symbology/symbologyDialog.js +10 -9
  19. package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +1 -1
  20. package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +16 -3
  21. package/lib/dialogs/symbology/tiff_layer/components/BandRow.d.ts +16 -3
  22. package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +21 -7
  23. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.d.ts +4 -0
  24. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +85 -0
  25. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.d.ts +1 -20
  26. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +25 -65
  27. package/lib/dialogs/symbology/vector_layer/VectorRendering.d.ts +1 -1
  28. package/lib/dialogs/symbology/vector_layer/VectorRendering.js +18 -13
  29. package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +1 -1
  30. package/lib/dialogs/symbology/vector_layer/types/Categorized.js +30 -19
  31. package/lib/dialogs/symbology/vector_layer/types/Graduated.d.ts +1 -1
  32. package/lib/dialogs/symbology/vector_layer/types/Graduated.js +16 -13
  33. package/lib/dialogs/symbology/vector_layer/types/Heatmap.d.ts +4 -0
  34. package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +77 -0
  35. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.d.ts +1 -1
  36. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +4 -3
  37. package/lib/formbuilder/creationform.d.ts +6 -2
  38. package/lib/formbuilder/creationform.js +6 -6
  39. package/lib/formbuilder/editform.d.ts +2 -2
  40. package/lib/formbuilder/editform.js +14 -9
  41. package/lib/formbuilder/formselectors.js +11 -1
  42. package/lib/formbuilder/objectform/baseform.d.ts +12 -3
  43. package/lib/formbuilder/objectform/baseform.js +39 -0
  44. package/lib/formbuilder/objectform/fileselectorwidget.d.ts +2 -0
  45. package/lib/formbuilder/objectform/fileselectorwidget.js +88 -0
  46. package/lib/formbuilder/objectform/geojsonsource.d.ts +5 -7
  47. package/lib/formbuilder/objectform/geojsonsource.js +8 -24
  48. package/lib/formbuilder/objectform/geotiffsource.d.ts +5 -1
  49. package/lib/formbuilder/objectform/geotiffsource.js +64 -18
  50. package/lib/formbuilder/objectform/heatmapLayerForm.d.ts +11 -0
  51. package/lib/formbuilder/objectform/heatmapLayerForm.js +60 -0
  52. package/lib/formbuilder/objectform/layerform.d.ts +2 -0
  53. package/lib/formbuilder/objectform/layerform.js +6 -0
  54. package/lib/formbuilder/objectform/pathbasedsource.d.ts +19 -0
  55. package/lib/formbuilder/objectform/pathbasedsource.js +98 -0
  56. package/lib/formbuilder/objectform/vectorlayerform.d.ts +0 -2
  57. package/lib/formbuilder/objectform/vectorlayerform.js +0 -59
  58. package/lib/icons.d.ts +1 -0
  59. package/lib/icons.js +5 -0
  60. package/lib/keybindings.json +62 -0
  61. package/lib/mainview/TemporalSlider.d.ts +8 -0
  62. package/lib/mainview/TemporalSlider.js +303 -0
  63. package/lib/mainview/mainView.d.ts +46 -8
  64. package/lib/mainview/mainView.js +431 -144
  65. package/lib/mainview/mainviewmodel.d.ts +4 -0
  66. package/lib/mainview/mainviewmodel.js +4 -0
  67. package/lib/mainview/mainviewwidget.d.ts +0 -2
  68. package/lib/mainview/mainviewwidget.js +0 -2
  69. package/lib/panelview/annotationPanel.js +5 -5
  70. package/lib/panelview/components/filter-panel/Filter.js +8 -24
  71. package/lib/panelview/components/identify-panel/IdentifyPanel.js +1 -1
  72. package/lib/panelview/components/layers.js +2 -2
  73. package/lib/panelview/components/sources.js +1 -1
  74. package/lib/panelview/leftpanel.d.ts +3 -0
  75. package/lib/panelview/leftpanel.js +5 -1
  76. package/lib/panelview/model.js +8 -8
  77. package/lib/panelview/objectproperties.js +10 -10
  78. package/lib/panelview/rightpanel.d.ts +1 -1
  79. package/lib/panelview/rightpanel.js +10 -10
  80. package/lib/statusbar/StatusBar.d.ts +13 -0
  81. package/lib/statusbar/StatusBar.js +52 -0
  82. package/lib/toolbar/widget.d.ts +1 -1
  83. package/lib/toolbar/widget.js +44 -37
  84. package/lib/tools.d.ts +50 -7
  85. package/lib/tools.js +394 -12
  86. package/lib/types.d.ts +2 -0
  87. package/lib/widget.d.ts +29 -5
  88. package/lib/widget.js +41 -7
  89. package/package.json +17 -5
  90. package/style/base.css +11 -0
  91. package/style/icons/logo_mini_qgz.svg +31 -0
  92. package/style/leftPanel.css +8 -0
  93. package/style/statusBar.css +16 -0
  94. package/style/symbologyDialog.css +7 -1
  95. package/style/temporalSlider.css +47 -0
@@ -1,36 +1,35 @@
1
1
  import { Button } from '@jupyterlab/ui-components';
2
2
  import React, { useEffect, useRef, useState } from 'react';
3
- import { GeoTiffClassifications } from '../../classificationModes';
3
+ import { Spinner } from '../../../../mainview/spinner';
4
4
  import { GlobalStateDbManager } from '../../../../store';
5
- import BandRow from '../components/BandRow';
5
+ import { GeoTiffClassifications } from '../../classificationModes';
6
6
  import ColorRamp from '../../components/color_ramp/ColorRamp';
7
7
  import StopRow from '../../components/color_stops/StopRow';
8
+ import useGetBandInfo from '../../hooks/useGetBandInfo';
8
9
  import { Utils } from '../../symbologyUtils';
9
- import { Spinner } from '../../../../mainview/spinner';
10
- import { loadGeoTIFFWithCache } from '../../../../tools';
11
- const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) => {
12
- const functions = ['discrete', 'linear', 'exact'];
13
- const modeOptions = ['continuous', 'equal interval', 'quantile'];
14
- const stopRowsRef = useRef();
15
- const bandRowsRef = useRef([]);
16
- const selectedFunctionRef = useRef();
17
- const colorRampOptionsRef = useRef();
18
- const layerStateRef = useRef();
19
- const selectedBandRef = useRef();
20
- const [layerState, setLayerState] = useState();
21
- const [selectedBand, setSelectedBand] = useState(1);
22
- const [stopRows, setStopRows] = useState([]);
23
- const [bandRows, setBandRows] = useState([]);
24
- const [selectedFunction, setSelectedFunction] = useState('linear');
25
- const [colorRampOptions, setColorRampOptions] = useState();
10
+ import BandRow from '../components/BandRow';
11
+ const SingleBandPseudoColor = ({ model, okSignalPromise, cancel, layerId }) => {
26
12
  if (!layerId) {
27
13
  return;
28
14
  }
29
- const layer = context.model.getLayer(layerId);
15
+ const layer = model.getLayer(layerId);
30
16
  if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
31
17
  return;
32
18
  }
19
+ const functions = ['discrete', 'linear', 'exact'];
20
+ const modeOptions = ['continuous', 'equal interval', 'quantile'];
33
21
  const stateDb = GlobalStateDbManager.getInstance().getStateDb();
22
+ const { bandRows, setBandRows, loading } = useGetBandInfo(model, layer);
23
+ const [layerState, setLayerState] = useState();
24
+ const [selectedBand, setSelectedBand] = useState(1);
25
+ const [stopRows, setStopRows] = useState([]);
26
+ const [selectedFunction, setSelectedFunction] = useState('linear');
27
+ const [colorRampOptions, setColorRampOptions] = useState();
28
+ const stopRowsRef = useRef();
29
+ const bandRowsRef = useRef([]);
30
+ const selectedFunctionRef = useRef();
31
+ const colorRampOptionsRef = useRef();
32
+ const selectedBandRef = useRef();
34
33
  useEffect(() => {
35
34
  populateOptions();
36
35
  okSignalPromise.promise.then(okSignal => {
@@ -42,10 +41,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
42
41
  });
43
42
  };
44
43
  }, []);
45
- useEffect(() => {
46
- layerStateRef.current = layerState;
47
- getBandInfo();
48
- }, [layerState]);
49
44
  useEffect(() => {
50
45
  bandRowsRef.current = bandRows;
51
46
  buildColorInfo();
@@ -55,7 +50,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
55
50
  selectedFunctionRef.current = selectedFunction;
56
51
  colorRampOptionsRef.current = colorRampOptions;
57
52
  selectedBandRef.current = selectedBand;
58
- layerStateRef.current = layerState;
59
53
  }, [stopRows, selectedFunction, colorRampOptions, selectedBand, layerState]);
60
54
  const populateOptions = async () => {
61
55
  var _a, _b, _c, _d;
@@ -67,39 +61,6 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
67
61
  setSelectedBand(band);
68
62
  setSelectedFunction(interpolation);
69
63
  };
70
- const preloadGeoTiffFile = async (sourceInfo) => {
71
- return await loadGeoTIFFWithCache(sourceInfo);
72
- };
73
- const getBandInfo = async () => {
74
- var _a, _b;
75
- const bandsArr = [];
76
- const source = context.model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
77
- const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
78
- if (!(sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url)) {
79
- return;
80
- }
81
- // Preload the file only once
82
- const preloadedFile = await preloadGeoTiffFile(sourceInfo);
83
- const { file, metadata, sourceUrl } = Object.assign({}, preloadedFile);
84
- if (file && metadata && sourceUrl === sourceInfo.url) {
85
- metadata['bands'].forEach((bandData) => {
86
- var _a, _b;
87
- bandsArr.push({
88
- band: bandData.band,
89
- colorInterpretation: bandData.colorInterpretation,
90
- stats: {
91
- minimum: (_a = sourceInfo.min) !== null && _a !== void 0 ? _a : bandData.minimum,
92
- maximum: (_b = sourceInfo.max) !== null && _b !== void 0 ? _b : bandData.maximum,
93
- mean: bandData.mean,
94
- stdDev: bandData.stdDev
95
- },
96
- metadata: bandData.metadata,
97
- histogram: bandData.histogram
98
- });
99
- });
100
- setBandRows(bandsArr);
101
- }
102
- };
103
64
  const buildColorInfo = () => {
104
65
  var _a;
105
66
  // This it to parse a color object on the layer
@@ -159,7 +120,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
159
120
  return;
160
121
  }
161
122
  const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
162
- const source = context.model.getSource(sourceId);
123
+ const source = model.getSource(sourceId);
163
124
  if (!source || !source.parameters) {
164
125
  return;
165
126
  }
@@ -168,7 +129,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
168
129
  sourceInfo.min = bandRow.stats.minimum;
169
130
  sourceInfo.max = bandRow.stats.maximum;
170
131
  source.parameters.urls[0] = sourceInfo;
171
- context.model.sharedModel.updateSource(sourceId, source);
132
+ model.sharedModel.updateSource(sourceId, source);
172
133
  // Update layer
173
134
  if (!layer.parameters) {
174
135
  return;
@@ -232,7 +193,8 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
232
193
  };
233
194
  layer.parameters.symbologyState = symbologyState;
234
195
  layer.parameters.color = colorExpr;
235
- context.model.sharedModel.updateLayer(layerId, layer);
196
+ layer.type = 'WebGlLayer';
197
+ model.sharedModel.updateLayer(layerId, layer);
236
198
  cancel();
237
199
  };
238
200
  const addStopRow = () => {
@@ -259,7 +221,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
259
221
  });
260
222
  let stops = [];
261
223
  const currentBand = bandRows[selectedBand - 1];
262
- const source = context.model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
224
+ const source = model.getSource((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.source);
263
225
  const sourceInfo = (_b = source === null || source === void 0 ? void 0 : source.parameters) === null || _b === void 0 ? void 0 : _b.urls[0];
264
226
  const nClasses = selectedMode === 'continuous' ? 52 : +numberOfShades;
265
227
  setIsLoading(true);
@@ -297,9 +259,7 @@ const SingleBandPseudoColor = ({ context, okSignalPromise, cancel, layerId }) =>
297
259
  return (value * (1 - 0) - min * (1 - 0)) / (max - min);
298
260
  };
299
261
  return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
300
- React.createElement("div", { className: "jp-gis-band-container" }, bandRows.length === 0 ? (React.createElement(Spinner, { loading: bandRows.length === 0 })) : (React.createElement(BandRow
301
- // Band numbers are 1 indexed
302
- , {
262
+ React.createElement("div", { className: "jp-gis-band-container" }, loading ? (React.createElement(Spinner, { loading: loading })) : (React.createElement(BandRow, { label: "Band",
303
263
  // Band numbers are 1 indexed
304
264
  index: selectedBand - 1, bandRow: bandRows[selectedBand - 1], bandRows: bandRows, setSelectedBand: setSelectedBand, setBandRows: setBandRows }))),
305
265
  React.createElement("div", { className: "jp-gis-symbology-row" },
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISymbologyDialogProps } from '../symbologyDialog';
3
- declare const VectorRendering: ({ context, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
3
+ declare const VectorRendering: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
4
4
  export default VectorRendering;
@@ -1,9 +1,10 @@
1
1
  import React, { useEffect, useState } from 'react';
2
+ import Categorized from './types/Categorized';
2
3
  import Graduated from './types/Graduated';
4
+ import Heatmap from './types/Heatmap';
3
5
  import SimpleSymbol from './types/SimpleSymbol';
4
- import Categorized from './types/Categorized';
5
- const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) => {
6
- const [selectedRenderType, setSelectedRenderType] = useState('Single Symbol');
6
+ const VectorRendering = ({ model, state, okSignalPromise, cancel, layerId }) => {
7
+ const [selectedRenderType, setSelectedRenderType] = useState('');
7
8
  const [componentToRender, setComponentToRender] = useState(null);
8
9
  const [renderTypeOptions, setRenderTypeOptions] = useState([
9
10
  'Single Symbol'
@@ -12,32 +13,36 @@ const VectorRendering = ({ context, state, okSignalPromise, cancel, layerId }) =
12
13
  if (!layerId) {
13
14
  return;
14
15
  }
15
- const layer = context.model.getLayer(layerId);
16
+ const layer = model.getLayer(layerId);
16
17
  if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
17
18
  return;
18
19
  }
19
20
  useEffect(() => {
20
21
  var _a, _b;
21
- const renderType = (_b = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) === null || _b === void 0 ? void 0 : _b.renderType;
22
- setSelectedRenderType(renderType !== null && renderType !== void 0 ? renderType : 'Single Symbol');
23
- if (layer.type === 'VectorLayer') {
24
- const options = ['Single Symbol', 'Graduated', 'Categorized'];
25
- setRenderTypeOptions(options);
22
+ let renderType = (_b = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) === null || _b === void 0 ? void 0 : _b.renderType;
23
+ if (!renderType) {
24
+ renderType = layer.type === 'HeatmapLayer' ? 'Heatmap' : 'Single Symbol';
26
25
  }
26
+ setSelectedRenderType(renderType);
27
+ const options = ['Single Symbol', 'Graduated', 'Categorized', 'Heatmap'];
28
+ setRenderTypeOptions(options);
27
29
  }, []);
28
30
  useEffect(() => {
29
31
  switch (selectedRenderType) {
30
32
  case 'Single Symbol':
31
- RenderComponent = (React.createElement(SimpleSymbol, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
33
+ RenderComponent = (React.createElement(SimpleSymbol, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
32
34
  break;
33
35
  case 'Graduated':
34
- RenderComponent = (React.createElement(Graduated, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
36
+ RenderComponent = (React.createElement(Graduated, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
35
37
  break;
36
38
  case 'Categorized':
37
- RenderComponent = (React.createElement(Categorized, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
39
+ RenderComponent = (React.createElement(Categorized, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
40
+ break;
41
+ case 'Heatmap':
42
+ RenderComponent = (React.createElement(Heatmap, { model: model, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: layerId }));
38
43
  break;
39
44
  default:
40
- RenderComponent = React.createElement("div", null, "Render Type Not Implemented (yet)");
45
+ RenderComponent = React.createElement("div", null, "Select a render type");
41
46
  }
42
47
  setComponentToRender(RenderComponent);
43
48
  }, [selectedRenderType]);
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISymbologyDialogProps } from '../../symbologyDialog';
3
- declare const Categorized: ({ context, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
3
+ declare const Categorized: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
4
4
  export default Categorized;
@@ -1,26 +1,28 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import ValueSelect from '../components/ValueSelect';
3
- import { useGetProperties } from '../../hooks/useGetProperties';
2
+ import { getNumericFeatureAttributes } from '../../../../tools';
3
+ import ColorRamp from '../../components/color_ramp/ColorRamp';
4
4
  import StopContainer from '../../components/color_stops/StopContainer';
5
+ import { useGetProperties } from '../../hooks/useGetProperties';
5
6
  import { Utils, VectorUtils } from '../../symbologyUtils';
6
- import ColorRamp from '../../components/color_ramp/ColorRamp';
7
- const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
7
+ import ValueSelect from '../components/ValueSelect';
8
+ const Categorized = ({ model, state, okSignalPromise, cancel, layerId }) => {
8
9
  const selectedValueRef = useRef();
9
10
  const stopRowsRef = useRef();
10
11
  const colorRampOptionsRef = useRef();
11
12
  const [selectedValue, setSelectedValue] = useState('');
12
13
  const [stopRows, setStopRows] = useState([]);
13
14
  const [colorRampOptions, setColorRampOptions] = useState();
15
+ const [features, setFeatures] = useState({});
14
16
  if (!layerId) {
15
17
  return;
16
18
  }
17
- const layer = context.model.getLayer(layerId);
19
+ const layer = model.getLayer(layerId);
18
20
  if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
19
21
  return;
20
22
  }
21
- const { featureProps } = useGetProperties({
23
+ const { featureProperties } = useGetProperties({
22
24
  layerId,
23
- model: context.model
25
+ model: model
24
26
  });
25
27
  useEffect(() => {
26
28
  const valueColorPairs = VectorUtils.buildColorInfo(layer);
@@ -35,19 +37,19 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
35
37
  };
36
38
  }, []);
37
39
  useEffect(() => {
38
- populateOptions();
39
- }, [featureProps]);
40
+ var _a, _b;
41
+ // We only want number values here
42
+ const numericFeatures = getNumericFeatureAttributes(featureProperties);
43
+ setFeatures(numericFeatures);
44
+ const layerParams = layer.parameters;
45
+ const value = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(numericFeatures)[0];
46
+ setSelectedValue(value);
47
+ }, [featureProperties]);
40
48
  useEffect(() => {
41
49
  selectedValueRef.current = selectedValue;
42
50
  stopRowsRef.current = stopRows;
43
51
  colorRampOptionsRef.current = colorRampOptions;
44
52
  }, [selectedValue, stopRows, colorRampOptions]);
45
- const populateOptions = async () => {
46
- var _a, _b;
47
- const layerParams = layer.parameters;
48
- const value = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : Object.keys(featureProps)[0];
49
- setSelectedValue(value);
50
- };
51
53
  const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp, setIsLoading) => {
52
54
  setColorRampOptions({
53
55
  selectedFunction: '',
@@ -55,7 +57,7 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
55
57
  numberOfShades: '',
56
58
  selectedMode: ''
57
59
  });
58
- const stops = Array.from(featureProps[selectedValue]).sort((a, b) => a - b);
60
+ const stops = Array.from(features[selectedValue]).sort((a, b) => a - b);
59
61
  const valueColorPairs = Utils.getValueColorPairs(stops, selectedRamp, stops.length);
60
62
  setStopRows(valueColorPairs);
61
63
  };
@@ -73,7 +75,15 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
73
75
  // fallback value
74
76
  colorExpr.push([0, 0, 0, 0.0]);
75
77
  const newStyle = Object.assign({}, layer.parameters.color);
76
- newStyle['circle-fill-color'] = colorExpr;
78
+ if (layer.parameters.type === 'fill') {
79
+ newStyle['fill-color'] = colorExpr;
80
+ }
81
+ if (layer.parameters.type === 'line') {
82
+ newStyle['stroke-color'] = colorExpr;
83
+ }
84
+ if (layer.parameters.type === 'circle') {
85
+ newStyle['circle-fill-color'] = colorExpr;
86
+ }
77
87
  const symbologyState = {
78
88
  renderType: 'Categorized',
79
89
  value: selectedValueRef.current,
@@ -83,11 +93,12 @@ const Categorized = ({ context, state, okSignalPromise, cancel, layerId }) => {
83
93
  };
84
94
  layer.parameters.symbologyState = symbologyState;
85
95
  layer.parameters.color = newStyle;
86
- context.model.sharedModel.updateLayer(layerId, layer);
96
+ layer.type = 'VectorLayer';
97
+ model.sharedModel.updateLayer(layerId, layer);
87
98
  cancel();
88
99
  };
89
100
  return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
90
- React.createElement(ValueSelect, { featureProperties: featureProps, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
101
+ React.createElement(ValueSelect, { featureProperties: features, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
91
102
  React.createElement(ColorRamp, { layerParams: layer.parameters, modeOptions: [], classifyFunc: buildColorInfoFromClassification, showModeRow: false }),
92
103
  React.createElement(StopContainer, { selectedMethod: '', stopRows: stopRows, setStopRows: setStopRows })));
93
104
  };
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISymbologyDialogProps } from '../../symbologyDialog';
3
- declare const Graduated: ({ context, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
3
+ declare const Graduated: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
4
4
  export default Graduated;
@@ -1,11 +1,12 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
+ import { getNumericFeatureAttributes } from '../../../../tools';
2
3
  import { VectorClassifications } from '../../classificationModes';
3
4
  import ColorRamp from '../../components/color_ramp/ColorRamp';
4
- import ValueSelect from '../components/ValueSelect';
5
5
  import StopContainer from '../../components/color_stops/StopContainer';
6
6
  import { useGetProperties } from '../../hooks/useGetProperties';
7
7
  import { Utils, VectorUtils } from '../../symbologyUtils';
8
- const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
8
+ import ValueSelect from '../components/ValueSelect';
9
+ const Graduated = ({ model, state, okSignalPromise, cancel, layerId }) => {
9
10
  const modeOptions = [
10
11
  'quantile',
11
12
  'equal interval',
@@ -21,17 +22,18 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
21
22
  const [selectedMethod, setSelectedMethod] = useState('color');
22
23
  const [stopRows, setStopRows] = useState([]);
23
24
  const [methodOptions, setMethodOptions] = useState(['color']);
25
+ const [features, setFeatures] = useState({});
24
26
  const [colorRampOptions, setColorRampOptions] = useState();
25
27
  if (!layerId) {
26
28
  return;
27
29
  }
28
- const layer = context.model.getLayer(layerId);
30
+ const layer = model.getLayer(layerId);
29
31
  if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
30
32
  return;
31
33
  }
32
- const { featureProps } = useGetProperties({
34
+ const { featureProperties } = useGetProperties({
33
35
  layerId,
34
- model: context.model
36
+ model: model
35
37
  });
36
38
  useEffect(() => {
37
39
  var _a, _b;
@@ -61,21 +63,21 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
61
63
  colorRampOptionsRef.current = colorRampOptions;
62
64
  }, [selectedValue, selectedMethod, stopRows, colorRampOptions]);
63
65
  useEffect(() => {
64
- populateOptions();
65
- }, [featureProps]);
66
- const populateOptions = async () => {
67
66
  var _a, _b, _c, _d, _e;
68
67
  // Set up method options
69
68
  if (((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.type) === 'circle') {
70
69
  const options = ['color', 'radius'];
71
70
  setMethodOptions(options);
72
71
  }
72
+ // We only want number values here
73
+ const numericFeatures = getNumericFeatureAttributes(featureProperties);
74
+ setFeatures(numericFeatures);
73
75
  const layerParams = layer.parameters;
74
- const value = (_c = (_b = layerParams.symbologyState) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : Object.keys(featureProps)[0];
76
+ const value = (_c = (_b = layerParams.symbologyState) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : Object.keys(numericFeatures)[0];
75
77
  const method = (_e = (_d = layerParams.symbologyState) === null || _d === void 0 ? void 0 : _d.method) !== null && _e !== void 0 ? _e : 'color';
76
78
  setSelectedValue(value);
77
79
  setSelectedMethod(method);
78
- };
80
+ }, [featureProperties]);
79
81
  const handleOk = () => {
80
82
  var _a, _b, _c, _d;
81
83
  if (!layer.parameters) {
@@ -116,7 +118,8 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
116
118
  };
117
119
  layer.parameters.symbologyState = symbologyState;
118
120
  layer.parameters.color = newStyle;
119
- context.model.sharedModel.updateLayer(layerId, layer);
121
+ layer.type = 'VectorLayer';
122
+ model.sharedModel.updateLayer(layerId, layer);
120
123
  cancel();
121
124
  };
122
125
  const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp) => {
@@ -126,7 +129,7 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
126
129
  selectedMode
127
130
  });
128
131
  let stops;
129
- const values = Array.from(featureProps[selectedValue]);
132
+ const values = Array.from(features[selectedValue]);
130
133
  switch (selectedMode) {
131
134
  case 'quantile':
132
135
  stops = VectorClassifications.calculateQuantileBreaks(values, +numberOfShades);
@@ -159,7 +162,7 @@ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
159
162
  setStopRows(stopOutputPairs);
160
163
  };
161
164
  return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
162
- React.createElement(ValueSelect, { featureProperties: featureProps, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
165
+ React.createElement(ValueSelect, { featureProperties: features, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
163
166
  React.createElement("div", { className: "jp-gis-symbology-row" },
164
167
  React.createElement("label", { htmlFor: 'vector-method-select' }, "Method:"),
165
168
  React.createElement("select", { name: 'vector-method-select', onChange: event => setSelectedMethod(event.target.value), className: "jp-mod-styled" }, methodOptions.map((method, index) => (React.createElement("option", { key: index, value: method, selected: method === selectedMethod, className: "jp-mod-styled" }, method))))),
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { ISymbologyDialogProps } from '../../symbologyDialog';
3
+ declare const Heatmap: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
4
+ export default Heatmap;
@@ -0,0 +1,77 @@
1
+ import colormap from 'colormap';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import CanvasSelectComponent from '../../components/color_ramp/CanvasSelectComponent';
4
+ const Heatmap = ({ model, state, okSignalPromise, cancel, layerId }) => {
5
+ if (!layerId) {
6
+ return;
7
+ }
8
+ const layer = model.getLayer(layerId);
9
+ if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
10
+ return;
11
+ }
12
+ const [selectedRamp, setSelectedRamp] = useState('');
13
+ const [heatmapOptions, setHetamapOptions] = useState({
14
+ radius: 8,
15
+ blur: 15
16
+ });
17
+ const selectedRampRef = useRef('cool');
18
+ const heatmapOptionsRef = useRef({
19
+ radius: 8,
20
+ blur: 15
21
+ });
22
+ useEffect(() => {
23
+ populateOptions();
24
+ okSignalPromise.promise.then(okSignal => {
25
+ okSignal.connect(handleOk, this);
26
+ });
27
+ return () => {
28
+ okSignalPromise.promise.then(okSignal => {
29
+ okSignal.disconnect(handleOk, this);
30
+ });
31
+ };
32
+ }, []);
33
+ useEffect(() => {
34
+ selectedRampRef.current = selectedRamp;
35
+ heatmapOptionsRef.current = heatmapOptions;
36
+ }, [selectedRamp, heatmapOptions]);
37
+ const populateOptions = async () => {
38
+ var _a;
39
+ let colorRamp;
40
+ if ((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) {
41
+ colorRamp = layer.parameters.symbologyState.colorRamp;
42
+ }
43
+ setSelectedRamp(colorRamp ? colorRamp : 'cool');
44
+ };
45
+ const handleOk = () => {
46
+ if (!layer.parameters) {
47
+ return;
48
+ }
49
+ const colorMap = colormap({
50
+ colormap: selectedRampRef.current,
51
+ nshades: 9,
52
+ format: 'hex'
53
+ });
54
+ const symbologyState = {
55
+ renderType: 'Heatmap',
56
+ colorRamp: selectedRampRef.current
57
+ };
58
+ layer.parameters.symbologyState = symbologyState;
59
+ layer.parameters.color = colorMap;
60
+ layer.parameters.blur = heatmapOptionsRef.current.blur;
61
+ layer.parameters.radius = heatmapOptionsRef.current.radius;
62
+ layer.type = 'HeatmapLayer';
63
+ model.sharedModel.updateLayer(layerId, layer);
64
+ cancel();
65
+ };
66
+ return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
67
+ React.createElement("div", { className: "jp-gis-symbology-row jp-gis-heatmap" },
68
+ React.createElement("label", { htmlFor: "color-ramp-select" }, "Color Ramp:"),
69
+ React.createElement(CanvasSelectComponent, { selectedRamp: selectedRamp, setSelected: setSelectedRamp })),
70
+ React.createElement("div", { className: "jp-gis-symbology-row" },
71
+ React.createElement("label", { htmlFor: 'vector-value-select' }, "Radius:"),
72
+ React.createElement("input", { type: "number", value: heatmapOptions.radius, className: "jp-mod-styled", onChange: event => setHetamapOptions(prevState => (Object.assign(Object.assign({}, prevState), { radius: +event.target.value }))) })),
73
+ React.createElement("div", { className: "jp-gis-symbology-row" },
74
+ React.createElement("label", { htmlFor: 'vector-value-select' }, "Blur:"),
75
+ React.createElement("input", { type: "number", value: heatmapOptions.blur, className: "jp-mod-styled", onChange: event => setHetamapOptions(prevState => (Object.assign(Object.assign({}, prevState), { blur: +event.target.value }))) }))));
76
+ };
77
+ export default Heatmap;
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISymbologyDialogProps } from '../../symbologyDialog';
3
- declare const SimpleSymbol: ({ context, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
3
+ declare const SimpleSymbol: ({ model, state, okSignalPromise, cancel, layerId }: ISymbologyDialogProps) => React.JSX.Element | undefined;
4
4
  export default SimpleSymbol;
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { parseColor } from '../../../../tools';
3
- const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
3
+ const SimpleSymbol = ({ model, state, okSignalPromise, cancel, layerId }) => {
4
4
  const styleRef = useRef();
5
5
  const [useCircleStuff, setUseCircleStuff] = useState(false);
6
6
  const [style, setStyle] = useState({
@@ -16,7 +16,7 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
16
16
  if (!layerId) {
17
17
  return;
18
18
  }
19
- const layer = context.model.getLayer(layerId);
19
+ const layer = model.getLayer(layerId);
20
20
  if (!layer) {
21
21
  return;
22
22
  }
@@ -75,7 +75,8 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
75
75
  };
76
76
  layer.parameters.symbologyState = symbologyState;
77
77
  layer.parameters.color = styleExpr;
78
- context.model.sharedModel.updateLayer(layerId, layer);
78
+ layer.type = 'VectorLayer';
79
+ model.sharedModel.updateLayer(layerId, layer);
79
80
  cancel();
80
81
  };
81
82
  return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
@@ -1,4 +1,3 @@
1
- import { DocumentRegistry } from '@jupyterlab/docregistry';
2
1
  import { IDict, IJGISFormSchemaRegistry, IJupyterGISModel, LayerType, SourceType } from '@jupytergis/schema';
3
2
  import { Dialog } from '@jupyterlab/apputils';
4
3
  import { Signal } from '@lumino/signaling';
@@ -37,12 +36,17 @@ export interface ICreationFormProps {
37
36
  */
38
37
  cancel?: () => void;
39
38
  formSchemaRegistry: IJGISFormSchemaRegistry;
40
- context: DocumentRegistry.IContext<IJupyterGISModel>;
39
+ model: IJupyterGISModel;
41
40
  /**
42
41
  * A signal emitting when the form changed, with a boolean whether there are some
43
42
  * extra errors or not.
44
43
  */
45
44
  formErrorSignal?: Signal<Dialog<any>, boolean>;
45
+ /**
46
+ * Configuration options for the dialog, including settings for layer data, source data,
47
+ * and other form-related parameters.
48
+ */
49
+ dialogOptions?: any;
46
50
  }
47
51
  /**
48
52
  * Form for creating a source, a layer or both at the same time
@@ -21,8 +21,8 @@ export class CreationForm extends React.Component {
21
21
  constructor(props) {
22
22
  super(props);
23
23
  this.sourceFormChangedSignal = new Signal(this);
24
- this.filePath = props.context.path;
25
- this.jGISModel = props.context.model;
24
+ this.filePath = props.model.filePath;
25
+ this.jGISModel = props.model;
26
26
  }
27
27
  render() {
28
28
  var _a;
@@ -105,13 +105,13 @@ export class CreationForm extends React.Component {
105
105
  return (React.createElement("div", null,
106
106
  this.props.createSource && (React.createElement("div", null,
107
107
  React.createElement("h3", null, "Source Properties"),
108
- React.createElement(SourceForm, { formContext: "create", model: this.jGISModel, filePath: `${this.filePath}::panel`, schema: sourceSchema, sourceData: this.props.sourceData, syncData: (properties) => {
108
+ React.createElement(SourceForm, { formContext: "create", model: this.jGISModel, filePath: this.filePath, schema: sourceSchema, sourceData: this.props.sourceData, syncData: (properties) => {
109
109
  sourceCreationPromise === null || sourceCreationPromise === void 0 ? void 0 : sourceCreationPromise.resolve(properties);
110
- }, ok: this.props.ok, cancel: this.props.cancel, formChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal }))),
110
+ }, ok: this.props.ok, cancel: this.props.cancel, formChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal, dialogOptions: this.props.dialogOptions, sourceType: this.props.sourceType }))),
111
111
  this.props.createLayer && (React.createElement("div", null,
112
112
  React.createElement("h3", null, "Layer Properties"),
113
- React.createElement(LayerForm, { formContext: "create", sourceType: this.props.sourceType, model: this.jGISModel, filePath: `${this.filePath}::panel`, schema: layerSchema, sourceData: layerData, syncData: (properties) => {
113
+ React.createElement(LayerForm, { formContext: "create", sourceType: this.props.sourceType, model: this.jGISModel, filePath: this.filePath, schema: layerSchema, sourceData: layerData, syncData: (properties) => {
114
114
  layerCreationPromise === null || layerCreationPromise === void 0 ? void 0 : layerCreationPromise.resolve(properties);
115
- }, ok: this.props.ok, cancel: this.props.cancel, sourceFormChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal })))));
115
+ }, ok: this.props.ok, cancel: this.props.cancel, sourceFormChangedSignal: this.sourceFormChangedSignal, formErrorSignal: this.props.formErrorSignal, dialogOptions: this.props.dialogOptions })))));
116
116
  }
117
117
  }
@@ -1,4 +1,3 @@
1
- import { DocumentRegistry } from '@jupyterlab/docregistry';
2
1
  import { IJGISFormSchemaRegistry, IJupyterGISModel } from '@jupytergis/schema';
3
2
  import * as React from 'react';
4
3
  export interface IEditFormProps {
@@ -11,7 +10,7 @@ export interface IEditFormProps {
11
10
  */
12
11
  source: string | undefined;
13
12
  formSchemaRegistry: IJGISFormSchemaRegistry;
14
- context: DocumentRegistry.IContext<IJupyterGISModel>;
13
+ model: IJupyterGISModel;
15
14
  }
16
15
  /**
17
16
  * Form for editing a source, a layer or both at the same time
@@ -21,4 +20,5 @@ export declare class EditForm extends React.Component<IEditFormProps, any> {
21
20
  [key: string]: any;
22
21
  }): Promise<void>;
23
22
  render(): React.JSX.Element | undefined;
23
+ private sourceFormChangedSignal;
24
24
  }