@jupytergis/base 0.1.1

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 (108) hide show
  1. package/lib/commands.d.ts +11 -0
  2. package/lib/commands.js +809 -0
  3. package/lib/console/consoleview.d.ts +24 -0
  4. package/lib/console/consoleview.js +55 -0
  5. package/lib/console/index.d.ts +1 -0
  6. package/lib/console/index.js +1 -0
  7. package/lib/constants.d.ts +57 -0
  8. package/lib/constants.js +89 -0
  9. package/lib/dialogs/components/symbology/BandRendering.d.ts +4 -0
  10. package/lib/dialogs/components/symbology/BandRendering.js +29 -0
  11. package/lib/dialogs/components/symbology/BandRow.d.ts +10 -0
  12. package/lib/dialogs/components/symbology/BandRow.js +43 -0
  13. package/lib/dialogs/components/symbology/SingleBandPseudoColor.d.ts +20 -0
  14. package/lib/dialogs/components/symbology/SingleBandPseudoColor.js +281 -0
  15. package/lib/dialogs/components/symbology/StopRow.d.ts +11 -0
  16. package/lib/dialogs/components/symbology/StopRow.js +58 -0
  17. package/lib/dialogs/formdialog.d.ts +31 -0
  18. package/lib/dialogs/formdialog.js +68 -0
  19. package/lib/dialogs/layerBrowserDialog.d.ts +25 -0
  20. package/lib/dialogs/layerBrowserDialog.js +141 -0
  21. package/lib/dialogs/symbologyDialog.d.ts +23 -0
  22. package/lib/dialogs/symbologyDialog.js +68 -0
  23. package/lib/dialogs/terrainDialog.d.ts +21 -0
  24. package/lib/dialogs/terrainDialog.js +60 -0
  25. package/lib/formbuilder/creationform.d.ts +56 -0
  26. package/lib/formbuilder/creationform.js +117 -0
  27. package/lib/formbuilder/editform.d.ts +24 -0
  28. package/lib/formbuilder/editform.js +60 -0
  29. package/lib/formbuilder/formselectors.d.ts +5 -0
  30. package/lib/formbuilder/formselectors.js +38 -0
  31. package/lib/formbuilder/index.d.ts +6 -0
  32. package/lib/formbuilder/index.js +6 -0
  33. package/lib/formbuilder/objectform/baseform.d.ts +79 -0
  34. package/lib/formbuilder/objectform/baseform.js +167 -0
  35. package/lib/formbuilder/objectform/geojsonsource.d.ts +19 -0
  36. package/lib/formbuilder/objectform/geojsonsource.js +80 -0
  37. package/lib/formbuilder/objectform/hillshadeLayerForm.d.ts +8 -0
  38. package/lib/formbuilder/objectform/hillshadeLayerForm.js +12 -0
  39. package/lib/formbuilder/objectform/layerform.d.ts +19 -0
  40. package/lib/formbuilder/objectform/layerform.js +17 -0
  41. package/lib/formbuilder/objectform/tilesourceform.d.ts +7 -0
  42. package/lib/formbuilder/objectform/tilesourceform.js +60 -0
  43. package/lib/formbuilder/objectform/vectorlayerform.d.ts +15 -0
  44. package/lib/formbuilder/objectform/vectorlayerform.js +88 -0
  45. package/lib/formbuilder/objectform/webGlLayerForm.d.ts +8 -0
  46. package/lib/formbuilder/objectform/webGlLayerForm.js +10 -0
  47. package/lib/icons.d.ts +6 -0
  48. package/lib/icons.js +31 -0
  49. package/lib/index.d.ts +10 -0
  50. package/lib/index.js +10 -0
  51. package/lib/mainview/index.d.ts +3 -0
  52. package/lib/mainview/index.js +3 -0
  53. package/lib/mainview/mainView.d.ts +113 -0
  54. package/lib/mainview/mainView.js +743 -0
  55. package/lib/mainview/mainviewmodel.d.ts +24 -0
  56. package/lib/mainview/mainviewmodel.js +34 -0
  57. package/lib/mainview/mainviewwidget.d.ts +14 -0
  58. package/lib/mainview/mainviewwidget.js +18 -0
  59. package/lib/mainview/spinner.d.ts +6 -0
  60. package/lib/mainview/spinner.js +5 -0
  61. package/lib/panelview/components/filter-panel/Filter.d.ts +19 -0
  62. package/lib/panelview/components/filter-panel/Filter.js +223 -0
  63. package/lib/panelview/components/filter-panel/FilterRow.d.ts +9 -0
  64. package/lib/panelview/components/filter-panel/FilterRow.js +61 -0
  65. package/lib/panelview/components/layers.d.ts +13 -0
  66. package/lib/panelview/components/layers.js +275 -0
  67. package/lib/panelview/components/sources.d.ts +10 -0
  68. package/lib/panelview/components/sources.js +147 -0
  69. package/lib/panelview/header.d.ts +11 -0
  70. package/lib/panelview/header.js +20 -0
  71. package/lib/panelview/index.d.ts +5 -0
  72. package/lib/panelview/index.js +5 -0
  73. package/lib/panelview/leftpanel.d.ts +51 -0
  74. package/lib/panelview/leftpanel.js +125 -0
  75. package/lib/panelview/model.d.ts +19 -0
  76. package/lib/panelview/model.js +30 -0
  77. package/lib/panelview/objectproperties.d.ts +17 -0
  78. package/lib/panelview/objectproperties.js +92 -0
  79. package/lib/panelview/rightpanel.d.ts +19 -0
  80. package/lib/panelview/rightpanel.js +45 -0
  81. package/lib/toolbar/index.d.ts +2 -0
  82. package/lib/toolbar/index.js +2 -0
  83. package/lib/toolbar/usertoolbaritem.d.ts +19 -0
  84. package/lib/toolbar/usertoolbaritem.js +57 -0
  85. package/lib/toolbar/widget.d.ts +22 -0
  86. package/lib/toolbar/widget.js +104 -0
  87. package/lib/tools.d.ts +25 -0
  88. package/lib/tools.js +215 -0
  89. package/lib/types.d.ts +11 -0
  90. package/lib/types.js +1 -0
  91. package/lib/widget.d.ts +49 -0
  92. package/lib/widget.js +144 -0
  93. package/package.json +95 -0
  94. package/style/base.css +55 -0
  95. package/style/colorExpression.css +36 -0
  96. package/style/dialog.css +8 -0
  97. package/style/filterPanel.css +70 -0
  98. package/style/icons/geojson.svg +12 -0
  99. package/style/icons/mound.svg +9 -0
  100. package/style/icons/nonvisibility.svg +8 -0
  101. package/style/icons/raster.svg +5 -0
  102. package/style/icons/visibility.svg +7 -0
  103. package/style/index.css +6 -0
  104. package/style/index.js +6 -0
  105. package/style/layerBrowser.css +256 -0
  106. package/style/leftPanel.css +150 -0
  107. package/style/symbologyDialog.css +86 -0
  108. package/style/terrainDialog.css +14 -0
