@jupytergis/base 0.4.5 → 0.5.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.
package/lib/commands.js CHANGED
@@ -164,21 +164,21 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
164
164
  /**
165
165
  * Source and layers
166
166
  */
167
- commands.addCommand(CommandIDs.newRasterEntry, Object.assign({ label: trans.__('New Raster Layer'), isEnabled: () => {
167
+ commands.addCommand(CommandIDs.newRasterEntry, Object.assign({ label: trans.__('New Raster Tile Layer'), isEnabled: () => {
168
168
  return tracker.currentWidget
169
169
  ? tracker.currentWidget.model.sharedModel.editable
170
170
  : false;
171
171
  }, execute: Private.createEntry({
172
172
  tracker,
173
173
  formSchemaRegistry,
174
- title: 'Create Raster Layer',
174
+ title: 'Create Raster Tile Layer',
175
175
  createLayer: true,
176
176
  createSource: true,
177
177
  sourceData: {
178
178
  minZoom: 0,
179
179
  maxZoom: 24
180
180
  },
181
- layerData: { name: 'Custom Raster Layer' },
181
+ layerData: { name: 'Custom Raster Tile Layer' },
182
182
  sourceType: 'RasterSource',
183
183
  layerType: 'RasterLayer'
184
184
  }) }, icons.get(CommandIDs.newRasterEntry)));
@@ -321,21 +321,6 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
321
321
  sourceType: 'VideoSource',
322
322
  layerType: 'RasterLayer'
323
323
  }) }, icons.get(CommandIDs.newVideoEntry)));
324
- commands.addCommand(CommandIDs.newShapefileSource, Object.assign({ label: args => args.from === 'contextMenu'
325
- ? trans.__('Shapefile')
326
- : trans.__('Add Shapefile Source'), isEnabled: () => {
327
- return tracker.currentWidget
328
- ? tracker.currentWidget.model.sharedModel.editable
329
- : false;
330
- }, execute: Private.createEntry({
331
- tracker,
332
- formSchemaRegistry,
333
- title: 'Create Shapefile Source',
334
- createLayer: false,
335
- createSource: true,
336
- sourceData: { name: 'Custom Shapefile Source' },
337
- sourceType: 'ShapefileSource'
338
- }) }, icons.get(CommandIDs.newShapefileSource)));
339
324
  commands.addCommand(CommandIDs.newGeoTiffEntry, Object.assign({ label: trans.__('New GeoTiff layer'), isEnabled: () => {
340
325
  return tracker.currentWidget
341
326
  ? tracker.currentWidget.model.sharedModel.editable
@@ -354,191 +339,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
354
339
  sourceType: 'GeoTiffSource',
355
340
  layerType: 'WebGlLayer'
356
341
  }) }, icons.get(CommandIDs.newGeoTiffEntry)));
