@jupytergis/base 0.1.3 → 0.1.5

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.
package/lib/commands.js CHANGED
@@ -3,7 +3,6 @@ import { CommandIDs, icons } from './constants';
3
3
  import { CreationFormDialog } from './dialogs/formdialog';
4
4
  import { LayerBrowserWidget } from './dialogs/layerBrowserDialog';
5
5
  import { SymbologyWidget } from './dialogs/symbologyDialog';
6
- import { TerrainDialogWidget } from './dialogs/terrainDialog';
7
6
  /**
8
7
  * Add the commands to the application's command registry.
9
8
  */
@@ -538,29 +537,6 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
538
537
  });
539
538
  }
540
539
  });
541
- /**
542
- * Terrain commands
543
- */
544
- commands.addCommand(CommandIDs.newTerrain, Object.assign({ label: trans.__('New Terrain'), isEnabled: () => {
545
- return tracker.currentWidget
546
- ? tracker.currentWidget.context.model.sharedModel.editable
547
- : false;
548
- }, execute: Private.createTerrainDialog(tracker) }, icons.get(CommandIDs.newTerrain)));
549
- commands.addCommand(CommandIDs.removeTerrain, {
550
- label: trans.__('Remove Terrain'),
551
- isEnabled: () => {
552
- return tracker.currentWidget
553
- ? tracker.currentWidget.context.model.sharedModel.editable
554
- : false;
555
- },
556
- execute: () => {
557
- var _a;
558
- (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.context.model.setTerrain({
559
- source: '',
560
- exaggeration: 0
561
- });
562
- }
563
- });
564
540
  // Console commands
565
541
  commands.addCommand(CommandIDs.toggleConsole, {
566
542
  label: trans.__('Toggle console'),
@@ -635,19 +611,6 @@ var Private;
635
611
  };
636
612
  }
637
613
  Private.createLayerBrowser = createLayerBrowser;
638
- function createTerrainDialog(tracker) {
639
- return async () => {
640
- const current = tracker.currentWidget;
641
- if (!current) {
642
- return;
643
- }
644
- const dialog = new TerrainDialogWidget({
645
- context: current.context
646
- });
647
- await dialog.launch();
648
- };
649
- }
650
- Private.createTerrainDialog = createTerrainDialog;
651
614
  function createSymbologyDialog(tracker, state) {
652
615
  return async () => {
653
616
  const current = tracker.currentWidget;
@@ -38,8 +38,6 @@ export declare namespace CommandIDs {
38
38
  const moveLayerToNewGroup = "jupytergis:moveLayerToNewGroup";
39
39
  const renameSource = "jupytergis:renameSource";
40
40
  const removeSource = "jupytergis:removeSource";
41
- const newTerrain = "jupytergis:newTerrain";
42
- const removeTerrain = "jupytergis:removeTerrain";
43
41
  const toggleConsole = "jupytergis:toggleConsole";
44
42
  const invokeCompleter = "jupytergis:invokeConsoleCompleter";
45
43
  const removeConsole = "jupytergis:removeConsole";
package/lib/constants.js CHANGED
@@ -46,9 +46,6 @@ export var CommandIDs;
46
46
  // Source actions
47
47
  CommandIDs.renameSource = 'jupytergis:renameSource';
48
48
  CommandIDs.removeSource = 'jupytergis:removeSource';
49
- // Terrain stuff
50
- CommandIDs.newTerrain = 'jupytergis:newTerrain';
51
- CommandIDs.removeTerrain = 'jupytergis:removeTerrain';
52
49
  // Console commands
53
50
  CommandIDs.toggleConsole = 'jupytergis:toggleConsole';
54
51
  CommandIDs.invokeCompleter = 'jupytergis:invokeConsoleCompleter';
@@ -80,7 +77,6 @@ const iconObject = {
80
77
  [CommandIDs.newVideoEntry]: { iconClass: 'fa fa-video' },
81
78
  [CommandIDs.newShapefileLayer]: { iconClass: 'fa fa-file' },
82
79
  [CommandIDs.newGeoTiffEntry]: { iconClass: 'fa fa-image' },
83
- [CommandIDs.newTerrain]: { iconClass: 'fa fa-mountain' },
84
80
  [CommandIDs.symbology]: { iconClass: 'fa fa-brush' }
85
81
  };
86
82
  /**
@@ -2,9 +2,9 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons';
2
2
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
3
  import { Button } from '@jupyterlab/ui-components';
4
4
  import React, { useEffect, useRef, useState } from 'react';
5
+ import { getGdal } from '../../../gdal';
5
6
  import BandRow from './BandRow';
6
7
  import StopRow from './StopRow';
7
- import { getGdal } from '../../../gdal';
8
8
  const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerId }) => {
9
9
  const functions = ['discrete', 'linear', 'exact'];
10
10
  const stopRowsRef = useRef();
@@ -248,7 +248,9 @@ const SingleBandPseudoColor = ({ context, state, okSignalPromise, cancel, layerI
248
248
  (currentBand.stats.maximum - currentBand.stats.minimum));
249
249
  };
250
250
  return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
251
- React.createElement("div", { className: "jp-gis-band-container" }, bandRows.length === 0 ? (React.createElement(FontAwesomeIcon, { icon: faSpinner })) : (React.createElement(BandRow
251
+ React.createElement("div", { className: "jp-gis-band-container" }, bandRows.length === 0 ? (React.createElement("div", { className: "jp-gis-band-info-loading-container" },
252
+ React.createElement("span", null, "Fetching band info..."),
253
+ React.createElement(FontAwesomeIcon, { icon: faSpinner, className: "jp-gis-loading-spinner" }))) : (React.createElement(BandRow
252
254
  // Band numbers are 1 indexed
253
255
  , {
254
256
  // Band numbers are 1 indexed
@@ -47,6 +47,14 @@ export declare class MainView extends React.Component<IProps, IStates> {
47
47
  */
48
48
  updateLayers(layerIds: string[]): void;
49
49
  private _updateLayersImpl;
50
+ /**
51
+ * Build the map layer.
52
+ *
53
+ * @param id - id of the layer.
54
+ * @param layer - the layer object.
55
+ * @returns - the map layer.
56
+ */
57
+ private _buildMapLayer;
50
58
  /**
51
59
  * Add a layer to the map.
52
60
  *
@@ -65,13 +73,6 @@ export declare class MainView extends React.Component<IProps, IStates> {
65
73
  * @returns
66
74
  */
67
75
  private hillshadeMath;
68
- /**
69
- * Move a layer in the stack.
70
- *
71
- * @param id - id of the layer.
72
- * @param index - expected index of the layer.
73
- */
74
- moveLayer(id: string, index: number | undefined): void;
75
76
  /**
76
77
  * Update a layer of the map.
77
78
  *
@@ -1,6 +1,6 @@
1
1
  import { JupyterGISModel } from '@jupytergis/schema';
2
2
  import { UUID } from '@lumino/coreutils';
3
- import { Map as OlMap, View } from 'ol';
3
+ import { Collection, Map as OlMap, View } from 'ol';
4
4
  import { ScaleLine } from 'ol/control';
5
5
  import { GeoJSON, MVT } from 'ol/format';
6
6
  import DragAndDrop from 'ol/interaction/DragAndDrop';
@@ -37,7 +37,9 @@ export class MainView extends React.Component {
37
37
  style: defaultStyle
38
38
  };
39
39
  const layerStyle = Object.assign({}, defaultRules);
40
- if (layer.filters && layer.filters.appliedFilters.length !== 0) {
40
+ if (layer.filters &&
41
+ layer.filters.logicalOp &&
42
+ layer.filters.appliedFilters.length !== 0) {
41
43
  const filterExpr = [];
42
44
  // 'Any' and 'All' operators require more than one argument
43
45
  // So if there's only one filter, skip that part to avoid error
@@ -215,10 +217,7 @@ export class MainView extends React.Component {
215
217
  projection: projection.getCode(),
216
218
  zoom
217
219
  };
218
- // Update the extent only if has been initially provided.
219
- if (currentOptions.extent) {
220
- updatedOptions.extent = view.calculateExtent();
221
- }
220
+ updatedOptions.extent = view.calculateExtent();
222
221
  this._model.setOptions(Object.assign(Object.assign({}, currentOptions), updatedOptions));
223
222
  });
224
223
  if (JupyterGISModel.getOrderedLayerIds(this._model).length !== 0) {
@@ -306,13 +305,17 @@ export class MainView extends React.Component {
306
305
  case 'GeoJSONSource': {
307
306
  const data = ((_a = source.parameters) === null || _a === void 0 ? void 0 : _a.data) ||
308
307
  (await this._model.readGeoJSON((_b = source.parameters) === null || _b === void 0 ? void 0 : _b.path));
309
- const format = new GeoJSON();
308
+ const format = new GeoJSON({
309
+ featureProjection: this._Map.getView().getProjection()
310
+ });
310
311
  // TODO: Don't hardcode projection
312
+ const featureArray = format.readFeatures(data, {
313
+ dataProjection: 'EPSG:4326',
314
+ featureProjection: this._Map.getView().getProjection()
315
+ });
316
+ const featureCollection = new Collection(featureArray);
311
317
  newSource = new VectorSource({
312
- features: format.readFeatures(data, {
313
- dataProjection: 'EPSG:4326',
314
- featureProjection: this._Map.getView().getProjection()
315
- })
318
+ features: featureCollection
316
319
  });
317
320
  break;
318
321
  }
@@ -426,59 +429,30 @@ export class MainView extends React.Component {
426
429
  this._updateLayersImpl(layerIds);
427
430
  }
428
431
  async _updateLayersImpl(layerIds) {
429
- const previousLayerIds = this.getLayers();
430
- // We use the reverse order of the list to add the layer from the top to the
431
- // bottom.
432
- // This is to ensure that the beforeId (layer on top of the one we add/move)
433
- // is already added/moved in the map.
434
- const reversedLayerIds = layerIds.slice().reverse();
435
- for (const layerId of reversedLayerIds) {
432
+ const mapLayers = [];
433
+ for (const layerId of layerIds) {
436
434
  const layer = this._model.sharedModel.getLayer(layerId);
437
435
  if (!layer) {
438
436
  console.log(`Layer id ${layerId} does not exist`);
439
- return;
440
- }
441
- // Get the expected index in the map.
442
- const currentLayerIds = [...previousLayerIds];
443
- let indexInMap = currentLayerIds.length;
444
- const nextLayer = layerIds[layerIds.indexOf(layerId) + 1];
445
- if (nextLayer !== undefined) {
446
- indexInMap = currentLayerIds.indexOf(nextLayer);
447
- if (indexInMap === -1) {
448
- indexInMap = currentLayerIds.length;
449
- }
450
- }
451
- if (this.getLayer(layerId)) {
452
- this.moveLayer(layerId, indexInMap);
437
+ continue;
453
438
  }
454
- else {
455
- await this.addLayer(layerId, layer, indexInMap);
456
- }
457
- // Remove the element of the previous list as treated.
458
- const index = previousLayerIds.indexOf(layerId);
459
- if (index > -1) {
460
- previousLayerIds.splice(index, 1);
439
+ const newMapLayer = await this._buildMapLayer(layerId, layer);
440
+ if (newMapLayer !== undefined) {
441
+ mapLayers.push(newMapLayer);
461
442
  }
462
443
  }
463
- // Remove the layers not used anymore.
464
- previousLayerIds.forEach(layerId => {
465
- this._Map.removeLayer(layerId);
466
- });
444
+ this._Map.setLayers(mapLayers);
467
445
  this._ready = true;
468
446
  }
469
447
  /**
470
- * Add a layer to the map.
448
+ * Build the map layer.
471
449
  *
472
450
  * @param id - id of the layer.
473
451
  * @param layer - the layer object.
474
- * @param index - expected index of the layer.
452
+ * @returns - the map layer.
475
453
  */
476
- async addLayer(id, layer, index) {
454
+ async _buildMapLayer(id, layer) {
477
455
  var _a;
478
- if (this.getLayer(id)) {
479
- // Layer already exists
480
- return;
481
- }
482
456
  const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
483
457
  const source = this._model.sharedModel.getSource(sourceId);
484
458
  if (!source) {
@@ -487,14 +461,14 @@ export class MainView extends React.Component {
487
461
  if (!this._sources[sourceId]) {
488
462
  await this.addSource(sourceId, source);
489
463
  }
490
- let newLayer;
464
+ let newMapLayer;
491
465
  let layerParameters;
492
466
  // TODO: OpenLayers provides a bunch of sources for specific tile
493
467
  // providers, so maybe set up some way to use those
494
468
  switch (layer.type) {
495
469
  case 'RasterLayer': {
496
470
  layerParameters = layer.parameters;
497
- newLayer = new TileLayer({
471
+ newMapLayer = new TileLayer({
498
472
  opacity: layerParameters.opacity,
499
473
  visible: layer.visible,
500
474
  source: this._sources[layerParameters.source]
@@ -503,7 +477,7 @@ export class MainView extends React.Component {
503
477
  }
504
478
  case 'VectorLayer': {
505
479
  layerParameters = layer.parameters;
506
- newLayer = new VectorLayer({
480
+ newMapLayer = new VectorLayer({
507
481
  opacity: layerParameters.opacity,
508
482
  visible: layer.visible,
509
483
  source: this._sources[layerParameters.source],
@@ -513,19 +487,16 @@ export class MainView extends React.Component {
513
487
  }
514
488
  case 'VectorTileLayer': {
515
489
  layerParameters = layer.parameters;
516
- if (!layerParameters.color) {
517
- return;
518
- }
519
- newLayer = new VectorTileLayer({
490
+ newMapLayer = new VectorTileLayer({
520
491
  opacity: layerParameters.opacity,
521
492
  source: this._sources[layerParameters.source]
522
493
  });
523
- this.updateLayer(id, layer, newLayer);
494
+ this.updateLayer(id, layer, newMapLayer);
524
495
  break;
525
496
  }
526
497
  case 'HillshadeLayer': {
527
498
  layerParameters = layer.parameters;
528
- newLayer = new WebGlTileLayer({
499
+ newMapLayer = new WebGlTileLayer({
529
500
  opacity: 0.3,
530
501
  source: this._sources[layerParameters.source],
531
502
  style: {
@@ -536,7 +507,7 @@ export class MainView extends React.Component {
536
507
  }
537
508
  case 'ImageLayer': {
538
509
  layerParameters = layer.parameters;
539
- newLayer = new ImageLayer({
510
+ newMapLayer = new ImageLayer({
540
511
  opacity: layerParameters.opacity,
541
512
  source: this._sources[layerParameters.source]
542
513
  });
@@ -552,43 +523,32 @@ export class MainView extends React.Component {
552
523
  if (layerParameters.color) {
553
524
  layerOptions['style'] = { color: layerParameters.color };
554
525
  }
555
- newLayer = new WebGlTileLayer(layerOptions);
526
+ newMapLayer = new WebGlTileLayer(layerOptions);
556
527
  break;
557
528
  }
558
529
  }
559
530
  // OpenLayers doesn't have name/id field so add it
560
- newLayer.set('id', id);
531
+ newMapLayer.set('id', id);
561
532
  // we need to keep track of which source has which layers
562
533
  this._sourceToLayerMap.set(layerParameters.source, id);
563
- this._Map.getLayers().insertAt(index, newLayer);
534
+ return newMapLayer;
564
535
  }
565
536
  /**
566
- * Move a layer in the stack.
537
+ * Add a layer to the map.
567
538
  *
568
539
  * @param id - id of the layer.
540
+ * @param layer - the layer object.
569
541
  * @param index - expected index of the layer.
570
542
  */
571
- moveLayer(id, index) {
572
- // Get the beforeId value according to the expected index.
573
- const currentLayerIds = this.getLayers();
574
- let beforeId = undefined;
575
- if (!(index === undefined) && index < currentLayerIds.length) {
576
- beforeId = currentLayerIds[index];
577
- }
578
- const layerArray = this._Map.getLayers().getArray();
579
- const movingLayer = this.getLayer(id);
580
- if (!movingLayer || !index || !beforeId) {
543
+ async addLayer(id, layer, index) {
544
+ if (this.getLayer(id)) {
545
+ // Layer already exists
581
546
  return;
582
547
  }
583
- const indexOfMovingLayer = layerArray.indexOf(movingLayer);
584
- layerArray.splice(indexOfMovingLayer, 1);
585
- const beforeLayer = this.getLayer(beforeId);
586
- if (!beforeLayer) {
587
- return;
548
+ const newMapLayer = await this._buildMapLayer(id, layer);
549
+ if (newMapLayer !== undefined) {
550
+ this._Map.getLayers().insertAt(index, newMapLayer);
588
551
  }
589
- const indexOfBeforeLayer = layerArray.indexOf(beforeLayer);
590
- layerArray.splice(indexOfBeforeLayer, 0, movingLayer);
591
- this._Map.setLayers(layerArray);
592
552
  }
593
553
  /**
594
554
  * Update a layer of the map.
@@ -662,14 +622,19 @@ export class MainView extends React.Component {
662
622
  }
663
623
  updateOptions(options) {
664
624
  const view = this._Map.getView();
665
- // use the extent if provided.
666
- if (options.extent) {
625
+ // Use the extent only if explicitly requested (QGIS files).
626
+ if (options.extent && options.useExtent) {
667
627
  view.fit(options.extent);
668
628
  }
669
629
  else {
670
630
  const centerCoord = fromLonLat([options.longitude || 0, options.latitude || 0], this._Map.getView().getProjection());
671
631
  this._Map.getView().setZoom(options.zoom || 0);
672
632
  this._Map.getView().setCenter(centerCoord);
633
+ // Save the extent if it does not exists, to allow proper export to qgis.
634
+ if (options.extent === undefined) {
635
+ options.extent = view.calculateExtent();
636
+ this._model.setOptions(options);
637
+ }
673
638
  }
674
639
  view.setRotation(options.bearing || 0);
675
640
  }
@@ -709,12 +674,14 @@ export class MainView extends React.Component {
709
674
  }
710
675
  else {
711
676
  const mapLayer = this.getLayer(change.id);
712
- if (mapLayer &&
713
- JupyterGISModel.getOrderedLayerIds(this._model).includes(change.id)) {
714
- this.updateLayer(change.id, layer, mapLayer);
715
- }
716
- else {
717
- this.updateLayers(JupyterGISModel.getOrderedLayerIds(this._model));
677
+ const layerTree = JupyterGISModel.getOrderedLayerIds(this._model);
678
+ if (mapLayer) {
679
+ if (layerTree.includes(change.id)) {
680
+ this.updateLayer(change.id, layer, mapLayer);
681
+ }
682
+ else {
683
+ this.updateLayers(layerTree);
684
+ }
718
685
  }
719
686
  }
720
687
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupytergis/base",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "A JupyterLab extension for 3D modelling.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -41,7 +41,7 @@
41
41
  "@deathbeds/jupyterlab-rjsf": "^1.1.0",
42
42
  "@jupyter/docprovider": "^2.0.0",
43
43
  "@jupyter/ydoc": "^1.0.0",
44
- "@jupytergis/schema": "^0.1.3",
44
+ "@jupytergis/schema": "^0.1.5",
45
45
  "@jupyterlab/application": "^4.0.0",
46
46
  "@jupyterlab/apputils": "^4.0.0",
47
47
  "@jupyterlab/completer": "^4.2.4",
package/style/base.css CHANGED
@@ -6,7 +6,6 @@
6
6
  @import url('./dialog.css');
7
7
  @import url('./layerBrowser.css');
8
8
  @import url('./leftPanel.css');
9
- @import url('./terrainDialog.css');
10
9
  @import url('./filterPanel.css');
11
10
  @import url('./symbologyDialog.css');
12
11
  @import url('ol/ol.css');
@@ -92,3 +92,31 @@
92
92
  .jp-gis-symbology-button-container {
93
93
  padding-top: 0.5rem;
94
94
  }
95
+
96
+ .jp-gis-band-info-loading-container {
97
+ display: flex;
98
+ justify-content: center;
99
+ align-items: center;
100
+ gap: 2rem;
101
+ margin: auto;
102
+ }
103
+
104
+ .jp-gis-loading-spinner {
105
+ animation: spin 4s linear infinite;
106
+ font-size: 1.5rem;
107
+ padding: 1rem 0;
108
+ margin: auto;
109
+ }
110
+
111
+ .jp-gis-band-info-loading-container > span {
112
+ font-size: 1rem;
113
+ }
114
+
115
+ @keyframes spin {
116
+ from {
117
+ transform: rotate(0deg);
118
+ }
119
+ to {
120
+ transform: rotate(360deg);
121
+ }
122
+ }
@@ -1,21 +0,0 @@
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;
@@ -1,60 +0,0 @@
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;
@@ -1,14 +0,0 @@
1
- .jp-gis-terrain-main {
2
- display: flex;
3
- flex-direction: column;
4
- gap: 0.5rem;
5
- overflow: hidden;
6
- }
7
-
8
- .jp-gis-terrain-label {
9
- margin: 0;
10
- padding: 0;
11
- font-weight: bold;
12
- display: block;
13
- position: relative;
14
- }