@jupytergis/base 0.4.0 → 0.4.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.
- package/lib/dialogs/symbology/hooks/useGetBandInfo.d.ts +2 -6
- package/lib/dialogs/symbology/hooks/useGetBandInfo.js +14 -31
- package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +3 -1
- package/lib/formbuilder/objectform/geotiffsource.js +0 -13
- package/lib/mainview/mainView.d.ts +1 -1
- package/lib/mainview/mainView.js +15 -40
- package/lib/tools.d.ts +0 -14
- package/lib/tools.js +28 -104
- package/lib/widget.d.ts +3 -3
- package/lib/widget.js +3 -3
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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 {
|
|
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
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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" },
|
|
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
|
|
45
|
+
addSource(id: string, source: IJGISSource): Promise<void>;
|
|
46
46
|
private computeSourceUrl;
|
|
47
47
|
/**
|
|
48
48
|
* Update a source in the map.
|
package/lib/mainview/mainView.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
712
|
-
|
|
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
|
|
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
|
|
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
|
|
982
|
+
await this.addSource(sourceId, source);
|
|
1008
983
|
}
|
|
1009
984
|
mapLayer.setVisible(layer.visible);
|
|
1010
985
|
switch (layer.type) {
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
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
|
-
|
|
385
|
-
try {
|
|
386
|
-
const response = await fetch(filepath);
|
|
358
|
+
const geojson = await fetchWithProxies(filepath, async (response) => {
|
|
387
359
|
const arrayBuffer = await response.arrayBuffer();
|
|
388
|
-
|
|
360
|
+
return shp(arrayBuffer);
|
|
361
|
+
});
|
|
362
|
+
if (geojson) {
|
|
389
363
|
await saveToIndexedDB(filepath, geojson);
|
|
390
364
|
return geojson;
|
|
391
365
|
}
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
|
|
426
|
-
|
|
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
|
-
|
|
435
|
-
|
|
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 {
|
|
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.
|
|
3
|
+
"version": "0.4.1",
|
|
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.
|
|
46
|
+
"@jupytergis/schema": "^0.4.1",
|
|
47
47
|
"@jupyterlab/application": "^4.3.0",
|
|
48
48
|
"@jupyterlab/apputils": "^4.3.0",
|
|
49
49
|
"@jupyterlab/completer": "^4.3.0",
|