357
- /**
358
- * SOURCES only commands.
359
- */
360
- commands.addCommand(CommandIDs.newRasterSource, Object.assign({ label: args => args.from === 'contextMenu'
361
- ? trans.__('Raster')
362
- : trans.__('New Raster Source'), isEnabled: () => {
363
- return tracker.currentWidget
364
- ? tracker.currentWidget.model.sharedModel.editable
365
- : false;
366
- }, execute: Private.createEntry({
367
- tracker,
368
- formSchemaRegistry,
369
- title: 'Create Raster Source',
370
- createLayer: false,
371
- createSource: true,
372
- sourceData: { name: 'Custom Raster Source', minZoom: 0, maxZoom: 24 },
373
- sourceType: 'RasterSource'
374
- }) }, icons.get(CommandIDs.newRasterSource)));
375
- commands.addCommand(CommandIDs.newRasterDemSource, Object.assign({ label: args => args.from === 'contextMenu'
376
- ? trans.__('Raster DEM')
377
- : trans.__('New Raster DEM Source'), isEnabled: () => {
378
- return tracker.currentWidget
379
- ? tracker.currentWidget.model.sharedModel.editable
380
- : false;
381
- }, execute: Private.createEntry({
382
- tracker,
383
- formSchemaRegistry,
384
- title: 'Create Raster Dem Source',
385
- createLayer: false,
386
- createSource: true,
387
- sourceData: { name: 'Custom Raster DEM Source' },
388
- sourceType: 'RasterDemSource'
389
- }) }, icons.get(CommandIDs.newRasterDemSource)));
390
- commands.addCommand(CommandIDs.newVectorSource, Object.assign({ label: args => args.from === 'contextMenu'
391
- ? trans.__('Vector')
392
- : trans.__('New Vector Source'), isEnabled: () => {
393
- return tracker.currentWidget
394
- ? tracker.currentWidget.model.sharedModel.editable
395
- : false;
396
- }, execute: Private.createEntry({
397
- tracker,
398
- formSchemaRegistry,
399
- title: 'Create Vector Source',
400
- createLayer: false,
401
- createSource: true,
402
- sourceData: { name: 'Custom Vector Source', minZoom: 0, maxZoom: 24 },
403
- sourceType: 'VectorTileSource'
404
- }) }, icons.get(CommandIDs.newVectorSource)));
405
- commands.addCommand(CommandIDs.newGeoJSONSource, Object.assign({ label: args => args.from === 'contextMenu'
406
- ? trans.__('GeoJSON')
407
- : trans.__('Add GeoJSON data from file'), isEnabled: () => {
408
- return tracker.currentWidget
409
- ? tracker.currentWidget.model.sharedModel.editable
410
- : false;
411
- }, execute: Private.createEntry({
412
- tracker,
413
- formSchemaRegistry,
414
- title: 'Create GeoJson Source',
415
- createLayer: false,
416
- createSource: true,
417
- sourceData: { name: 'Custom GeoJSON Source' },
418
- sourceType: 'GeoJSONSource'
419
- }) }, icons.get(CommandIDs.newGeoJSONSource)));
420
- commands.addCommand(CommandIDs.newImageSource, Object.assign({ label: args => args.from === 'contextMenu'
421
- ? trans.__('Image')
422
- : trans.__('Add Image Source'), isEnabled: () => {
423
- return tracker.currentWidget
424
- ? tracker.currentWidget.model.sharedModel.editable
425
- : false;
426
- }, execute: Private.createEntry({
427
- tracker,
428
- formSchemaRegistry,
429
- title: 'Create Image Source',
430
- createLayer: false,
431
- createSource: true,
432
- sourceData: { name: 'Custom Image Source' },
433
- sourceType: 'ImageSource'
434
- }) }, icons.get(CommandIDs.newImageSource)));
435
- commands.addCommand(CommandIDs.newVideoSource, Object.assign({ label: args => args.from === 'contextMenu'
436
- ? trans.__('Video')
437
- : trans.__('Add Video Source'), isEnabled: () => {
438
- return tracker.currentWidget
439
- ? tracker.currentWidget.model.sharedModel.editable
440
- : false;
441
- }, execute: Private.createEntry({
442
- tracker,
443
- formSchemaRegistry,
444
- title: 'Create Video Source',
445
- createLayer: false,
446
- createSource: true,
447
- sourceData: { name: 'Custom Video Source' },
448
- sourceType: 'VideoSource'
449
- }) }, icons.get(CommandIDs.newVideoSource)));
450
- // Layers only
451
- commands.addCommand(CommandIDs.newRasterLayer, Object.assign({ label: args => args.from === 'contextMenu'
452
- ? trans.__('Raster')
453
- : trans.__('Add Raster layer'), isEnabled: () => {
454
- return tracker.currentWidget
455
- ? tracker.currentWidget.model.sharedModel.editable
456
- : false;
457
- }, execute: Private.createEntry({
458
- tracker,
459
- formSchemaRegistry,
460
- title: 'Create Raster Layer',
461
- createLayer: true,
462
- createSource: false,
463
- layerData: {
464
- name: 'Custom Raster Layer'
465
- },
466
- sourceType: 'RasterSource',
467
- layerType: 'RasterLayer'
468
- }) }, icons.get(CommandIDs.newVectorLayer)));
469
- commands.addCommand(CommandIDs.newVectorLayer, Object.assign({ label: args => args.from === 'contextMenu'
470
- ? trans.__('Vector')
471
- : trans.__('Add New Vector layer'), isEnabled: () => {
472
- return tracker.currentWidget
473
- ? tracker.currentWidget.model.sharedModel.editable
474
- : false;
475
- }, execute: Private.createEntry({
476
- tracker,
477
- formSchemaRegistry,
478
- title: 'Create Vector Layer',
479
- createLayer: true,
480
- createSource: false,
481
- layerData: {
482
- name: 'Custom Vector Layer'
483
- },
484
- sourceType: 'VectorTileSource',
485
- layerType: 'VectorTileLayer'
486
- }) }, icons.get(CommandIDs.newVectorLayer)));
487
- commands.addCommand(CommandIDs.newHillshadeLayer, Object.assign({ label: args => args.from === 'contextMenu'
488
- ? trans.__('Hillshade')
489
- : trans.__('Add Hillshade layer'), isEnabled: () => {
490
- return tracker.currentWidget
491
- ? tracker.currentWidget.model.sharedModel.editable
492
- : false;
493
- }, execute: Private.createEntry({
494
- tracker,
495
- formSchemaRegistry,
496
- title: 'Create Hillshade Layer',
497
- createLayer: true,
498
- createSource: false,
499
- layerData: {
500
- name: 'Custom Hillshade Layer'
501
- },
502
- sourceType: 'RasterDemSource',
503
- layerType: 'HillshadeLayer'
504
- }) }, icons.get(CommandIDs.newHillshadeLayer)));
505
- commands.addCommand(CommandIDs.newImageLayer, Object.assign({ label: args => args.from === 'contextMenu'
506
- ? trans.__('Image')
507
- : trans.__('Add Image layer'), isEnabled: () => {
508
- return tracker.currentWidget
509
- ? tracker.currentWidget.model.sharedModel.editable
510
- : false;
511
- }, execute: Private.createEntry({
512
- tracker,
513
- formSchemaRegistry,
514
- title: 'Create Image Layer',
515
- createLayer: true,
516
- createSource: false,
517
- layerData: {
518
- name: 'Custom Image Layer'
519
- },
520
- sourceType: 'ImageSource',
521
- layerType: 'RasterLayer'
522
- }) }, icons.get(CommandIDs.newImageLayer)));
523
- commands.addCommand(CommandIDs.newVideoLayer, Object.assign({ label: args => args.from === 'contextMenu'
524
- ? trans.__('Video')
525
- : trans.__('Add Video layer'), isEnabled: () => {
526
- return tracker.currentWidget
527
- ? tracker.currentWidget.model.sharedModel.editable
528
- : false;
529
- }, execute: Private.createEntry({
530
- tracker,
531
- formSchemaRegistry,
532
- title: 'Create Video Layer',
533
- createLayer: true,
534
- createSource: false,
535
- layerData: {
536
- name: 'Custom Video Layer'
537
- },
538
- sourceType: 'VideoSource',
539
- layerType: 'RasterLayer'
540
- }) }, icons.get(CommandIDs.newVideoLayer)));
541
- commands.addCommand(CommandIDs.newShapefileLayer, Object.assign({ label: trans.__('New Shapefile Layer'), isEnabled: () => {
342
+ commands.addCommand(CommandIDs.newShapefileEntry, Object.assign({ label: trans.__('New Shapefile Layer'), isEnabled: () => {
542
343
  return tracker.currentWidget
543
344
  ? tracker.currentWidget.model.sharedModel.editable
544
345
  : false;
@@ -552,23 +353,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
552
353
  layerData: { name: 'Custom Shapefile Layer' },
553
354
  sourceType: 'ShapefileSource',
554
355
  layerType: 'VectorLayer'
555
- }) }, icons.get(CommandIDs.newShapefileLayer)));
556
- commands.addCommand(CommandIDs.newHeatmapLayer, Object.assign({ label: args => args.from === 'contextMenu'
557
- ? trans.__('Heatmap')
558
- : trans.__('Add HeatmapLayer'), isEnabled: () => {
559
- return tracker.currentWidget
560
- ? tracker.currentWidget.model.sharedModel.editable
561
- : false;
562
- }, execute: Private.createEntry({
563
- tracker,
564
- formSchemaRegistry,
565
- title: 'Create Heatmap Layer',
566
- createLayer: true,
567
- createSource: false,
568
- layerData: { name: 'Custom Heatmap Layer' },
569
- sourceType: 'GeoJSONSource',
570
- layerType: 'HeatmapLayer'
571
- }) }, icons.get(CommandIDs.newHeatmapLayer)));
356
+ }) }, icons.get(CommandIDs.newShapefileEntry)));
572
357
  /**
573
358
  * LAYERS and LAYER GROUP actions.
574
359
  */
