Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions packages/base/src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,12 +410,15 @@ export const getFromIndexedDB = async (key: string) => {

const fetchWithProxies = async <T>(
url: string,
model: IJupyterGISModel,
parseResponse: (response: Response) => Promise<T>
): Promise<T | null> => {
const settings = await model.getSettings();

const proxyUrls = [
url, // Direct fetch
`/jupytergis_core/proxy?url=${encodeURIComponent(url)}`, // Internal proxy
`https://corsproxy.io/?url=${encodeURIComponent(url)}` // External proxy
`${settings.proxyUrl}/?url=${encodeURIComponent(url)}` // External proxy
];

for (const proxyUrl of proxyUrls) {
Expand Down Expand Up @@ -444,6 +447,7 @@ const fetchWithProxies = async <T>(
*/
export const loadGeoTiff = async (
sourceInfo: { url?: string | undefined },
model: IJupyterGISModel,
file?: Contents.IModel | null
) => {
if (!sourceInfo?.url) {
Expand All @@ -468,7 +472,9 @@ export const loadGeoTiff = async (
let fileBlob: Blob | null = null;

if (!file) {
fileBlob = await fetchWithProxies(url, async response => response.blob());
fileBlob = await fetchWithProxies(url, model, async response =>
response.blob()
);
if (!fileBlob) {
showErrorMessage('Network error', `Failed to fetch ${url}`);
throw new Error(`Failed to fetch ${url}`);
Expand Down Expand Up @@ -535,10 +541,14 @@ export const loadFile = async (fileInfo: {
return cached.file;
}

const geojson = await fetchWithProxies(filepath, async response => {
const arrayBuffer = await response.arrayBuffer();
return shp(arrayBuffer);
});
const geojson = await fetchWithProxies(
filepath,
model,
async response => {
const arrayBuffer = await response.arrayBuffer();
return shp(arrayBuffer);
}
);

if (geojson) {
await saveToIndexedDB(filepath, geojson);
Expand All @@ -555,8 +565,10 @@ export const loadFile = async (fileInfo: {
return cached.file;
}

const geojson = await fetchWithProxies(filepath, async response =>
response.json()
const geojson = await fetchWithProxies(
filepath,
model,
async response => response.json()
);

if (geojson) {
Expand Down Expand Up @@ -627,7 +639,7 @@ export const loadFile = async (fileInfo: {

case 'GeoTiffSource': {
if (typeof file.content === 'string') {
const tiff = loadGeoTiff({ url: filepath }, file);
const tiff = loadGeoTiff({ url: filepath }, model, file);
return tiff;
} else {
throw new Error('Invalid file format for tiff content.');
Expand Down
1 change: 1 addition & 0 deletions packages/schema/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export interface IJupyterGISModel extends DocumentRegistry.IModel {
contentsManager: Contents.IManager | undefined;
filePath: string;

getSettings(): any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get better typing than this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially, the any is shadowing the fact that it can be null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, i'll look into this

getContent(): IJGISContent;
getLayers(): IJGISLayers;
getLayer(id: string): IJGISLayer | undefined;
Expand Down
28 changes: 27 additions & 1 deletion packages/schema/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ import {
Pointer
} from './interfaces';
import jgisSchema from './schema/project/jgis.json';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

const SETTINGS_ID = '@jupytergis/jupytergis-core:jupytergis-settings';

export class JupyterGISModel implements IJupyterGISModel {
constructor(options: JupyterGISModel.IOptions) {
const { annotationModel, sharedModel } = options;
const { annotationModel, sharedModel, settingRegistry } = options;

if (sharedModel) {
this._sharedModel = sharedModel;
Expand All @@ -50,6 +53,26 @@ export class JupyterGISModel implements IJupyterGISModel {
this
);
this.annotationModel = annotationModel;
this.settingRegistry = settingRegistry;
}

/**
* Initialize custom settings for JupyterLab.
*/
async initSettings(): Promise<void> {
if (this.settingRegistry) {
const setting = await this.settingRegistry.load(SETTINGS_ID);
this._settings = setting.composite as any;

setting.changed.connect(() => {
this._settings = setting.composite as any;
console.log('JupyterGIS Settings updated:', this._settings);
});
}
}

getSettings(): any {
return this._settings;
}

private _onSharedModelChanged = (sender: any, changes: any): void => {
Expand Down Expand Up @@ -724,7 +747,9 @@ export class JupyterGISModel implements IJupyterGISModel {
readonly defaultKernelName: string = '';
readonly defaultKernelLanguage: string = '';
readonly annotationModel?: IAnnotationModel;
readonly settingRegistry?: ISettingRegistry;

private _settings: any = {};
private _sharedModel: IJupyterGISDoc;
private _filePath: string;
private _contentsManager?: Contents.IManager;
Expand Down Expand Up @@ -770,6 +795,7 @@ export namespace JupyterGISModel {
export interface IOptions
extends DocumentRegistry.IModelOptions<IJupyterGISDoc> {
annotationModel?: IAnnotationModel;
settingRegistry?: ISettingRegistry;
}
}

Expand Down
4 changes: 3 additions & 1 deletion python/jupytergis_core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"author": "JupyterGIS contributors",
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
"schema/**/*.{json,js,ts}"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down Expand Up @@ -91,6 +92,7 @@
"access": "public"
},
"jupyterlab": {
"schemaDir": "schema",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 17 of this file, you want to list the schema folder as part of the package file

"discovery": {
"server": {
"managers": [
Expand Down
13 changes: 13 additions & 0 deletions python/jupytergis_core/schema/jupytergis-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"title": "JupyterGIS Settings",
"description": "Settings for the JupyterGIS extension.",
"type": "object",
"properties": {
"proxyUrl": {
"type": "string",
"title": "Proxy URL",
"description": "The proxy URL to use for external requests.",
"default": "https://corsproxy.io"
}
}
}
8 changes: 7 additions & 1 deletion python/jupytergis_core/src/jgisplugin/modelfactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@jupytergis/schema';
import { DocumentRegistry } from '@jupyterlab/docregistry';
import { Contents } from '@jupyterlab/services';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

/**
* A Model factory to create new instances of JupyterGISModel.
Expand All @@ -14,6 +15,7 @@ export class JupyterGISModelFactory
{
constructor(options: JupyterGISModelFactory.IOptions) {
this._annotationModel = options.annotationModel;
this._settingRegistry = options.settingRegistry;
}
/**
* Whether the model is collaborative or not.
Expand Down Expand Up @@ -84,17 +86,21 @@ export class JupyterGISModelFactory
const model = new JupyterGISModel({
sharedModel: options.sharedModel,
languagePreference: options.languagePreference,
annotationModel: this._annotationModel
annotationModel: this._annotationModel,
settingRegistry: this._settingRegistry
});
model.initSettings();
return model;
}

private _annotationModel: IAnnotationModel;
private _settingRegistry: ISettingRegistry;
private _disposed = false;
}

export namespace JupyterGISModelFactory {
export interface IOptions {
annotationModel: IAnnotationModel;
settingRegistry: ISettingRegistry;
}
}
24 changes: 20 additions & 4 deletions python/jupytergis_core/src/jgisplugin/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { PageConfig } from '@jupyterlab/coreutils';
import { IFileBrowserFactory } from '@jupyterlab/filebrowser';
import { ILauncher } from '@jupyterlab/launcher';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

import { CommandIDs, logoIcon, logoMiniIcon } from '@jupytergis/base';
import { JupyterGISDocumentWidgetFactory } from '../factory';
Expand All @@ -36,8 +37,9 @@ const FACTORY = 'JupyterGIS .jgis Viewer';
const CONTENT_TYPE = 'jgis';
const PALETTE_CATEGORY = 'JupyterGIS';
const MODEL_NAME = 'jupytergis-jgismodel';
const SETTINGS_ID = '@jupytergis/jupytergis-core:jupytergis-settings';

const activate = (
const activate = async (
app: JupyterFrontEnd,
tracker: WidgetTracker<IJupyterGISWidget>,
themeManager: IThemeManager,
Expand All @@ -48,14 +50,24 @@ const activate = (
rendermime: IRenderMimeRegistry,
consoleTracker: IConsoleTracker,
annotationModel: IAnnotationModel,
settingRegistry: ISettingRegistry,
launcher: ILauncher | null,
palette: ICommandPalette | null,
drive: ICollaborativeDrive | null
): void => {
): Promise<void> => {
if (PageConfig.getOption('jgis_expose_maps')) {
window.jupytergisMaps = {};
}

let settings: ISettingRegistry.ISettings | null = null;

try {
settings = await settingRegistry.load(SETTINGS_ID);
console.log(`Loaded settings for ${SETTINGS_ID}`, settings);
} catch (error) {
console.warn(`Failed to load settings for ${SETTINGS_ID}`, error);
}

const widgetFactory = new JupyterGISDocumentWidgetFactory({
name: FACTORY,
modelName: MODEL_NAME,
Expand Down Expand Up @@ -85,7 +97,10 @@ const activate = (
app.docRegistry.addWidgetFactory(mimeDocumentFactory);

// Creating and registering the model factory for our custom DocumentModel
const modelFactory = new JupyterGISModelFactory({ annotationModel });
const modelFactory = new JupyterGISModelFactory({
annotationModel,
settingRegistry
});
app.docRegistry.addModelFactory(modelFactory);

// register the filetype
Expand Down Expand Up @@ -270,7 +285,8 @@ const jGISPlugin: JupyterFrontEndPlugin<void> = {
IEditorServices,
IRenderMimeRegistry,
IConsoleTracker,
IAnnotationToken
IAnnotationToken,
ISettingRegistry
],
optional: [ILauncher, ICommandPalette, ICollaborativeDrive],
autoStart: true,
Expand Down
6 changes: 5 additions & 1 deletion python/jupytergis_qgis/src/modelfactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@jupytergis/schema';
import { DocumentRegistry } from '@jupyterlab/docregistry';
import { Contents } from '@jupyterlab/services';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

/**
* A Model factory to create new instances of JupyterGISModel.
Expand Down Expand Up @@ -86,18 +87,21 @@ export class JupyterGISModelFactoryBase
const model = new JupyterGISModel({
sharedModel: options.sharedModel,
languagePreference: options.languagePreference,
annotationModel: this._annotationModel
annotationModel: this._annotationModel,
settingRegistry: this._settingRegistry
});
return model;
}

private _annotationModel: IAnnotationModel;
private _settingRegistry: ISettingRegistry;
private _disposed = false;
}

export namespace JupyterGISModelFactoryBase {
export interface IOptions {
annotationModel: IAnnotationModel;
settingRegistry: ISettingRegistry;
}
}

Expand Down
13 changes: 10 additions & 3 deletions python/jupytergis_qgis/src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { ConsolePanel, IConsoleTracker } from '@jupyterlab/console';
import { PathExt } from '@jupyterlab/coreutils';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { Widget } from '@lumino/widgets';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

import {
JupyterGISDocumentWidget,
Expand Down Expand Up @@ -78,6 +79,7 @@ const activate = async (
rendermime: IRenderMimeRegistry,
consoleTracker: IConsoleTracker,
annotationModel: IAnnotationModel,
settingRegistry: ISettingRegistry,
commandPalette: ICommandPalette | null
): Promise<void> => {
const fcCheck = await requestAPI<{ installed: boolean }>(
Expand Down Expand Up @@ -133,8 +135,12 @@ const activate = async (
app.docRegistry.addWidgetFactory(QGZWidgetFactory);

// Creating and registering the model factory for our custom DocumentModel
app.docRegistry.addModelFactory(new QGSModelFactory({ annotationModel }));
app.docRegistry.addModelFactory(new QGZModelFactory({ annotationModel }));
app.docRegistry.addModelFactory(
new QGSModelFactory({ annotationModel, settingRegistry })
);
app.docRegistry.addModelFactory(
new QGZModelFactory({ annotationModel, settingRegistry })
);
// register the filetype
app.docRegistry.addFileType({
name: 'QGS',
Expand Down Expand Up @@ -311,7 +317,8 @@ export const qgisplugin: JupyterFrontEndPlugin<void> = {
IEditorServices,
IRenderMimeRegistry,
IConsoleTracker,
IAnnotationToken
IAnnotationToken,
ISettingRegistry
],
optional: [ICommandPalette],
autoStart: true,
Expand Down
Loading