@@ -0,0 +1,58 @@
1
+ import { faTrash } from '@fortawesome/free-solid-svg-icons';
2
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import { Button } from '@jupyterlab/ui-components';
4
+ import React from 'react';
5
+ const StopRow = ({ index, value, outputValue, stopRows, setStopRows, deleteRow }) => {
6
+ const rgbArrToHex = (rgbArr) => {
7
+ const hex = rgbArr
8
+ .slice(0, -1) // Color input doesn't support hex alpha values so cut that out
9
+ .map((val) => {
10
+ return val.toString(16).padStart(2, '0');
11
+ })
12
+ .join('');
13
+ return '#' + hex;
14
+ };
15
+ const hexToRgb = (hex) => {
16
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
17
+ if (!result) {
18
+ console.warn('Unable to parse hex value, defaulting to black');
19
+ return [parseInt('0', 16), parseInt('0', 16), parseInt('0', 16)];
20
+ }
21
+ const rgbValues = [
22
+ parseInt(result[1], 16),
23
+ parseInt(result[2], 16),
24
+ parseInt(result[3], 16),
25
+ 1 // TODO: Make alpha customizable?
26
+ ];
27
+ return rgbValues;
28
+ };
29
+ const handleValueChange = (event) => {
30
+ const newRows = [...stopRows];
31
+ newRows[index].value = +event.target.value;
32
+ setStopRows(newRows);
33
+ };
34
+ const handleBlur = () => {
35
+ const newRows = [...stopRows];
36
+ newRows.sort((a, b) => {
37
+ if (a.value < b.value) {
38
+ return -1;
39
+ }
40
+ if (a.value > b.value) {
41
+ return 1;
42
+ }
43
+ return 0;
44
+ });
45
+ setStopRows(newRows);
46
+ };
47
+ const handleColorChange = (event) => {
48
+ const newRows = [...stopRows];
49
+ newRows[index].color = hexToRgb(event.target.value);
50
+ setStopRows(newRows);
51
+ };
52
+ return (React.createElement("div", { className: "jp-gis-color-row" },
53
+ React.createElement("input", { id: `jp-gis-color-value-${index}`, type: "number", value: value, onChange: handleValueChange, onBlur: handleBlur, className: "jp-mod-styled" }),
54
+ React.createElement("input", { id: `jp-gis-color-color-${index}`, value: rgbArrToHex(outputValue), type: "color", onChange: handleColorChange, className: "jp-mod-styled" }),
55
+ React.createElement(Button, { id: `jp-gis-remove-color-${index}`, className: "jp-Button jp-gis-filter-icon" },
56
+ React.createElement(FontAwesomeIcon, { icon: faTrash, onClick: deleteRow }))));
57
+ };
58
+ export default StopRow;
@@ -0,0 +1,31 @@
1
+ import { IDict } from '@jupytergis/schema';
2
+ import { Dialog } from '@jupyterlab/apputils';
3
+ import * as React from 'react';
4
+ import { ICreationFormProps } from '../formbuilder';
5
+ import { Signal } from '@lumino/signaling';
6
+ import { PromiseDelegate } from '@lumino/coreutils';
7
+ export interface ICreationFormWrapperProps extends ICreationFormProps {
8
+ /**
9
+ * A promise resolving when the dialog is ready.
10
+ * Return a signal emitting when OK button is pressed.
11
+ */
12
+ okSignalPromise: PromiseDelegate<Signal<Dialog<any>, number>>;
13
+ /**
14
+ * A promise resolving when the dialog is ready.
15
+ * Return a signal emitting when the form changed, with a boolean whether there are
16
+ * some extra errors or not.
17
+ */
18
+ formErrorSignalPromise?: PromiseDelegate<Signal<Dialog<any>, boolean>>;
19
+ }
20
+ export interface ICreationFormDialogOptions extends ICreationFormProps {
21
+ title: string;
22
+ }
23
+ export declare const CreationFormWrapper: (props: ICreationFormWrapperProps) => false | React.JSX.Element;
24
+ /**
25
+ * Form for creating a source, a layer or both at the same time
26
+ */
27
+ export declare class CreationFormDialog extends Dialog<IDict> {
28
+ constructor(options: ICreationFormDialogOptions);
29
+ resolve(index?: number): void;
30
+ private okSignal;
31
+ }
@@ -0,0 +1,68 @@
1
+ import { Dialog } from '@jupyterlab/apputils';
2
+ import * as React from 'react';
3
+ import { CreationForm } from '../formbuilder';
4
+ import { Signal } from '@lumino/signaling';
5
+ import { PromiseDelegate } from '@lumino/coreutils';
6
+ export const CreationFormWrapper = (props) => {
7
+ var _a;
8
+ const [ready, setReady] = React.useState(false);
9
+ const okSignal = React.useRef();
10
+ const formErrorSignal = React.useRef();
11
+ Promise.all([
12
+ props.okSignalPromise.promise,
13
+ (_a = props.formErrorSignalPromise) === null || _a === void 0 ? void 0 : _a.promise
14
+ ]).then(([ok, formChanged]) => {
15
+ okSignal.current = ok;
16
+ formErrorSignal.current = formChanged;
17
+ setReady(true);
18
+ });
19
+ return (ready && (React.createElement(CreationForm, { context: props.context, formSchemaRegistry: props.formSchemaRegistry, createLayer: props.createLayer, createSource: props.createSource, layerType: props.layerType, sourceType: props.sourceType, sourceData: props.sourceData, layerData: props.layerData, ok: okSignal.current, cancel: props.cancel, formErrorSignal: formErrorSignal.current })));
20
+ };
21
+ /**
22
+ * Form for creating a source, a layer or both at the same time
23
+ */
24
+ export class CreationFormDialog extends Dialog {
25
+ constructor(options) {
26
+ const cancelCallback = () => {
27
+ this.resolve(0);
28
+ };
29
+ const okSignalPromise = new PromiseDelegate();
30
+ const formErrorSignalPromise = new PromiseDelegate();
31
+ const body = (React.createElement("div", { style: { overflow: 'auto' } },
32
+ React.createElement(CreationFormWrapper, { context: options.context, formSchemaRegistry: options.formSchemaRegistry, createLayer: options.createLayer, createSource: options.createSource, layerType: options.layerType, sourceType: options.sourceType, sourceData: options.sourceData, layerData: options.layerData, okSignalPromise: okSignalPromise, cancel: cancelCallback, formErrorSignalPromise: formErrorSignalPromise })));
33
+ super({
34
+ title: options.title,
35
+ body,
36
+ buttons: [Dialog.cancelButton(), Dialog.okButton()]
37
+ });
38
+ this.okSignal = new Signal(this);
39
+ const formErrorSignal = new Signal(this);
40
+ /**
41
+ * Disable the OK button if the form is invalid.
42
+ */
43
+ formErrorSignal.connect((_, extraErrors) => {
44
+ const invalid = extraErrors || !!this.node.querySelector(':invalid');
45
+ if (invalid) {
46
+ this.node
47
+ .getElementsByClassName('jp-mod-accept')[0]
48
+ .setAttribute('disabled', '');
49
+ }
50
+ else {
51
+ this.node
52
+ .getElementsByClassName('jp-mod-accept')[0]
53
+ .removeAttribute('disabled');
54
+ }
55
+ });
56
+ okSignalPromise.resolve(this.okSignal);
57
+ formErrorSignalPromise.resolve(formErrorSignal);
58
+ this.addClass('jGIS-layer-CreationFormDialog');
59
+ }
60
+ resolve(index) {
61
+ if (index === 0) {
62
+ super.resolve(index);
63
+ }
64
+ if (index === 1) {
65
+ this.okSignal.emit(1);
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,25 @@
1
+ import { IJGISFormSchemaRegistry, IJupyterGISModel, IRasterLayerGalleryEntry } from '@jupytergis/schema';
2
+ import { Dialog } from '@jupyterlab/apputils';
3
+ import { PromiseDelegate } from '@lumino/coreutils';
4
+ import React from 'react';
5
+ import { DocumentRegistry } from '@jupyterlab/docregistry';
6
+ import { Signal } from '@lumino/signaling';
7
+ interface ILayerBrowserDialogProps {
8
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
9
+ registry: IRasterLayerGalleryEntry[];
10
+ formSchemaRegistry: IJGISFormSchemaRegistry;
11
+ okSignalPromise: PromiseDelegate<Signal<Dialog<any>, number>>;
12
+ cancel: () => void;
13
+ }
14
+ export declare const LayerBrowserComponent: ({ context, registry, formSchemaRegistry, okSignalPromise, cancel }: ILayerBrowserDialogProps) => React.JSX.Element;
15
+ export interface ILayerBrowserOptions {
16
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
17
+ registry: IRasterLayerGalleryEntry[];
18
+ formSchemaRegistry: IJGISFormSchemaRegistry;
19
+ }
20
+ export declare class LayerBrowserWidget extends Dialog<boolean> {
21
+ constructor(options: ILayerBrowserOptions);
22
+ resolve(index?: number): void;
23
+ private okSignal;
24
+ }
25
+ export {};
@@ -0,0 +1,141 @@
1
+ import { faCheck, faPlus } from '@fortawesome/free-solid-svg-icons';
2
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import { Dialog } from '@jupyterlab/apputils';
4
+ import { PromiseDelegate, UUID } from '@lumino/coreutils';
5
+ import React, { useEffect, useState } from 'react';
6
+ import CUSTOM_RASTER_IMAGE from '../../rasterlayer_gallery/custom_raster.png';
7
+ import { CreationFormWrapper } from './formdialog';
8
+ import { Signal } from '@lumino/signaling';
9
+ export const LayerBrowserComponent = ({ context, registry, formSchemaRegistry, okSignalPromise, cancel }) => {
10
+ const [searchTerm, setSearchTerm] = useState('');
11
+ const [activeLayers, setActiveLayers] = useState([]);
12
+ const [selectedCategory, setSelectedCategory] = useState();
13
+ const [creatingCustomRaster, setCreatingCustomRaster] = useState(false);
14
+ const [galleryWithCategory, setGalleryWithCategory] = useState(registry);
15
+ const providers = [...new Set(registry.map(item => item.source.provider))];
16
+ const filteredGallery = galleryWithCategory.filter(item => item.name.toLowerCase().includes(searchTerm));
17
+ useEffect(() => {
18
+ context.model.sharedModel.layersChanged.connect(handleLayerChange);
19
+ return () => {
20
+ context.model.sharedModel.layersChanged.disconnect(handleLayerChange);
21
+ };
22
+ }, []);
23
+ /**
24
+ * Track which layers are currently added to the map
25
+ */
26
+ const handleLayerChange = (_, change) => {
27
+ // The split is to get rid of the 'Layer' part of the name to match the names in the gallery
28
+ setActiveLayers(Object.values(context.model.sharedModel.layers).map(layer => layer.name.split(' ')[0]));
29
+ };
30
+ const handleSearchInput = (event) => {
31
+ setSearchTerm(event.target.value.toLowerCase());
32
+ };
33
+ const handleCategoryClick = (event) => {
34
+ const categoryTab = event.target;
35
+ const sameAsOld = categoryTab.innerText === (selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.innerText);
36
+ categoryTab.classList.toggle('jGIS-layer-browser-category-selected');
37
+ selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.classList.remove('jGIS-layer-browser-category-selected');
38
+ const filteredGallery = sameAsOld
39
+ ? registry
40
+ : registry.filter(item => { var _a; return (_a = item.source.provider) === null || _a === void 0 ? void 0 : _a.includes(categoryTab.innerText); });
41
+ setGalleryWithCategory(filteredGallery);
42
+ setSearchTerm('');
43
+ setSelectedCategory(sameAsOld ? null : categoryTab);
44
+ };
45
+ const handleCustomTileClick = () => {
46
+ setCreatingCustomRaster(true);
47
+ };
48
+ /**
49
+ * Add tile layer and source to model
50
+ * @param tile Tile to add
51
+ */
52
+ const handleTileClick = (tile) => {
53
+ const sourceId = UUID.uuid4();
54
+ const sourceModel = {
55
+ type: 'RasterSource',
56
+ name: tile.name,
57
+ parameters: tile.source
58
+ };
59
+ const layerModel = {
60
+ type: 'RasterLayer',
61
+ parameters: {
62
+ source: sourceId
63
+ },
64
+ visible: true,
65
+ name: tile.name + ' Layer'
66
+ };
67
+ context.model.sharedModel.addSource(sourceId, sourceModel);
68
+ context.model.addLayer(UUID.uuid4(), layerModel);
69
+ };
70
+ if (creatingCustomRaster) {
71
+ // Disconnect any previous handler
72
+ okSignalPromise.promise.then(value => {
73
+ value.disconnect(cancel, this);
74
+ });
75
+ return (React.createElement("div", { className: "jGIS-customlayer-form" },
76
+ React.createElement(CreationFormWrapper, { context: context, formSchemaRegistry: formSchemaRegistry, createLayer: true, createSource: true, layerType: 'RasterLayer', sourceType: 'RasterSource', layerData: {
77
+ name: 'Custom Raster'
78
+ }, sourceData: {
79
+ url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
80
+ maxZoom: 24,
81
+ minZoom: 0,
82
+ attribution: '(C) OpenStreetMap contributors'
83
+ }, okSignalPromise: okSignalPromise, cancel: cancel })));
84
+ }
85
+ // Ok is like cancel in the case of gallery item selections
86
+ okSignalPromise.promise.then(value => {
87
+ value.connect(cancel, this);
88
+ });
89
+ return (React.createElement("div", { className: "jGIS-layer-browser-container" },
90
+ React.createElement("div", { className: "jGIS-layer-browser-header-container" },
91
+ React.createElement("div", { className: "jGIS-layer-browser-header" },
92
+ React.createElement("h2", { className: "jGIS-layer-browser-header-text" }, "Layer Browser"),
93
+ React.createElement("div", { className: "jGIS-layer-browser-header-search-container" },
94
+ React.createElement("input", { type: "text", placeholder: "Search...", value: searchTerm, onChange: handleSearchInput, className: "jGIS-layer-browser-header-search" }))),
95
+ React.createElement("div", { className: "jGIS-layer-browser-categories" }, providers.map(provider => (React.createElement("span", { className: "jGIS-layer-browser-category", onClick: handleCategoryClick }, provider))))),
96
+ React.createElement("div", { className: "jGIS-layer-browser-grid" },
97
+ React.createElement("div", { className: "jGIS-layer-browser-tile jGIS-layer-browser-custom-tile", onClick: () => handleCustomTileClick() },
98
+ React.createElement("div", { className: "jGIS-layer-browser-tile-img-container" },
99
+ React.createElement("img", { className: "jGIS-layer-browser-img", src: CUSTOM_RASTER_IMAGE }),
100
+ React.createElement("div", { className: "jGIS-layer-browser-icon" },
101
+ React.createElement(FontAwesomeIcon, { style: { height: 20 }, icon: faPlus }))),
102
+ React.createElement("div", { className: "jGIS-layer-browser-text-container" },
103
+ React.createElement("div", { className: "jGIS-layer-browser-text-info" },
104
+ React.createElement("h3", { className: "jGIS-layer-browser-text-header jGIS-layer-browser-text-general" }, "Custom Raster Layer")),
105
+ React.createElement("p", { className: "jGIS-layer-browser-text-general jGIS-layer-browser-text-source" }, "Create A Custom Raster Layer"))),
106
+ filteredGallery.map(tile => (React.createElement("div", { className: "jGIS-layer-browser-tile", onClick: () => handleTileClick(tile) },
107
+ React.createElement("div", { className: "jGIS-layer-browser-tile-img-container" },
108
+ React.createElement("img", { className: "jGIS-layer-browser-img", src: tile.thumbnail }),
109
+ activeLayers.indexOf(tile.name) === -1 ? (React.createElement("div", { className: "jGIS-layer-browser-icon" },
110
+ React.createElement(FontAwesomeIcon, { style: { height: 20 }, icon: faPlus }))) : (React.createElement("div", { className: "jGIS-layer-browser-icon jGIS-layer-browser-added" },
111
+ React.createElement(FontAwesomeIcon, { style: { height: 20 }, icon: faCheck }),
112
+ React.createElement("p", { className: "jGIS-layer-browser-text-general" }, "Added!")))),
113
+ React.createElement("div", { className: "jGIS-layer-browser-text-container" },
114
+ React.createElement("div", { className: "jGIS-layer-browser-text-info" },
115
+ React.createElement("h3", { className: "jGIS-layer-browser-text-header jGIS-layer-browser-text-general" }, tile.name)),
116
+ React.createElement("p", { className: "jGIS-layer-browser-text-general jGIS-layer-browser-text-source" }, tile.source.attribution))))))));
117
+ };
118
+ export class LayerBrowserWidget extends Dialog {
119
+ constructor(options) {
120
+ let cancelCallback = undefined;
121
+ cancelCallback = () => {
122
+ this.resolve(0);
123
+ };
124
+ const okSignalPromise = new PromiseDelegate();
125
+ const body = (React.createElement(LayerBrowserComponent, { context: options.context, registry: options.registry, formSchemaRegistry: options.formSchemaRegistry, okSignalPromise: okSignalPromise, cancel: cancelCallback }));
126
+ super({ body, buttons: [Dialog.cancelButton(), Dialog.okButton()] });
127
+ this.id = 'jupytergis::layerBrowser';
128
+ this.okSignal = new Signal(this);
129
+ okSignalPromise.resolve(this.okSignal);
130
+ // Override default dialog style
131
+ this.addClass('jGIS-layerbrowser-FormDialog');
132
+ }
133
+ resolve(index) {
134
+ if (index === 0) {
135
+ super.resolve(index);
136
+ }
137
+ if (index === 1) {
138
+ this.okSignal.emit(1);
139
+ }
140
+ }
141
+ }
@@ -0,0 +1,23 @@
1
+ import { IJupyterGISModel } from '@jupytergis/schema';
2
+ import { Dialog } from '@jupyterlab/apputils';
3
+ import { DocumentRegistry } from '@jupyterlab/docregistry';
4
+ import { IStateDB } from '@jupyterlab/statedb';
5
+ import { PromiseDelegate } from '@lumino/coreutils';
6
+ import { Signal } from '@lumino/signaling';
7
+ export interface ISymbologyDialogProps {
8
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
9
+ state: IStateDB;
10
+ okSignalPromise: PromiseDelegate<Signal<SymbologyWidget, null>>;
11
+ cancel: () => void;
12
+ layerId?: string;
13
+ }
14
+ export interface ISymbologyWidgetOptions {
15
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
16
+ state: IStateDB;
17
+ }
18
+ export declare class SymbologyWidget extends Dialog<boolean> {
19
+ private okSignal;
20
+ constructor(options: ISymbologyWidgetOptions);
21
+ resolve(index: number): void;
22
+ }
23
+ export default SymbologyWidget;
@@ -0,0 +1,68 @@
1
+ import { Dialog } from '@jupyterlab/apputils';
2
+ import { PromiseDelegate } from '@lumino/coreutils';
3
+ import { Signal } from '@lumino/signaling';
4
+ import React, { useEffect, useState } from 'react';
5
+ import BandRendering from './components/symbology/BandRendering';
6
+ const SymbologyDialog = ({ context, state, okSignalPromise, cancel }) => {
7
+ const [selectedLayer, setSelectedLayer] = useState(null);
8
+ const [componentToRender, setComponentToRender] = useState(null);
9
+ let LayerSymbology;
10
+ useEffect(() => {
11
+ const handleClientStateChanged = () => {
12
+ var _a, _b;
13
+ if (!((_b = (_a = context.model.localState) === null || _a === void 0 ? void 0 : _a.selected) === null || _b === void 0 ? void 0 : _b.value)) {
14
+ return;
15
+ }
16
+ const currentLayer = Object.keys(context.model.localState.selected.value)[0];
17
+ setSelectedLayer(currentLayer);
18
+ };
19
+ // Initial state
20
+ handleClientStateChanged();
21
+ context.model.clientStateChanged.connect(handleClientStateChanged);
22
+ return () => {
23
+ context.model.clientStateChanged.disconnect(handleClientStateChanged);
24
+ };
25
+ }, []);
26
+ useEffect(() => {
27
+ if (!selectedLayer) {
28
+ return;
29
+ }
30
+ const layer = context.model.getLayer(selectedLayer);
31
+ if (!layer) {
32
+ return;
33
+ }
34
+ // TODO WebGlLayers can also be used for other layers, need a better way to determine source + layer combo
35
+ switch (layer.type) {
36
+ case 'WebGlLayer':
37
+ LayerSymbology = (React.createElement(BandRendering, { context: context, state: state, okSignalPromise: okSignalPromise, cancel: cancel, layerId: selectedLayer }));
38
+ break;
39
+ default:
40
+ LayerSymbology = React.createElement("div", null, "Layer Type Not Supported");
41
+ }
42
+ setComponentToRender(LayerSymbology);
43
+ }, [selectedLayer]);
44
+ return React.createElement(React.Fragment, null, componentToRender);
45
+ };
46
+ export class SymbologyWidget extends Dialog {
47
+ constructor(options) {
48
+ const cancelCallback = () => {
49
+ this.resolve(0);
50
+ };
51
+ const okSignalPromise = new PromiseDelegate();
52
+ const body = (React.createElement(SymbologyDialog, { context: options.context, okSignalPromise: okSignalPromise, cancel: cancelCallback, state: options.state }));
53
+ super({ title: 'Symbology', body });
54
+ this.id = 'jupytergis::symbologyWidget';
55
+ this.okSignal = new Signal(this);
56
+ okSignalPromise.resolve(this.okSignal);
57
+ this.addClass('jp-gis-symbology-dialog');
58
+ }
59
+ resolve(index) {
60
+ if (index === 0) {
61
+ super.resolve(index);
62
+ }
63
+ if (index === 1) {
64
+ this.okSignal.emit(null);
65
+ }
66
+ }
67
+ }
68
+ export default SymbologyWidget;
@@ -0,0 +1,21 @@
1
+ import { IJupyterGISModel } from '@jupytergis/schema';
2
+ import { Dialog } from '@jupyterlab/apputils';
3
+ import { DocumentRegistry } from '@jupyterlab/docregistry';
4
+ import { PromiseDelegate } from '@lumino/coreutils';
5
+ import { Signal } from '@lumino/signaling';
6
+ import React from 'react';
7
+ interface ITerrainDialogProps {
8
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
9
+ okSignalPromise: PromiseDelegate<Signal<TerrainDialogWidget, null>>;
10
+ cancel: () => void;
11
+ }
12
+ declare const TerrainDialog: ({ context, okSignalPromise, cancel }: ITerrainDialogProps) => React.JSX.Element;
13
+ export interface ITerrainDialogOptions {
14
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
15
+ }
16
+ export declare class TerrainDialogWidget extends Dialog<boolean> {
17
+ private okSignal;
18
+ constructor(options: ITerrainDialogOptions);
19
+ resolve(index?: number): void;
20
+ }
21
+ export default TerrainDialog;
@@ -0,0 +1,60 @@
1
+ import { Dialog } from '@jupyterlab/apputils';
2
+ import { PromiseDelegate } from '@lumino/coreutils';
3
+ import { Signal } from '@lumino/signaling';
4
+ import React, { useEffect, useRef, useState } from 'react';
5
+ const TerrainDialog = ({ context, okSignalPromise, cancel }) => {
6
+ const rasterDemSources = context.model.getSourcesByType('RasterDemSource');
7
+ const [selectedSource, setSelectedSource] = useState(Object.keys(rasterDemSources)[0]);
8
+ const [exaggerationInput, setExaggerationInput] = useState(1);
9
+ const selectedSourceRef = useRef(selectedSource);
10
+ const exaggerationInputRef = useRef(exaggerationInput);
11
+ useEffect(() => {
12
+ selectedSourceRef.current = selectedSource;
13
+ exaggerationInputRef.current = exaggerationInput;
14
+ }, [selectedSource, exaggerationInput]);
15
+ // Handler for changing the selected option
16
+ const handleSourceChange = (event) => {
17
+ setSelectedSource(event.target.value);
18
+ };
19
+ // Handler for changing the number input
20
+ const handleExaggerationChange = (event) => {
21
+ setExaggerationInput(Number(event.target.value));
22
+ };
23
+ const handleOk = () => {
24
+ context.model.setTerrain({
25
+ source: selectedSourceRef.current,
26
+ exaggeration: exaggerationInputRef.current
27
+ });
28
+ cancel();
29
+ };
30
+ okSignalPromise.promise.then(okSignal => {
31
+ okSignal.connect(handleOk);
32
+ });
33
+ return (React.createElement("div", { className: "jp-gis-terrain-main" },
34
+ React.createElement("label", { className: "jp-gis-terrain-label", htmlFor: "source" }, "Source:"),
35
+ React.createElement("select", { id: "source", className: "jp-mod-styled", value: selectedSource, onChange: handleSourceChange, "aria-label": "Select source" }, Object.entries(rasterDemSources).map(([key, value]) => (React.createElement("option", { key: key, value: key }, value)))),
36
+ React.createElement("label", { className: "jp-gis-terrain-label", htmlFor: "exaggeration" }, "Exaggeration:"),
37
+ React.createElement("input", { id: "exaggeration", className: "jp-mod-styled", type: "number", min: 0, step: 0.1, value: exaggerationInput, onChange: handleExaggerationChange, placeholder: "Enter an exaggeration value", "aria-label": "Enter exaggeration value" })));
38
+ };
39
+ export class TerrainDialogWidget extends Dialog {
40
+ constructor(options) {
41
+ const cancelCallback = () => {
42
+ this.resolve(0);
43
+ };
44
+ const okSignalPromise = new PromiseDelegate();
45
+ const body = (React.createElement(TerrainDialog, { context: options.context, okSignalPromise: okSignalPromise, cancel: cancelCallback }));
46
+ super({ title: 'Add New Terrain', body });
47
+ this.id = 'jupytergis::terrain';
48
+ this.okSignal = new Signal(this);
49
+ okSignalPromise.resolve(this.okSignal);
50
+ }
51
+ resolve(index) {
52
+ if (index === 0) {
53
+ super.resolve(index);
54
+ }
55
+ if (index === 1) {
56
+ this.okSignal.emit(null);
57
+ }
58
+ }
59
+ }
60
+ export default TerrainDialog;
@@ -0,0 +1,56 @@
1
+ import { DocumentRegistry } from '@jupyterlab/docregistry';
2
+ import { IDict, IJGISFormSchemaRegistry, IJupyterGISModel, LayerType, SourceType } from '@jupytergis/schema';
3
+ import { Dialog } from '@jupyterlab/apputils';
4
+ import { Signal } from '@lumino/signaling';
5
+ import * as React from 'react';
6
+ export interface ICreationFormProps {
7
+ /**
8
+ * Whether or not to create a layer
9
+ */
10
+ createLayer: boolean;
11
+ /**
12
+ * Whether or not to create a source
13
+ */
14
+ createSource: boolean;
15
+ /**
16
+ * The type of layer to create.
17
+ */
18
+ layerType?: LayerType;
19
+ /**
20
+ * The type of source to create or to select in the case where we only create a layer.
21
+ */
22
+ sourceType: SourceType;
23
+ /**
24
+ * The initial layer data, if it applies.
25
+ */
26
+ layerData?: IDict;
27
+ /**
28
+ * The initial source data, if it applies.
29
+ */
30
+ sourceData?: IDict;
31
+ /**
32
+ * Ok signal. This is the signal sent by the parent dialog upon "Ok" button click. No ok button will be displayed if defined.
33
+ */
34
+ ok?: Signal<Dialog<any>, number>;
35
+ /**
36
+ * Cancel callback
37
+ */
38
+ cancel?: () => void;
39
+ formSchemaRegistry: IJGISFormSchemaRegistry;
40
+ context: DocumentRegistry.IContext<IJupyterGISModel>;
41
+ /**
42
+ * A signal emitting when the form changed, with a boolean whether there are some
43
+ * extra errors or not.
44
+ */
45
+ formErrorSignal?: Signal<Dialog<any>, boolean>;
46
+ }
47
+ /**
48
+ * Form for creating a source, a layer or both at the same time
49
+ */
50
+ export declare class CreationForm extends React.Component<ICreationFormProps, any> {
51
+ constructor(props: ICreationFormProps);
52
+ render(): React.JSX.Element | undefined;
53
+ private jGISModel;
54
+ private filePath;
55
+ private sourceFormChangedSignal;
56
+ }