@@ -725,7 +510,19 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
725
510
  ? tracker.currentWidget.model.sharedModel.editable
726
511
  : false;
727
512
  },
728
- execute: async () => await Private.toggleConsole(tracker)
513
+ isToggled: () => {
514
+ var _a;
515
+ if (tracker.currentWidget instanceof JupyterGISDocumentWidget) {
516
+ return ((_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content.consoleOpened) === true;
517
+ }
518
+ else {
519
+ return false;
520
+ }
521
+ },
522
+ execute: async () => {
523
+ await Private.toggleConsole(tracker);
524
+ commands.notifyCommandChanged(CommandIDs.toggleConsole);
525
+ }
729
526
  });
730
527
  commands.addCommand(CommandIDs.executeConsole, {
731
528
  label: trans.__('Execute console'),
@@ -13,6 +13,7 @@ export declare namespace CommandIDs {
13
13
  const openLayerBrowser = "jupytergis:openLayerBrowser";
14
14
  const newRasterEntry = "jupytergis:newRasterEntry";
15
15
  const newVectorTileEntry = "jupytergis:newVectorTileEntry";
16
+ const newShapefileEntry = "jupytergis:newShapefileEntry";
16
17
  const newGeoJSONEntry = "jupytergis:newGeoJSONEntry";
17
18
  const newHillshadeEntry = "jupytergis:newHillshadeEntry";
18
19
  const newImageEntry = "jupytergis:newImageEntry";
@@ -20,22 +21,6 @@ export declare namespace CommandIDs {
20
21
  const newGeoTiffEntry = "jupytergis:newGeoTiffEntry";
21
22
  const buffer = "jupytergis:buffer";
22
23
  const dissolve = "jupytergis:dissolve";
23
- const newRasterSource = "jupytergis:newRasterSource";
24
- const newRasterDemSource = "jupytergis:newRasterDemSource";
25
- const newVectorSource = "jupytergis:newVectorSource";
26
- const newGeoJSONSource = "jupytergis:newGeoJSONSource";
27
- const newImageSource = "jupytergis:imageSource";
28
- const newVideoSource = "jupytergis:videoSource";
29
- const newShapefileSource = "jupytergis:shapefileSource";
30
- const newGeoTiffSource = "jupytergis:newGeoTiffSource";
31
- const newRasterLayer = "jupytergis:newRasterLayer";
32
- const newVectorLayer = "jupytergis:newVectorLayer";
33
- const newHillshadeLayer = "jupytergis:newHillshadeLayer";
34
- const newImageLayer = "jupytergis:newImageLayer";
35
- const newVideoLayer = "jupytergis:newVideoLayer";
36
- const newShapefileLayer = "jupytergis:newShapefileLayer";
37
- const newWebGlTileLayer = "jupytergis:newWebGlTileLayer";
38
- const newHeatmapLayer = "jupytergis:newHeatmapLayer";
39
24
  const renameLayer = "jupytergis:renameLayer";
40
25
  const removeLayer = "jupytergis:removeLayer";
41
26
  const renameGroup = "jupytergis:renameGroup";
package/lib/constants.js CHANGED
@@ -18,6 +18,7 @@ export var CommandIDs;
18
18
  // Layer and source
19
19
  CommandIDs.newRasterEntry = 'jupytergis:newRasterEntry';
20
20
  CommandIDs.newVectorTileEntry = 'jupytergis:newVectorTileEntry';
21
+ CommandIDs.newShapefileEntry = 'jupytergis:newShapefileEntry';
21
22
  CommandIDs.newGeoJSONEntry = 'jupytergis:newGeoJSONEntry';
22
23
  CommandIDs.newHillshadeEntry = 'jupytergis:newHillshadeEntry';
23
24
  CommandIDs.newImageEntry = 'jupytergis:newImageEntry';
@@ -26,24 +27,6 @@ export var CommandIDs;
26
27
  // Processing commands
27
28
  CommandIDs.buffer = 'jupytergis:buffer';
28
29
  CommandIDs.dissolve = 'jupytergis:dissolve';
29
- // Sources only commands
30
- CommandIDs.newRasterSource = 'jupytergis:newRasterSource';
31
- CommandIDs.newRasterDemSource = 'jupytergis:newRasterDemSource';
32
- CommandIDs.newVectorSource = 'jupytergis:newVectorSource';
33
- CommandIDs.newGeoJSONSource = 'jupytergis:newGeoJSONSource';
34
- CommandIDs.newImageSource = 'jupytergis:imageSource';
35
- CommandIDs.newVideoSource = 'jupytergis:videoSource';
36
- CommandIDs.newShapefileSource = 'jupytergis:shapefileSource';
37
- CommandIDs.newGeoTiffSource = 'jupytergis:newGeoTiffSource';
38
- // Layers only commands
39
- CommandIDs.newRasterLayer = 'jupytergis:newRasterLayer';
40
- CommandIDs.newVectorLayer = 'jupytergis:newVectorLayer';
41
- CommandIDs.newHillshadeLayer = 'jupytergis:newHillshadeLayer';
42
- CommandIDs.newImageLayer = 'jupytergis:newImageLayer';
43
- CommandIDs.newVideoLayer = 'jupytergis:newVideoLayer';
44
- CommandIDs.newShapefileLayer = 'jupytergis:newShapefileLayer';
45
- CommandIDs.newWebGlTileLayer = 'jupytergis:newWebGlTileLayer';
46
- CommandIDs.newHeatmapLayer = 'jupytergis:newHeatmapLayer';
47
30
  // Layer and group actions
48
31
  CommandIDs.renameLayer = 'jupytergis:renameLayer';
49
32
  CommandIDs.removeLayer = 'jupytergis:removeLayer';
@@ -87,7 +70,7 @@ const iconObject = {
87
70
  [CommandIDs.newHillshadeEntry]: { icon: moundIcon },
88
71
  [CommandIDs.newImageEntry]: { iconClass: 'fa fa-image' },
89
72
  [CommandIDs.newVideoEntry]: { iconClass: 'fa fa-video' },
90
- [CommandIDs.newShapefileLayer]: { iconClass: 'fa fa-file' },
73
+ [CommandIDs.newShapefileEntry]: { iconClass: 'fa fa-file' },
91
74
  [CommandIDs.newGeoTiffEntry]: { iconClass: 'fa fa-image' },
92
75
  [CommandIDs.symbology]: { iconClass: 'fa fa-brush' },
93
76
  [CommandIDs.identify]: { icon: infoIcon },
package/lib/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export * from './tools';
12
12
  export * from './types';
13
13
  export * from './widget';
14
14
  export * from './annotations';
15
+ export * from './menus';
package/lib/index.js CHANGED
@@ -12,3 +12,4 @@ export * from './tools';
12
12
  export * from './types';
13
13
  export * from './widget';
14
14
  export * from './annotations';
15
+ export * from './menus';
package/lib/menus.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Menu } from '@lumino/widgets';
2
+ import { CommandRegistry } from '@lumino/commands';
3
+ export declare const vectorSubMenu: (commands: CommandRegistry) => Menu;
4
+ export declare const rasterSubMenu: (commands: CommandRegistry) => Menu;
package/lib/menus.js ADDED
@@ -0,0 +1,45 @@
1
+ import { Menu } from '@lumino/widgets';
2
+ import { CommandIDs } from './constants';
3
+ import { rasterIcon } from './icons';
4
+ export const vectorSubMenu = (commands) => {
5
+ const subMenu = new Menu({ commands });
6
+ subMenu.title.label = 'Add Vector Layer';
7
+ subMenu.title.iconClass = 'fa fa-vector-square';
8
+ subMenu.id = 'jp-gis-toolbar-vector-menu';
9
+ subMenu.addItem({
10
+ type: 'command',
11
+ command: CommandIDs.newVectorTileEntry
12
+ });
13
+ subMenu.addItem({
14
+ type: 'command',
15
+ command: CommandIDs.newGeoJSONEntry
16
+ });
17
+ subMenu.addItem({
18
+ type: 'command',
19
+ command: CommandIDs.newShapefileEntry
20
+ });
21
+ return subMenu;
22
+ };
23
+ export const rasterSubMenu = (commands) => {
24
+ const subMenu = new Menu({ commands });
25
+ subMenu.title.label = 'Add Raster Layer';
26
+ subMenu.title.icon = rasterIcon;
27
+ subMenu.id = 'jp-gis-toolbar-raster-menu';
28
+ subMenu.addItem({
29
+ type: 'command',
30
+ command: CommandIDs.newRasterEntry
31
+ });
32
+ subMenu.addItem({
33
+ type: 'command',
34
+ command: CommandIDs.newHillshadeEntry
35
+ });
36
+ subMenu.addItem({
37
+ type: 'command',
38
+ command: CommandIDs.newImageEntry
39
+ });
40
+ subMenu.addItem({
41
+ type: 'command',
42
+ command: CommandIDs.newGeoTiffEntry
43
+ });
44
+ return subMenu;
45
+ };
@@ -1,6 +1,5 @@
1
1
  import { SidePanel } from '@jupyterlab/ui-components';
2
2
  import { LayersPanel } from './components/layers';
3
- import { SourcesPanel } from './components/sources';
4
3
  import { ControlPanelHeader } from './header';
5
4
  import { FilterPanel } from './components/filter-panel/Filter';
6
5
  import { CommandIDs } from '../constants';
@@ -62,13 +61,6 @@ export class LeftPanelWidget extends SidePanel {
62
61
  this._commands = options.commands;
63
62
  const header = new ControlPanelHeader();
64
63
  this.header.addWidget(header);
65
- const sourcesPanel = new SourcesPanel({
66
- model: this._model,
67
- onSelect: this._onSelect
68
- });
69
- sourcesPanel.title.caption = 'Sources';
70
- sourcesPanel.title.label = 'Sources';
71
- this.addWidget(sourcesPanel);
72
64
  const layerTree = new LayersPanel({
73
65
  model: this._model,
74
66
  state: this._state,
@@ -1,9 +1,10 @@
1
1
  import { CommandToolbarButton } from '@jupyterlab/apputils';
2
2
  import { MenuSvg, ReactWidget, ReactiveToolbar, ToolbarButton, addIcon, redoIcon, undoIcon } from '@jupyterlab/ui-components';
3
- import { Menu, Widget } from '@lumino/widgets';
3
+ import { Widget } from '@lumino/widgets';
4
4
  import * as React from 'react';
5
5
  import { CommandIDs } from '../constants';
6
- import { rasterIcon, terminalToolbarIcon } from '../icons';
6
+ import { terminalToolbarIcon } from '../icons';
7
+ import { rasterSubMenu, vectorSubMenu } from '../menus';
7
8
  import { UsersItem } from './usertoolbaritem';
8
9
  export const TOOLBAR_SEPARATOR_CLASS = 'jGIS-Toolbar-Separator';
9
10
  export const TOOLBAR_GROUPNAME_CLASS = 'jGIS-Toolbar-GroupName';
@@ -53,60 +54,16 @@ export class ToolbarWidget extends ReactiveToolbar {
53
54
  });
54
55
  this.addItem('openLayerBrowser', openLayersBrowserButton);
55
56
  openLayersBrowserButton.node.dataset.testid = 'open-layers-browser';
56
- const newRasterEntryButton = new CommandToolbarButton({
57
- id: CommandIDs.newRasterEntry,
58
- label: '',
59
- commands: options.commands
60
- });
61
- this.addItem('newRasterEntry', newRasterEntryButton);
62
- const newVectorTileEntryButton = new CommandToolbarButton({
63
- id: CommandIDs.newVectorTileEntry,
64
- label: '',
65
- commands: options.commands
66
- });
67
- this.addItem('newVectorTileEntry', newVectorTileEntryButton);
68
- newRasterEntryButton.node.dataset.testid = 'new-raster-entry-button';
69
- const geolocationButton = new CommandToolbarButton({
70
- id: CommandIDs.getGeolocation,
71
- commands: options.commands,
72
- label: ''
73
- });
74
- this.addItem('Geolocation', geolocationButton);
75
- geolocationButton.node.dataset.testid = 'geolocation-button';
76
- // vector sub menu
77
- const vectorSubMenu = new Menu({ commands: options.commands });
78
- vectorSubMenu.title.label = 'Add Vector Layer';
79
- vectorSubMenu.title.iconClass = 'fa fa-vector-square';
80
- vectorSubMenu.id = 'jp-gis-toolbar-vector-menu';
81
- vectorSubMenu.addItem({
82
- type: 'command',
83
- command: CommandIDs.newGeoJSONEntry
84
- });
85
- vectorSubMenu.addItem({
86
- type: 'command',
87
- command: CommandIDs.newShapefileLayer
88
- });
89
- //raster submenu
90
- const rasterSubMenu = new Menu({ commands: options.commands });
91
- rasterSubMenu.title.label = 'Add Raster Layer';
92
- rasterSubMenu.title.icon = rasterIcon;
93
- rasterSubMenu.id = 'jp-gis-toolbar-raster-menu';
94
- rasterSubMenu.addItem({
95
- type: 'command',
96
- command: CommandIDs.newHillshadeEntry
97
- });
98
- rasterSubMenu.addItem({
99
- type: 'command',
100
- command: CommandIDs.newImageEntry
101
- });
102
- rasterSubMenu.addItem({
103
- type: 'command',
104
- command: CommandIDs.newGeoTiffEntry
105
- });
106
57
  const NewSubMenu = new MenuSvg({ commands: options.commands });
107
58
  NewSubMenu.title.label = 'Add Layer';
108
- NewSubMenu.addItem({ type: 'submenu', submenu: rasterSubMenu });
109
- NewSubMenu.addItem({ type: 'submenu', submenu: vectorSubMenu });
59
+ NewSubMenu.addItem({
60
+ type: 'submenu',
61
+ submenu: rasterSubMenu(options.commands)
62
+ });
63
+ NewSubMenu.addItem({
64
+ type: 'submenu',
65
+ submenu: vectorSubMenu(options.commands)
66
+ });
110
67
  const NewEntryButton = new ToolbarButton({
111
68
  icon: addIcon,
112
69
  noFocusOnClick: false,
@@ -121,6 +78,13 @@ export class ToolbarWidget extends ReactiveToolbar {
121
78
  NewEntryButton.node.dataset.testid = 'new-entry-button';
122
79
  this.addItem('New', NewEntryButton);
123
80
  this.addItem('separator2', new Separator());
81
+ const geolocationButton = new CommandToolbarButton({
82
+ id: CommandIDs.getGeolocation,
83
+ commands: options.commands,
84
+ label: ''
85
+ });
86
+ this.addItem('Geolocation', geolocationButton);
87
+ geolocationButton.node.dataset.testid = 'geolocation-button';
124
88
  const identifyButton = new CommandToolbarButton({
125
89
  id: CommandIDs.identify,
126
90
  label: '',
package/lib/tools.d.ts CHANGED
@@ -65,7 +65,7 @@ export declare const getFromIndexedDB: (key: string) => Promise<{
65
65
  */
66
66
  export declare const loadGeoTiff: (sourceInfo: {
67
67
  url?: string | undefined;
68
- }, file?: Contents.IModel | null) => Promise<{
68
+ }, model: IJupyterGISModel, file?: Contents.IModel | null) => Promise<{
69
69
  file: any;
70
70
  metadata: any;
71
71
  sourceUrl: string;
package/lib/tools.js CHANGED
@@ -301,11 +301,19 @@ export const getFromIndexedDB = async (key) => {
301
301
  request.onerror = () => reject(request.error);
302
302
  });
303
303
  };
304
- const fetchWithProxies = async (url, parseResponse) => {
304
+ const fetchWithProxies = async (url, model, parseResponse) => {
305
+ let settings = null;
306
+ try {
307
+ settings = await model.getSettings();
308
+ }
309
+ catch (e) {
310
+ console.warn('Failed to get settings from model. Falling back.', e);
311
+ }
312
+ const proxyUrl = settings && settings.proxyUrl ? settings.proxyUrl : 'https://corsproxy.io';
305
313
  const proxyUrls = [
306
314
  url, // Direct fetch
307
315
  `/jupytergis_core/proxy?url=${encodeURIComponent(url)}`, // Internal proxy
308
- `https://corsproxy.io/?url=${encodeURIComponent(url)}` // External proxy
316
+ `${proxyUrl}/?url=${encodeURIComponent(url)}` // External proxy
309
317
  ];
310
318
  for (const proxyUrl of proxyUrls) {
311
319
  try {
@@ -328,7 +336,7 @@ const fetchWithProxies = async (url, parseResponse) => {
328
336
  * @param sourceInfo object containing the URL of the GeoTIFF file.
329
337
  * @returns A promise that resolves to the file as a Blob, or undefined .
330
338
  */
331
- export const loadGeoTiff = async (sourceInfo, file) => {
339
+ export const loadGeoTiff = async (sourceInfo, model, file) => {
332
340
  if (!(sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url)) {
333
341
  return null;
334
342
  }
@@ -347,7 +355,7 @@ export const loadGeoTiff = async (sourceInfo, file) => {
347
355
  }
348
356
  let fileBlob = null;
349
357
  if (!file) {
350
- fileBlob = await fetchWithProxies(url, async (response) => response.blob());
358
+ fileBlob = await fetchWithProxies(url, model, async (response) => response.blob());
351
359
  if (!fileBlob) {
352
360
  showErrorMessage('Network error', `Failed to fetch ${url}`);
353
361
  throw new Error(`Failed to fetch ${url}`);
@@ -403,7 +411,7 @@ export const loadFile = async (fileInfo) => {
403
411
  if (cached) {
404
412
  return cached.file;
405
413
  }
406
- const geojson = await fetchWithProxies(filepath, async (response) => {
414
+ const geojson = await fetchWithProxies(filepath, model, async (response) => {
407
415
  const arrayBuffer = await response.arrayBuffer();
408
416
  return shp(arrayBuffer);
409
417
  });
@@ -419,7 +427,7 @@ export const loadFile = async (fileInfo) => {
419
427
  if (cached) {
420
428
  return cached.file;
421
429
  }
422
- const geojson = await fetchWithProxies(filepath, async (response) => response.json());
430
+ const geojson = await fetchWithProxies(filepath, model, async (response) => response.json());
423
431
  if (geojson) {
424
432
  await saveToIndexedDB(filepath, geojson);
425
433
  return geojson;
@@ -476,7 +484,7 @@ export const loadFile = async (fileInfo) => {
476
484
  }
477
485
  case 'GeoTiffSource': {
478
486
  if (typeof file.content === 'string') {
479
- const tiff = loadGeoTiff({ url: filepath }, file);
487
+ const tiff = loadGeoTiff({ url: filepath }, model, file);
480
488
  return tiff;
481
489
  }
482
490
  else {
package/lib/widget.d.ts CHANGED
@@ -53,6 +53,7 @@ export declare class JupyterGISPanel extends SplitPanel {
53
53
  dispose(): void;
54
54
  get currentViewModel(): MainViewModel;
55
55
  get consolePanel(): ConsolePanel | undefined;
56
+ get consoleOpened(): boolean;
56
57
  executeConsole(): void;
57
58
  removeConsole(): void;
58
59
  toggleConsole(jgisPath: string): Promise<void>;
package/lib/widget.js CHANGED
@@ -116,6 +116,9 @@ export class JupyterGISPanel extends SplitPanel {
116
116
  var _a;
117
117
  return (_a = this._consoleView) === null || _a === void 0 ? void 0 : _a.consolePanel;
118
118
  }
119
+ get consoleOpened() {
120
+ return this._consoleOpened;
121
+ }
119
122
  executeConsole() {
120
123
  if (this._consoleView) {
121
124
  this._consoleView.execute();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupytergis/base",
3
- "version": "0.4.5",
3
+ "version": "0.5.0",
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.5",
46
+ "@jupytergis/schema": "^0.5.0",
47
47
  "@jupyterlab/application": "^4.3.0",
48
48
  "@jupyterlab/apputils": "^4.3.0",
49
49
  "@jupyterlab/completer": "^4.3.0",
@@ -3,7 +3,6 @@
3
3
  | Distributed under the terms of the Modified BSD License.
4
4
  |---------------------------------------------------------------------------- */
5
5
 
6
- .jp-gis-sourcePanel,
7
6
  .jp-gis-layerPanel {
8
7
  min-height: 3em;
9
8
  }
@@ -1,10 +0,0 @@
1
- import { Panel } from '@lumino/widgets';
2
- import { ILeftPanelOptions } from '../leftpanel';
3
- /**
4
- * The sources panel widget.
5
- */
6
- export declare class SourcesPanel extends Panel {
7
- constructor(options: ILeftPanelOptions);
8
- private _model;
9
- private _onSelect;
10
- }
@@ -1,147 +0,0 @@
1
- import { DOMUtils } from '@jupyterlab/apputils';
2
- import { LabIcon, ReactWidget } from '@jupyterlab/ui-components';
3
- import { Panel } from '@lumino/widgets';
4
- import React, { useEffect, useState } from 'react';
5
- import { icons } from '../../constants';
6
- const SOURCES_PANEL_CLASS = 'jp-gis-sourcePanel';
7
- const SOURCE_CLASS = 'jp-gis-source';
8
- const SOURCE_TITLE_CLASS = 'jp-gis-sourceTitle';
9
- const SOURCE_ICON_CLASS = 'jp-gis-sourceIcon';
10
- const SOURCE_TEXT_CLASS = 'jp-gis-sourceText';
11
- const SOURCE_UNUSED = 'jp-gis-sourceUnused';
12
- const SOURCE_INFO = 'jp-gis-sourceInfo';
13
- /**
14
- * The sources panel widget.
15
- */
16
- export class SourcesPanel extends Panel {
17
- constructor(options) {
18
- super();
19
- this._model = options.model;
20
- this._onSelect = options.onSelect;
21
- this.id = 'jupytergis::sourcesPanel';
22
- this.addClass(SOURCES_PANEL_CLASS);
23
- this.addWidget(ReactWidget.create(React.createElement(SourcesBodyComponent, { model: this._model, onSelect: this._onSelect })));
24
- }
25
- }
26
- /**
27
- * The body component of the panel.
28
- */
29
- function SourcesBodyComponent(props) {
30
- var _a, _b;
31
- const [model, setModel] = useState((_a = props.model) === null || _a === void 0 ? void 0 : _a.jGISModel);
32
- const [sourceIds, setSourceIds] = useState(Private.sortedSourceIds(model));
33
- /**
34
- * Propagate the source selection.
35
- */
36
- const onItemClick = ({ type, item, nodeId, event }) => {
37
- props.onSelect({ type, item, nodeId, event });
38
- };
39
- /**
40
- * Listen to the sources and changes.
41
- */
42
- useEffect(() => {
43
- const updateSources = () => {
44
- setSourceIds([...Private.sortedSourceIds(model)]);
45
- };
46
- model === null || model === void 0 ? void 0 : model.sharedModel.sourcesChanged.connect(updateSources);
47
- model === null || model === void 0 ? void 0 : model.clientStateChanged.connect(updateSources);
48
- updateSources();
49
- return () => {
50
- model === null || model === void 0 ? void 0 : model.sharedModel.sourcesChanged.disconnect(updateSources);
51
- model === null || model === void 0 ? void 0 : model.clientStateChanged.disconnect(updateSources);
52
- };
53
- }, [model]);
54
- /**
55
- * Update the model when it changes.
56
- */
57
- (_b = props.model) === null || _b === void 0 ? void 0 : _b.documentChanged.connect((_, widget) => {
58
- setModel(widget === null || widget === void 0 ? void 0 : widget.model);
59
- });
60
- return (React.createElement("div", { id: "jp-gis-sources" }, sourceIds.map(sourceId => {
61
- return (React.createElement(SourceComponent, { key: `source-${sourceId}`, gisModel: model, sourceId: sourceId, onClick: onItemClick }));
62
- })));
63
- }
64
- function isSelected(sourceId, model) {
65
- var _a, _b, _c, _d;
66
- return ((((_b = (_a = model === null || model === void 0 ? void 0 : model.localState) === null || _a === void 0 ? void 0 : _a.selected) === null || _b === void 0 ? void 0 : _b.value) &&
67
- Object.keys((_d = (_c = model === null || model === void 0 ? void 0 : model.localState) === null || _c === void 0 ? void 0 : _c.selected) === null || _d === void 0 ? void 0 : _d.value).includes(sourceId)) ||
68
- false);
69
- }
70
- /**
71
- * The component to display a single source.
72
- */
73
- function SourceComponent(props) {
74
- const { sourceId, gisModel, onClick } = props;
75
- const source = gisModel === null || gisModel === void 0 ? void 0 : gisModel.getSource(sourceId);
76
- if (source === undefined) {
77
- return React.createElement(React.Fragment, null);
78
- }
79
- const [id, setId] = useState('');
80
- const [selected, setSelected] = useState(
81
- // TODO Support multi-selection as `model?.jGISModel?.localState?.selected.value` does
82
- isSelected(sourceId, gisModel));
83
- const [unused, setUnused] = useState(false);
84
- const name = source.name;
85
- useEffect(() => {
86
- setId(DOMUtils.createDomID());
87
- }, []);
88
- /**
89
- * Check if the source is used by a layer.
90
- */
91
- useEffect(() => {
92
- const checkUsage = () => {
93
- const sources = gisModel === null || gisModel === void 0 ? void 0 : gisModel.getLayersBySource(sourceId);
94
- setUnused(sources ? sources.length === 0 : true);
95
- };
96
- gisModel === null || gisModel === void 0 ? void 0 : gisModel.sharedLayersChanged.connect(checkUsage);
97
- checkUsage();
98
- return () => {
99
- gisModel === null || gisModel === void 0 ? void 0 : gisModel.sharedLayersChanged.disconnect(checkUsage);
100
- };
101
- }, [gisModel]);
102
- /**
103
- * Listen to the changes on the current source.
104
- */
105
- useEffect(() => {
106
- const onClientSharedStateChanged = (sender, clients) => {
107
- // TODO Support follow mode and remoteUser state
108
- setSelected(isSelected(sourceId, gisModel));
109
- };
110
- gisModel === null || gisModel === void 0 ? void 0 : gisModel.clientStateChanged.connect(onClientSharedStateChanged);
111
- return () => {
112
- gisModel === null || gisModel === void 0 ? void 0 : gisModel.clientStateChanged.disconnect(onClientSharedStateChanged);
113
- };
114
- }, [gisModel]);
115
- const setSelection = (event) => {
116
- var _a;
117
- const childId = (_a = event.currentTarget.children.namedItem(id)) === null || _a === void 0 ? void 0 : _a.id;
118
- onClick({ type: 'source', item: sourceId, nodeId: childId, event });
119
- };
120
- let mainClasses = SOURCE_CLASS;
121
- if (selected) {
122
- mainClasses = mainClasses.concat(' jp-mod-selected');
123
- }
124
- if (unused) {
125
- mainClasses = mainClasses.concat(` ${SOURCE_UNUSED}`);
126
- }
127
- return (React.createElement("div", { className: mainClasses },
128
- React.createElement("div", { className: SOURCE_TITLE_CLASS, onClick: setSelection, onContextMenu: setSelection },
129
- icons.has(source.type) && (React.createElement(LabIcon.resolveReact, Object.assign({}, icons.get(source.type), { className: SOURCE_ICON_CLASS }))),
130
- React.createElement("span", { id: id, className: SOURCE_TEXT_CLASS }, name),
131
- unused && React.createElement("span", { className: SOURCE_INFO }, "(unused)"))));
132
- }
133
- var Private;
134
- (function (Private) {
135
- function sortedSourceIds(model) {
136
- const sources = model === null || model === void 0 ? void 0 : model.getSources();
137
- if (sources === undefined) {
138
- return [];
139
- }
140
- return Object.keys(sources).sort((id1, id2) => {
141
- const name1 = sources[id1].name.toLowerCase();
142
- const name2 = sources[id2].name.toLowerCase();
143
- return name1 < name2 ? -1 : name1 > name2 ? 1 : 0;
144
- });
145
- }
146
- Private.sortedSourceIds = sortedSourceIds;
147
- })(Private || (Private = {}));