Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Jul 19, 2024
1 parent b3acc89 commit 1145327
Show file tree
Hide file tree
Showing 12 changed files with 428 additions and 208 deletions.
154 changes: 57 additions & 97 deletions packages/base/src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
IDict,
IGeoJSONSource,
IJGISFormSchemaRegistry,
IJGISLayer,
IJGISLayerBrowserRegistry,
IJGISLayerGroup,
IJGISLayerItem,
Expand All @@ -24,7 +22,7 @@ import { LayerBrowserWidget } from './dialogs/layerBrowserDialog';
import {
DataErrorDialog,
DialogAddDataSourceBody,
FormDialog
CreationFormDialog
} from './dialogs/formdialog';
import { geoJSONIcon } from './icons';
import { JupyterGISWidget } from './widget';
Expand Down Expand Up @@ -272,7 +270,7 @@ export function addCommands(
: false;
},
iconClass: 'fa fa-vector-square',
execute: Private.createVectorTileLayer(tracker)
execute: Private.createVectorTileLayer(tracker, formSchemaRegistry)
});

commands.addCommand(CommandIDs.newGeoJSONSource, {
Expand Down Expand Up @@ -351,7 +349,8 @@ namespace Private {
}

export function createVectorTileLayer(
tracker: WidgetTracker<JupyterGISWidget>
tracker: WidgetTracker<JupyterGISWidget>,
formSchemaRegistry: IJGISFormSchemaRegistry
) {
return async (args: any) => {
const current = tracker.currentWidget;
Expand All @@ -360,55 +359,16 @@ namespace Private {
return;
}

const form = {
title: 'Vector Tile Layer parameters',
default: (model: IJupyterGISModel) => {
return {
name: 'Vector Tile Source',
maxZoom: 24,
minZoom: 0
};
}
};

const dialog = new FormDialog({
const dialog = new CreationFormDialog({
context: current.context,
title: form.title,
sourceData: form.default(current.context.model),
schema: FORM_SCHEMA['VectorTileSource'],
syncData: (props: IDict) => {
const sharedModel = current.context.model.sharedModel;
if (!sharedModel) {
return;
}

const { name, ...parameters } = props;

const sourceId = UUID.uuid4();

const sourceModel: IJGISSource = {
type: 'VectorTileSource',
name,
parameters: {
url: parameters.url,
minZoom: parameters.minZoom,
maxZoom: parameters.maxZoom
}
};

const layerModel: IJGISLayer = {
type: 'VectorLayer',
parameters: {
type: 'line',
source: sourceId
},
visible: true,
name: name + ' Layer'
};

sharedModel.addSource(sourceId, sourceModel);
current.context.model.addLayer(UUID.uuid4(), layerModel);
}
title: 'Create Vector Tile Layer',
createLayer: true,
createSource: true,
// sourceData: form.default(current.context.model),
// layerData: form.default(current.context.model),
sourceType: 'VectorTileSource',
layerType: 'VectorLayer',
formSchemaRegistry
});
await dialog.launch();
};
Expand Down Expand Up @@ -506,50 +466,50 @@ namespace Private {
return;
}

const sources = current.context.model.getSourcesByType('GeoJSONSource');

const form = {
title: 'Vector Layer parameters',
default: (model: IJupyterGISModel) => {
return {
name: 'VectorSource',
source: Object.keys(sources)[0] ?? null
};
}
};

FORM_SCHEMA['VectorLayer'].properties.source.enumNames =
Object.values(sources);
FORM_SCHEMA['VectorLayer'].properties.source.enum = Object.keys(sources);
const dialog = new FormDialog({
context: current.context,
title: form.title,
sourceData: form.default(current.context.model),
schema: FORM_SCHEMA['VectorLayer'],
syncData: (props: IDict) => {
const sharedModel = current.context.model.sharedModel;
if (!sharedModel) {
return;
}

const { name, ...parameters } = props;

const layerModel: IJGISLayer = {
type: 'VectorLayer',
parameters: {
source: parameters.source,
type: parameters.type,
color: parameters.color,
opacity: parameters.opacity
},
visible: true,
name: name + ' Layer'
};

current.context.model.addLayer(UUID.uuid4(), layerModel);
}
});
await dialog.launch();
// const sources = current.context.model.getSourcesByType('GeoJSONSource');

// const form = {
// title: 'Vector Layer parameters',
// default: (model: IJupyterGISModel) => {
// return {
// name: 'VectorSource',
// source: Object.keys(sources)[0] ?? null
// };
// }
// };

// FORM_SCHEMA['VectorLayer'].properties.source.enumNames =
// Object.values(sources);
// FORM_SCHEMA['VectorLayer'].properties.source.enum = Object.keys(sources);
// const dialog = new FormDialog({
// context: current.context,
// title: form.title,
// sourceData: form.default(current.context.model),
// schema: FORM_SCHEMA['VectorLayer'],
// syncData: (props: IDict) => {
// const sharedModel = current.context.model.sharedModel;
// if (!sharedModel) {
// return;
// }

// const { name, ...parameters } = props;

// const layerModel: IJGISLayer = {
// type: 'VectorLayer',
// parameters: {
// source: parameters.source,
// type: parameters.type,
// color: parameters.color,
// opacity: parameters.opacity
// },
// visible: true,
// name: name + ' Layer'
// };

// current.context.model.addLayer(UUID.uuid4(), layerModel);
// }
// });
// await dialog.launch();
};
}

Expand Down
151 changes: 74 additions & 77 deletions packages/base/src/dialogs/formdialog.tsx
Original file line number Diff line number Diff line change
@@ -1,105 +1,102 @@
import {
IDict,
IJGISFormSchemaRegistry,
IJupyterGISModel,
LayerType,
SourceType
} from '@jupytergis/schema';
import { IDict } from '@jupytergis/schema';
import { Dialog } from '@jupyterlab/apputils';
import { DocumentRegistry } from '@jupyterlab/docregistry';
import { LabIcon, errorIcon } from '@jupyterlab/ui-components';
import { Widget } from '@lumino/widgets';
import { ErrorObject } from 'ajv';
import * as React from 'react';

import { BaseForm } from '../formbuilder/baseform';
import { deepCopy } from '../tools';
import { CreationForm, ICreationFormProps } from '../formbuilder';
import { Signal } from '@lumino/signaling';
import { PromiseDelegate } from '@lumino/coreutils';

export interface ICreationFormDialogOptions {
/**
* The type of layer to create.
*/
layerType?: LayerType;

/**
* The type of source to create.
*/
sourceType?: SourceType;

/**
* The initial layer data, if it applies.
*/
layerData?: IDict;

/**
* The initial source data, if it applies.
*/
sourceData?: IDict;
export interface ICreationFormWrapperProps extends ICreationFormProps {
okSignalPromise: PromiseDelegate<Signal<Dialog<IDict>, number>>;
}

formSchemaRegistry: IJGISFormSchemaRegistry;
context: DocumentRegistry.IContext<IJupyterGISModel>;
export interface ICreationFormDialogOptions extends ICreationFormProps {
title: string;
}

const CreationFormWrapper = (props: ICreationFormWrapperProps) => {
const [ok, setOk] = React.useState<Signal<Dialog<IDict>, number> | undefined>(
undefined
);

props.okSignalPromise.promise.then(value => {
setOk(value);
});

return (
ok && (
<CreationForm
context={props.context}
formSchemaRegistry={props.formSchemaRegistry}
createLayer={props.createLayer}
createSource={props.createSource}
layerType={props.layerType}
sourceType={props.sourceType}
sourceData={props.sourceData}
layerData={props.layerData}
ok={ok}
cancel={props.cancel}
/>
)
);
};

/**
* Form for creating a source, a layer or both at the same time
*/
export class CreationFormDialog extends Dialog<IDict> {
constructor(options: ICreationFormDialogOptions) {
const filePath = options.context.path;
const jGISModel = options.context.model;

let layerSchema: IDict | undefined = undefined;
if (options.layerType) {
layerSchema = deepCopy(
options.formSchemaRegistry.getSchemas().get(options.layerType)
);

if (!layerSchema) {
console.log(`Cannot find schema for ${options.layerType}`);
return;
}

// If a source is created as part of this form, remove the source selection from the layer form
if (options.sourceType) {
delete layerSchema.properties?.source;
}
layerSchema['properties'] = {
name: { type: 'string', description: 'The name of the layer' },
...layerSchema['properties']
};
}

let sourceSchema: IDict | undefined = undefined;
if (options.sourceType) {
sourceSchema = deepCopy(
options.formSchemaRegistry.getSchemas().get(options.sourceType)
);
}
const cancelCallback = () => {
this.resolve(0);
};

if (!layerSchema && !sourceSchema) {
// Unreachable
console.log(
`Cannot find schema for ${options.layerType}, ${options.sourceType}`
);
return;
}
const okSignalPromise = new PromiseDelegate<
Signal<Dialog<IDict>, number>
>();

const body = (
<div style={{ overflow: 'hidden' }}>
<BaseForm
formContext="create"
model={jGISModel}
filePath={`${filePath}::dialog`}
<div style={{ overflow: 'auto' }}>
<CreationFormWrapper
context={options.context}
formSchemaRegistry={options.formSchemaRegistry}
createLayer={options.createLayer}
createSource={options.createSource}
layerType={options.layerType}
sourceType={options.sourceType}
sourceData={options.sourceData}
schema={options.schema}
syncData={options.syncData}
layerData={options.layerData}
okSignalPromise={okSignalPromise}
cancel={cancelCallback}
/>
</div>
);

super({ title: options.title, body, buttons: [Dialog.cancelButton()] });
super({
title: options.title,
body,
buttons: [Dialog.cancelButton(), Dialog.okButton()]
});

this.okSignal = new Signal(this);
okSignalPromise.resolve(this.okSignal);

this.addClass('jGIS-layer-CreationFormDialog');
}

resolve(index?: number): void {
if (index === 0) {
super.resolve(index);
}

if (index === 1) {
this.okSignal.emit(1);
}
}

private okSignal: Signal<Dialog<any>, number>;
}

/**
Expand Down
Loading

0 comments on commit 1145327

Please sign in to comment.