@jupytergis/base 0.4.0 → 0.4.2

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.
@@ -1,4 +1,4 @@
1
- import { IDict, IJGISLayer, IJupyterGISModel } from '@jupytergis/schema';
1
+ import { IJGISLayer, IJupyterGISModel } from '@jupytergis/schema';
2
2
  export interface IBandHistogram {
3
3
  buckets: number[];
4
4
  count: number;
@@ -7,15 +7,11 @@ export interface IBandHistogram {
7
7
  }
8
8
  export interface IBandRow {
9
9
  band: number;
10
- colorInterpretation: string;
10
+ colorInterpretation?: string;
11
11
  stats: {
12
12
  minimum: number;
13
13
  maximum: number;
14
- mean: number;
15
- stdDev: number;
16
14
  };
17
- metadata: IDict;
18
- histogram: IBandHistogram;
19
15
  }
20
16
  declare const useGetBandInfo: (model: IJupyterGISModel, layer: IJGISLayer) => {
21
17
  bandRows: IBandRow[];
@@ -1,19 +1,11 @@
1
1
  import { useEffect, useState } from 'react';
2
- import { loadFile } from '../../../tools';
3
- const preloadGeoTiffFile = async (sourceInfo, model) => {
4
- var _a;
5
- return await loadFile({
6
- filepath: (_a = sourceInfo.url) !== null && _a !== void 0 ? _a : '',
7
- type: 'GeoTiffSource',
8
- model: model
9
- });
10
- };
2
+ import { fromUrl } from 'geotiff';
11
3
  const useGetBandInfo = (model, layer) => {
12
4
  const [bandRows, setBandRows] = useState([]);
13
5
  const [loading, setLoading] = useState(false);
14
6
  const [error, setError] = useState(null);
15
7
  const fetchBandInfo = async () => {
16
- var _a, _b;
8
+ var _a, _b, _c, _d;
17
9
  setLoading(true);
18
10
  setError(null);
19
11
  try {
@@ -25,29 +17,20 @@ const useGetBandInfo = (model, layer) => {
25
17
  setLoading(false);
26
18
  return;
27
19
  }
28
- const preloadedFile = await preloadGeoTiffFile(sourceInfo, model);
29
- const { file, metadata, sourceUrl } = Object.assign({}, preloadedFile);
30
- if (file && metadata && sourceUrl === sourceInfo.url) {
31
- metadata['bands'].forEach((bandData) => {
32
- var _a, _b;
33
- bandsArr.push({
34
- band: bandData.band,
35
- colorInterpretation: bandData.colorInterpretation,
36
- stats: {
37
- minimum: (_a = sourceInfo.min) !== null && _a !== void 0 ? _a : bandData.minimum,
38
- maximum: (_b = sourceInfo.max) !== null && _b !== void 0 ? _b : bandData.maximum,
39
- mean: bandData.mean,
40
- stdDev: bandData.stdDev
41
- },
42
- metadata: bandData.metadata,
43
- histogram: bandData.histogram
44
- });
20
+ // TODO Get band names + get band stats
21
+ const tiff = await fromUrl(sourceInfo.url);
22
+ const image = await tiff.getImage();
23
+ const numberOfBands = image.getSamplesPerPixel();
24
+ for (let i = 0; i < numberOfBands; i++) {
25
+ bandsArr.push({
26
+ band: i,
27
+ stats: {
28
+ minimum: (_c = sourceInfo.min) !== null && _c !== void 0 ? _c : 0,
29
+ maximum: (_d = sourceInfo.max) !== null && _d !== void 0 ? _d : 100
30
+ }
45
31
  });
46
- setBandRows(bandsArr);
47
- }
48
- else {
49
- setError('Failed to preload the file or metadata mismatch.');
50
32
  }
33
+ setBandRows(bandsArr);
51
34
  }
52
35
  catch (err) {
53
36
  setError(`Error fetching band info: ${err.message}`);
@@ -33,7 +33,9 @@ const BandRow = ({ label, index, bandRow, bandRows, setSelectedBand, setBandRows
33
33
  ":"),
34
34
  React.createElement("div", { className: "jp-select-wrapper" },
35
35
  React.createElement("select", { name: `band-select-${index}`, onChange: event => setSelectedBand(+event.target.value), className: "jp-mod-styled" },
36
- bandRows.map((band, bandIndex) => (React.createElement("option", { key: bandIndex, value: band.band, selected: band.band === (bandRow === null || bandRow === void 0 ? void 0 : bandRow.band), className: "jp-mod-styled" }, `Band ${band.band} (${band.colorInterpretation})`))),
36
+ bandRows.map((band, bandIndex) => (React.createElement("option", { key: bandIndex, value: band.band, selected: band.band === (bandRow === null || bandRow === void 0 ? void 0 : bandRow.band), className: "jp-mod-styled" }, band.colorInterpretation
37
+ ? `Band ${band.band} (${band.colorInterpretation})`
38
+ : `Band ${band.band}`))),
37
39
  isMultibandColor ? (React.createElement("option", { key: 'unset', value: 0, selected: !bandRow, className: "jp-mod-styled" }, "Unset")) : null))),
38
40
  isMultibandColor ? null : (React.createElement("div", { className: "jp-gis-symbology-row", style: { gap: '0.5rem' } },
39
41
  React.createElement("div", { style: {
@@ -1,6 +1,5 @@
1
1
  import { showErrorMessage } from '@jupyterlab/apputils';
2
2
  import { BaseForm } from './baseform';
3
- import { FileSelectorWidget } from './fileselectorwidget';
4
3
  import { getMimeType } from '../../tools';
5
4
  /**
6
5
  * The form to modify a GeoTiff source.
@@ -13,22 +12,10 @@ export class GeoTiffSourcePropertiesForm extends BaseForm {
13
12
  this._validateUrls((_b = (_a = props.sourceData) === null || _a === void 0 ? void 0 : _a.urls) !== null && _b !== void 0 ? _b : []);
14
13
  }
15
14
  processSchema(data, schema, uiSchema) {
16
- var _a;
17
15
  super.processSchema(data, schema, uiSchema);
18
16
  if (!schema.properties || !data) {
19
17
  return;
20
18
  }
21
- // Customize the widget for urls
22
- if (schema.properties && schema.properties.urls) {
23
- const docManager = (_a = this.props.formChangedSignal) === null || _a === void 0 ? void 0 : _a.sender.props.formSchemaRegistry.getDocManager();
24
- uiSchema.urls = Object.assign(Object.assign({}, uiSchema.urls), { items: Object.assign(Object.assign({}, uiSchema.urls.items), { url: {
25
- 'ui:widget': FileSelectorWidget,
26
- 'ui:options': {
27
- docManager,
28
- formOptions: this.props
29
- }
30
- } }) });
31
- }
32
19
  // This is not user-editable
33
20
  delete schema.properties.valid;
34
21
  }
@@ -42,7 +42,7 @@ export declare class MainView extends React.Component<IProps, IStates> {
42
42
  * @param id - the source id.
43
43
  * @param source - the source object.
44
44
  */
45
- addSource(id: string, source: IJGISSource, layerId?: string): Promise<void>;
45
+ addSource(id: string, source: IJGISSource): Promise<void>;
46
46
  private computeSourceUrl;
47
47
  /**
48
48
  * Update a source in the map.
@@ -479,7 +479,7 @@ export class MainView extends React.Component {
479
479
  parameters: { path: event.file.name }
480
480
  };
481
481
  const layerId = UUID.uuid4();
482
- this.addSource(sourceId, sourceModel, layerId);
482
+ this.addSource(sourceId, sourceModel);
483
483
  this._model.sharedModel.addSource(sourceId, sourceModel);
484
484
  const layerModel = {
485
485
  type: 'VectorLayer',
@@ -573,8 +573,11 @@ export class MainView extends React.Component {
573
573
  * @param id - the source id.
574
574
  * @param source - the source object.
575
575
  */
576
- async addSource(id, source, layerId) {
576
+ async addSource(id, source) {
577
577
  var _a, _b;
578
+ const rasterSourceCommon = {
579
+ interpolate: false
580
+ };
578
581
  let newSource;
579
582
  switch (source.type) {
580
583
  case 'RasterSource': {
@@ -582,29 +585,16 @@ export class MainView extends React.Component {
582
585
  const pmTiles = sourceParameters.url.endsWith('.pmtiles');
583
586
  const url = this.computeSourceUrl(source);
584
587
  if (!pmTiles) {
585
- newSource = new XYZSource({
586
- attributions: sourceParameters.attribution,
587
- minZoom: sourceParameters.minZoom,
588
- maxZoom: sourceParameters.maxZoom,
589
- tileSize: 256,
590
- url: url
591
- });
588
+ newSource = new XYZSource(Object.assign(Object.assign({}, rasterSourceCommon), { attributions: sourceParameters.attribution, minZoom: sourceParameters.minZoom, maxZoom: sourceParameters.maxZoom, tileSize: 256, url: url }));
592
589
  }
593
590
  else {
594
- newSource = new PMTilesRasterSource({
595
- attributions: sourceParameters.attribution,
596
- tileSize: 256,
597
- url: url
598
- });
591
+ newSource = new PMTilesRasterSource(Object.assign(Object.assign({}, rasterSourceCommon), { attributions: sourceParameters.attribution, tileSize: 256, url: url }));
599
592
  }
600
593
  break;
601
594
  }
602
595
  case 'RasterDemSource': {
603
596
  const sourceParameters = source.parameters;
604
- newSource = new ImageTileSource({
605
- url: this.computeSourceUrl(source),
606
- attributions: sourceParameters.attribution
607
- });
597
+ newSource = new ImageTileSource(Object.assign(Object.assign({}, rasterSourceCommon), { url: this.computeSourceUrl(source), attributions: sourceParameters.attribution }));
608
598
  break;
609
599
  }
610
600
  case 'VectorTileSource': {
@@ -691,12 +681,7 @@ export class MainView extends React.Component {
691
681
  type: 'ImageSource',
692
682
  model: this._model
693
683
  });
694
- newSource = new Static({
695
- imageExtent: extent,
696
- url: imageUrl,
697
- interpolate: false,
698
- crossOrigin: ''
699
- });
684
+ newSource = new Static(Object.assign(Object.assign({}, rasterSourceCommon), { imageExtent: extent, url: imageUrl, crossOrigin: '' }));
700
685
  break;
701
686
  }
702
687
  case 'VideoSource': {
@@ -708,20 +693,10 @@ export class MainView extends React.Component {
708
693
  const addNoData = (url) => {
709
694
  return Object.assign(Object.assign({}, url), { nodata: 0 });
710
695
  };
711
- const sourcesWithBlobs = await Promise.all(sourceParameters.urls.map(async (sourceInfo) => {
712
- var _a;
713
- const geotiff = await loadFile({
714
- filepath: (_a = sourceInfo.url) !== null && _a !== void 0 ? _a : '',
715
- type: 'GeoTiffSource',
716
- model: this._model
717
- });
718
- return Object.assign(Object.assign({}, addNoData(sourceInfo)), { geotiff, url: URL.createObjectURL(geotiff.file) });
696
+ const sources = await Promise.all(sourceParameters.urls.map(async (sourceInfo) => {
697
+ return Object.assign(Object.assign({}, addNoData(sourceInfo)), { min: sourceInfo.min, max: sourceInfo.max, url: sourceInfo.url });
719
698
  }));
720
- newSource = new GeoTIFFSource({
721
- sources: sourcesWithBlobs,
722
- normalize: sourceParameters.normalize,
723
- wrapX: sourceParameters.wrapX
724
- });
699
+ newSource = new GeoTIFFSource(Object.assign(Object.assign({}, rasterSourceCommon), { sources, normalize: sourceParameters.normalize, wrapX: sourceParameters.wrapX }));
725
700
  break;
726
701
  }
727
702
  }
@@ -762,7 +737,7 @@ export class MainView extends React.Component {
762
737
  // remove source being updated
763
738
  this.removeSource(id);
764
739
  // create updated source
765
- await this.addSource(id, source, layerId);
740
+ await this.addSource(id, source);
766
741
  // change source of target layer
767
742
  mapLayer.setSource(this._sources[id]);
768
743
  }
@@ -840,7 +815,7 @@ export class MainView extends React.Component {
840
815
  this.setState(old => (Object.assign(Object.assign({}, old), { loadingLayer: true })));
841
816
  this._loadingLayers.add(id);
842
817
  if (!this._sources[sourceId]) {
843
- await this.addSource(sourceId, source, id);
818
+ await this.addSource(sourceId, source);
844
819
  }
845
820
  this._loadingLayers.add(id);
846
821
  let newMapLayer;
@@ -1004,7 +979,7 @@ export class MainView extends React.Component {
1004
979
  return;
1005
980
  }
1006
981
  if (!this._sources[sourceId]) {
1007
- await this.addSource(sourceId, source, id);
982
+ await this.addSource(sourceId, source);
1008
983
  }
1009
984
  mapLayer.setVisible(layer.visible);
1010
985
  switch (layer.type) {
@@ -219,10 +219,10 @@ function LayerComponent(props) {
219
219
  };
220
220
  return (React.createElement("div", { className: `${LAYER_ITEM_CLASS} ${LAYER_CLASS}${selected ? ' jp-mod-selected' : ''}`, draggable: true, onDragStart: Private.onDragStart, onDragOver: Private.onDragOver, onDragEnd: Private.onDragEnd, "data-id": layerId },
221
221
  React.createElement("div", { className: LAYER_TITLE_CLASS, onClick: setSelection, onContextMenu: setSelection },
222
+ React.createElement(Button, { title: layer.visible ? 'Hide layer' : 'Show layer', onClick: toggleVisibility, minimal: true },
223
+ React.createElement(LabIcon.resolveReact, { icon: layer.visible ? visibilityIcon : nonVisibilityIcon, className: `${LAYER_ICON_CLASS}${layer.visible ? '' : ' jp-gis-mod-hidden'}`, tag: "span" })),
222
224
  icons.has(layer.type) && (React.createElement(LabIcon.resolveReact, Object.assign({}, icons.get(layer.type), { className: LAYER_ICON_CLASS }))),
223
- React.createElement("span", { id: id, className: LAYER_TEXT_CLASS }, name)),
224
- React.createElement(Button, { title: layer.visible ? 'Hide layer' : 'Show layer', onClick: toggleVisibility, minimal: true },
225
- React.createElement(LabIcon.resolveReact, { icon: layer.visible ? visibilityIcon : nonVisibilityIcon, className: `${LAYER_ICON_CLASS}${layer.visible ? '' : ' jp-gis-mod-hidden'}`, tag: "span" }))));
225
+ React.createElement("span", { id: id, className: LAYER_TEXT_CLASS }, name))));
226
226
  }
227
227
  var Private;
228
228
  (function (Private) {
package/lib/tools.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { VectorTile } from '@mapbox/vector-tile';
2
- import { Contents } from '@jupyterlab/services';
3
2
  import { IDict, IJGISLayerBrowserRegistry, IJGISOptions, IJGISSource, IJupyterGISModel } from '@jupytergis/schema';
4
3
  export declare const debounce: (func: CallableFunction, timeout?: number) => CallableFunction;
5
4
  export declare function throttle<T extends (...args: any[]) => void>(callback: T, delay?: number): T;
@@ -57,19 +56,6 @@ export declare const getFromIndexedDB: (key: string) => Promise<{
57
56
  file: any;
58
57
  metadata?: any | undefined;
59
58
  } | undefined>;
60
- /**
61
- * Load a GeoTIFF file from IndexedDB database cache or fetch it .
62
- *
63
- * @param sourceInfo object containing the URL of the GeoTIFF file.
64
- * @returns A promise that resolves to the file as a Blob, or undefined .
65
- */
66
- export declare const loadGeoTiff: (sourceInfo: {
67
- url?: string | undefined;
68
- }, file?: Contents.IModel | null) => Promise<{
69
- file: any;
70
- metadata: any;
71
- sourceUrl: string;
72
- } | null>;
73
59
  /**
74
60
  * Generalized file reader for different source types.
75
61
  *
package/lib/tools.js CHANGED
@@ -6,7 +6,6 @@ import { showErrorMessage } from '@jupyterlab/apputils';
6
6
  import * as d3Color from 'd3-color';
7
7
  import shp from 'shpjs';
8
8
  import RASTER_LAYER_GALLERY from '../rasterlayer_gallery/raster_layer_gallery.json';
9
- import { getGdal } from './gdal';
10
9
  export const debounce = (func, timeout = 100) => {
11
10
  let timeoutId;
12
11
  return (...args) => {
@@ -301,51 +300,26 @@ export const getFromIndexedDB = async (key) => {
301
300
  request.onerror = () => reject(request.error);
302
301
  });
303
302
  };
304
- /**
305
- * Load a GeoTIFF file from IndexedDB database cache or fetch it .
306
- *
307
- * @param sourceInfo object containing the URL of the GeoTIFF file.
308
- * @returns A promise that resolves to the file as a Blob, or undefined .
309
- */
310
- export const loadGeoTiff = async (sourceInfo, file) => {
311
- if (!(sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url)) {
312
- return null;
313
- }
314
- const mimeType = getMimeType(sourceInfo.url);
315
- if (!mimeType || !mimeType.startsWith('image/tiff')) {
316
- throw new Error('Invalid file type. Expected GeoTIFF (image/tiff).');
317
- }
318
- const cachedData = await getFromIndexedDB(sourceInfo.url);
319
- if (cachedData) {
320
- return {
321
- file: cachedData.file,
322
- metadata: cachedData.metadata,
323
- sourceUrl: sourceInfo.url
324
- };
325
- }
326
- let fileBlob;
327
- if (!file) {
328
- const response = await fetch(`/jupytergis_core/proxy?url=${sourceInfo.url}`);
329
- if (!response.ok) {
330
- throw new Error(`Failed to fetch file. Status: ${response.status}`);
303
+ const fetchWithProxies = async (url, parseResponse) => {
304
+ const proxyUrls = [
305
+ url, // Direct fetch
306
+ `/jupytergis_core/proxy?url=${encodeURIComponent(url)}`, // Internal proxy
307
+ `https://corsproxy.io/?url=${encodeURIComponent(url)}` // External proxy
308
+ ];
309
+ for (const proxyUrl of proxyUrls) {
310
+ try {
311
+ const response = await fetch(proxyUrl);
312
+ if (!response.ok) {
313
+ console.warn(`Failed to fetch from ${proxyUrl}: ${response.statusText}`);
314
+ continue;
315
+ }
316
+ return await parseResponse(response);
317
+ }
318
+ catch (error) {
319
+ console.warn(`Error fetching from ${proxyUrl}:`, error);
331
320
  }
332
- fileBlob = await response.blob();
333
- }
334
- else {
335
- fileBlob = await base64ToBlob(file.content, mimeType);
336
321
  }
337
- const geotiff = new File([fileBlob], 'loaded.tif');
338
- const Gdal = await getGdal();
339
- const result = await Gdal.open(geotiff);
340
- const tifDataset = result.datasets[0];
341
- const metadata = await Gdal.gdalinfo(tifDataset, ['-stats']);
342
- Gdal.close(tifDataset);
343
- await saveToIndexedDB(sourceInfo.url, fileBlob, metadata);
344
- return {
345
- file: fileBlob,
346
- metadata,
347
- sourceUrl: sourceInfo.url
348
- };
322
+ return null;
349
323
  };
350
324
  /**
351
325
  * Generalized file reader for different source types.
@@ -381,70 +355,29 @@ export const loadFile = async (fileInfo) => {
381
355
  if (cached) {
382
356
  return cached.file;
383
357
  }
384
- // First trying a direct fetch
385
- try {
386
- const response = await fetch(filepath);
358
+ const geojson = await fetchWithProxies(filepath, async (response) => {
387
359
  const arrayBuffer = await response.arrayBuffer();
388
- const geojson = await shp(arrayBuffer);
360
+ return shp(arrayBuffer);
361
+ });
362
+ if (geojson) {
389
363
  await saveToIndexedDB(filepath, geojson);
390
364
  return geojson;
391
365
  }
392
- catch (error) {
393
- console.warn('Cannot load shapefile from ${filepath}: ${error}');
394
- }
395
- // Trying through our proxy server
396
- try {
397
- const response = await fetch(`/jupytergis_core/proxy?url=${filepath}`);
398
- const arrayBuffer = await response.arrayBuffer();
399
- const geojson = await shp(arrayBuffer);
400
- await saveToIndexedDB(filepath, geojson);
401
- return geojson;
402
- }
403
- catch (error) {
404
- console.warn('Cannot communicate with the JupyterGIS proxy server:', error);
405
- }
406
- // Trying through an external proxy server
407
- try {
408
- const response = await fetch(`https://corsproxy.io/?url=${filepath}`);
409
- const arrayBuffer = await response.arrayBuffer();
410
- const geojson = await shp(arrayBuffer);
411
- await saveToIndexedDB(filepath, geojson);
412
- return geojson;
413
- }
414
- catch (error) {
415
- console.warn('Cannot communicate with external proxy server', error);
416
- }
417
- showErrorMessage('Network error', 'Failed to fetch ${filepath}');
418
- throw new Error('Failed to fetch ${filepath}');
366
+ showErrorMessage('Network error', `Failed to fetch ${filepath}`);
367
+ throw new Error(`Failed to fetch ${filepath}`);
419
368
  }
420
369
  case 'GeoJSONSource': {
421
370
  const cached = await getFromIndexedDB(filepath);
422
371
  if (cached) {
423
372
  return cached.file;
424
373
  }
425
- try {
426
- const response = await fetch(`/jupytergis_core/proxy?url=${filepath}`);
427
- if (!response.ok) {
428
- throw new Error(`Failed to fetch GeoJSON from URL: ${filepath}`);
429
- }
430
- const geojson = await response.json();
374
+ const geojson = await fetchWithProxies(filepath, async (response) => response.json());
375
+ if (geojson) {
431
376
  await saveToIndexedDB(filepath, geojson);
432
377
  return geojson;
433
378
  }
434
- catch (error) {
435
- console.error('Error loading remote GeoJSON:', error);
436
- throw error;
437
- }
438
- }
439
- case 'GeoTiffSource': {
440
- try {
441
- const tiff = loadGeoTiff({ url: filepath });
442
- return tiff;
443
- }
444
- catch (error) {
445
- console.error('Error loading remote GeoTIFF:', error);
446
- throw error;
447
- }
379
+ showErrorMessage('Network error', `Failed to fetch ${filepath}`);
380
+ throw new Error(`Failed to fetch ${filepath}`);
448
381
  }
449
382
  default: {
450
383
  throw new Error(`Unsupported URL handling for source type: ${type}`);
@@ -493,15 +426,6 @@ export const loadFile = async (fileInfo) => {
493
426
  throw new Error('Invalid file format for image content.');
494
427
  }
495
428
  }
496
- case 'GeoTiffSource': {
497
- if (typeof file.content === 'string') {
498
- const tiff = loadGeoTiff({ url: filepath }, file);
499
- return tiff;
500
- }
501
- else {
502
- throw new Error('Invalid file format for tiff content.');
503
- }
504
- }
505
429
  default: {
506
430
  throw new Error(`Unsupported source type: ${type}`);
507
431
  }
package/lib/widget.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { IJupyterGISDocumentWidget, IJupyterGISModel, IJupyterGISOutputWidget } from '@jupytergis/schema';
1
2
  import { MainAreaWidget } from '@jupyterlab/apputils';
2
3
  import { ConsolePanel, IConsoleTracker } from '@jupyterlab/console';
3
4
  import { DocumentWidget } from '@jupyterlab/docregistry';
@@ -5,11 +6,10 @@ import { IObservableMap, ObservableMap } from '@jupyterlab/observables';
5
6
  import { JSONValue } from '@lumino/coreutils';
6
7
  import { ISignal } from '@lumino/signaling';
7
8
  import { SplitPanel } from '@lumino/widgets';
8
- import { IJupyterGISModel, IJupyterGISOutputWidget, IJupyterGISDocumentWidget } from '@jupytergis/schema';
9
+ import { CommandRegistry } from '@lumino/commands';
10
+ import { ConsoleView } from './console';
9
11
  import { JupyterGISMainViewPanel } from './mainview';
10
12
  import { MainViewModel } from './mainview/mainviewmodel';
11
- import { ConsoleView } from './console';
12
- import { CommandRegistry } from '@lumino/commands';
13
13
  export type JupyterGISWidget = JupyterGISDocumentWidget | JupyterGISOutputWidget;
14
14
  export declare class JupyterGISDocumentWidget extends DocumentWidget<JupyterGISPanel, IJupyterGISModel> implements IJupyterGISDocumentWidget {
15
15
  constructor(options: DocumentWidget.IOptions<JupyterGISPanel, IJupyterGISModel>);
package/lib/widget.js CHANGED
@@ -14,10 +14,10 @@ import { DocumentWidget } from '@jupyterlab/docregistry';
14
14
  import { ObservableMap } from '@jupyterlab/observables';
15
15
  import { Signal } from '@lumino/signaling';
16
16
  import { SplitPanel, Widget } from '@lumino/widgets';
17
+ import { MessageLoop } from '@lumino/messaging';
18
+ import { ConsoleView } from './console';
17
19
  import { JupyterGISMainViewPanel } from './mainview';
18
20
  import { MainViewModel } from './mainview/mainviewmodel';
19
- import { ConsoleView } from './console';
20
- import { MessageLoop } from '@lumino/messaging';
21
21
  const CELL_OUTPUT_WIDGET_CLASS = 'jgis-cell-output-widget';
22
22
  export class JupyterGISDocumentWidget extends DocumentWidget {
23
23
  constructor(options) {
@@ -71,7 +71,7 @@ export class JupyterGISPanel extends SplitPanel {
71
71
  const { model, consoleTracker, commandRegistry } = options, consoleOption = __rest(options, ["model", "consoleTracker", "commandRegistry"]);
72
72
  this._initModel({ model, commandRegistry });
73
73
  this._initView();
74
- this._consoleOption = consoleOption;
74
+ this._consoleOption = Object.assign({ commandRegistry }, consoleOption);
75
75
  this._consoleTracker = consoleTracker;
76
76
  }
77
77
  _initModel(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupytergis/base",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "A JupyterLab extension for 3D modelling.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -43,7 +43,7 @@
43
43
  "@fortawesome/react-fontawesome": "latest",
44
44
  "@jupyter/react-components": "^0.16.6",
45
45
  "@jupyter/ydoc": "^2.0.0 || ^3.0.0",
46
- "@jupytergis/schema": "^0.4.0",
46
+ "@jupytergis/schema": "^0.4.2",
47
47
  "@jupyterlab/application": "^4.3.0",
48
48
  "@jupyterlab/apputils": "^4.3.0",
49
49
  "@jupyterlab/completer": "^4.3.0",
@@ -75,7 +75,6 @@
75
75
 
76
76
  .jp-gis-layer button,
77
77
  .jp-gis-source button {
78
- margin-left: auto;
79
78
  min-height: unset;
80
79
  min-width: unset;
81
80
  padding: unset;