Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bec511f
Add `describedBy` to commands
arjxn-py Oct 28, 2025
c0ed545
lint
arjxn-py Oct 28, 2025
3e19dcf
command to add geojson with params
arjxn-py Oct 29, 2025
6f80029
`newRasterWithParams`
arjxn-py Oct 29, 2025
8375e73
`newVectorTileWithParams`
arjxn-py Oct 29, 2025
6e34acf
`newGeoParquetWithParams`
arjxn-py Oct 30, 2025
e54d397
`newHillshadeWithParams`
arjxn-py Oct 31, 2025
28e19e2
`newImageWithParams`
arjxn-py Oct 31, 2025
7b59b1c
`newVideoWithParams`
arjxn-py Oct 31, 2025
89d9a54
`newGeoTiffWithParams`
arjxn-py Oct 31, 2025
f1a942b
`newShapefileWithParams`
arjxn-py Oct 31, 2025
afb13c1
add undo redo in doc action commands
arjxn-py Oct 31, 2025
1127741
`identifyWithParams`
arjxn-py Oct 31, 2025
ba83fa1
`temporalControllerWithParams`
arjxn-py Oct 31, 2025
abdd670
`renameLayerWithParams`
arjxn-py Oct 31, 2025
9052a4f
lint
arjxn-py Oct 31, 2025
a8c9e9f
`removeLayerWithParams`
arjxn-py Oct 31, 2025
be53860
`renameGroupWithParams`
arjxn-py Oct 31, 2025
2b862ef
`removeGroupWithParams`, `moveLayersToGroupWithParams`
arjxn-py Oct 31, 2025
a8c75bd
`moveLayerToNewGroupWithParams`
arjxn-py Oct 31, 2025
717071a
`renameSourceWithParams`, `removeSourceWithParams`
arjxn-py Oct 31, 2025
8201547
`zoomToLayerWithParams`
arjxn-py Oct 31, 2025
94fdd20
`downloadGeoJSONWithParams`
arjxn-py Oct 31, 2025
078b87c
`getGeolocationWithParams`
arjxn-py Oct 31, 2025
9b83900
Processing commands from params [needs review]
arjxn-py Nov 3, 2025
34c4a54
usage
arjxn-py Nov 3, 2025
a7abf1c
fix processing commands
arjxn-py Nov 11, 2025
156496d
refactor layer addition commands
arjxn-py Nov 11, 2025
b2172c4
processing without dialog
arjxn-py Nov 11, 2025
1ed8ed8
try fixing CI build
arjxn-py Nov 12, 2025
5e8063b
Merge branch 'main' into add-describedby
arjxn-py Nov 12, 2025
e4ffcfe
fix
arjxn-py Nov 12, 2025
507de69
lint
arjxn-py Nov 12, 2025
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
681 changes: 681 additions & 0 deletions packages/base/src/commands/documentActionCommands.ts

Large diffs are not rendered by default.

257 changes: 257 additions & 0 deletions packages/base/src/commands/index.ts

Large diffs are not rendered by default.

306 changes: 306 additions & 0 deletions packages/base/src/commands/operationCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
import { IJupyterGISModel, IJGISLayer, IJGISSource } from '@jupytergis/schema';
import { IRenderMime } from '@jupyterlab/rendermime';
import { CommandRegistry } from '@lumino/commands';
import { UUID } from '@lumino/coreutils';

import { JupyterGISTracker } from '../types';

export namespace LayerCreationCommandIDs {
export const newGeoJSONWithParams = 'jupytergis:newGeoJSONWithParams';
export const newRasterWithParams = 'jupytergis:newRasterWithParams';
export const newVectorTileWithParams = 'jupytergis:newVectorTileWithParams';
export const newGeoParquetWithParams = 'jupytergis:newGeoParquetWithParams';
export const newHillshadeWithParams = 'jupytergis:newHillshadeWithParams';
export const newImageWithParams = 'jupytergis:newImageWithParams';
export const newVideoWithParams = 'jupytergis:newVideoWithParams';
export const newGeoTiffWithParams = 'jupytergis:newGeoTiffWithParams';
export const newShapefileWithParams = 'jupytergis:newShapefileWithParams';
}

type LayerCreationSpec = {
id: string;
label: string;
sourceType: string;
layerType: string;
sourceSchema: Record<string, unknown>;
layerParamsSchema: Record<string, unknown>;
buildParameters: (params: any, sourceId: string) => IJGISLayer['parameters'];
};

/**
* Generic command factory for layer creation.
*/
function createLayerCommand(
commands: CommandRegistry,
tracker: JupyterGISTracker,
trans: IRenderMime.TranslationBundle,
spec: LayerCreationSpec,
): void {
commands.addCommand(spec.id, {
label: trans.__(spec.label),
isEnabled: () => true,
describedBy: {
args: {
type: 'object',
required: ['filePath', 'Name', 'parameters'],
properties: {
filePath: { type: 'string', description: 'Path to the .jGIS file' },
Name: { type: 'string', description: 'Layer name' },
parameters: {
type: 'object',
properties: {
source: spec.sourceSchema,
...spec.layerParamsSchema,
},
},
} as any,
},
},
execute: (async (args: {
filePath: string;
Name: string;
parameters: Record<string, any>;
}) => {
const { filePath, Name, parameters } = args;
const current = tracker.find(w => w.model.filePath === filePath);
if (!current || !current.model.sharedModel.editable) {
console.warn('Invalid or non-editable document for', filePath);
return;
}

const model: IJupyterGISModel = current.model;
const sharedModel = model.sharedModel;
const sourceId = UUID.uuid4();
const layerId = UUID.uuid4();

const sourceModel: IJGISSource = {
type: spec.sourceType as any,
name: `${Name} Source`,
parameters: parameters.source,
};
sharedModel.addSource(sourceId, sourceModel);

const layerModel: IJGISLayer = {
type: spec.layerType as any,
name: Name,
visible: true,
parameters: spec.buildParameters(parameters, sourceId),
};
model.addLayer(layerId, layerModel);
}) as any,
});
}

/**
* Register all layer creation commands using declarative specs.
*/
export function addLayerCreationCommands(options: {
tracker: JupyterGISTracker;
commands: CommandRegistry;
trans: IRenderMime.TranslationBundle;
}): void {
const { tracker, commands, trans } = options;

const specs: LayerCreationSpec[] = [
{
id: LayerCreationCommandIDs.newGeoJSONWithParams,
label: 'New GeoJSON Layer From Parameters',
sourceType: 'GeoJSONSource',
layerType: 'VectorLayer',
sourceSchema: {
type: 'object',
required: ['path'],
properties: { path: { type: 'string' } },
},
layerParamsSchema: {
color: { type: 'object' },
opacity: { type: 'number', default: 1 },
symbologyState: { type: 'object' },
},
buildParameters: (p, id) => ({
source: id,
color: p.color ?? {},
opacity: p.opacity ?? 1,
symbologyState: p.symbologyState,
}),
},
{
id: LayerCreationCommandIDs.newRasterWithParams,
label: 'New Raster Layer From Parameters',
sourceType: 'RasterSource',
layerType: 'RasterLayer',
sourceSchema: {
type: 'object',
required: ['url'],
properties: { url: { type: 'string' } },
},
layerParamsSchema: { opacity: { type: 'number', default: 1 } },
buildParameters: (p, id) => ({
source: id,
opacity: p.opacity ?? 1,
}),
},
{
id: LayerCreationCommandIDs.newVectorTileWithParams,
label: 'New Vector Tile Layer From Parameters',
sourceType: 'VectorTileSource',
layerType: 'VectorTileLayer',
sourceSchema: {
type: 'object',
required: ['url'],
properties: { url: { type: 'string' } },
},
layerParamsSchema: {
color: { type: 'object' },
opacity: { type: 'number', default: 1 },
},
buildParameters: (p, id) => ({
source: id,
color: p.color ?? {},
opacity: p.opacity ?? 1,
}),
},
{
id: LayerCreationCommandIDs.newGeoParquetWithParams,
label: 'New GeoParquet Layer From Parameters',
sourceType: 'GeoParquetSource',
layerType: 'VectorLayer',
sourceSchema: {
type: 'object',
required: ['path'],
properties: { path: { type: 'string' } },
},
layerParamsSchema: {
color: { type: 'object' },
opacity: { type: 'number', default: 1 },
symbologyState: { type: 'object' },
},
buildParameters: (p, id) => ({
source: id,
color: p.color ?? {},
opacity: p.opacity ?? 1,
symbologyState: p.symbologyState,
}),
},
{
id: LayerCreationCommandIDs.newHillshadeWithParams,
label: 'New Hillshade Layer From Parameters',
sourceType: 'RasterDemSource',
layerType: 'HillshadeLayer',
sourceSchema: {
type: 'object',
required: ['url'],
properties: { url: { type: 'string' } },
},
layerParamsSchema: {
shadowColor: { type: 'string', default: '#473B24' },
},
buildParameters: (p, id) => ({
source: id,
shadowColor: p.shadowColor ?? '#473B24',
}),
},
{
id: LayerCreationCommandIDs.newImageWithParams,
label: 'New Image Layer From Parameters',
sourceType: 'ImageSource',
layerType: 'ImageLayer',
sourceSchema: {
type: 'object',
required: ['path', 'coordinates'],
properties: {
path: { type: 'string' },
coordinates: {
type: 'array',
items: { type: 'array', items: { type: 'number' } },
},
},
},
layerParamsSchema: { opacity: { type: 'number', default: 1 } },
buildParameters: (p, id) => ({
source: id,
opacity: p.opacity ?? 1,
}),
},
{
id: LayerCreationCommandIDs.newVideoWithParams,
label: 'New Video Layer From Parameters',
sourceType: 'VideoSource',
layerType: 'RasterLayer',
sourceSchema: {
type: 'object',
required: ['urls', 'coordinates'],
properties: {
urls: { type: 'array', items: { type: 'string' } },
coordinates: {
type: 'array',
items: { type: 'array', items: { type: 'number' } },
},
},
},
layerParamsSchema: { opacity: { type: 'number', default: 1 } },
buildParameters: (p, id) => ({
source: id,
opacity: p.opacity ?? 1,
}),
},
{
id: LayerCreationCommandIDs.newGeoTiffWithParams,
label: 'New GeoTIFF Layer From Parameters',
sourceType: 'GeoTiffSource',
layerType: 'WebGlLayer',
sourceSchema: {
type: 'object',
required: ['urls'],
properties: {
urls: {
type: 'array',
items: {
type: 'object',
properties: {
url: { type: 'string' },
min: { type: 'number' },
max: { type: 'number' },
},
},
},
},
},
layerParamsSchema: {
opacity: { type: 'number', default: 1 },
color: { type: 'any' },
symbologyState: { type: 'object' },
},
buildParameters: (p, id) => ({
source: id,
opacity: p.opacity ?? 1,
color: p.color,
symbologyState: p.symbologyState ?? { renderType: 'continuous' },
}),
},
{
id: LayerCreationCommandIDs.newShapefileWithParams,
label: 'New Shapefile Layer From Parameters',
sourceType: 'ShapefileSource',
layerType: 'VectorLayer',
sourceSchema: {
type: 'object',
required: ['path'],
properties: { path: { type: 'string' } },
},
layerParamsSchema: {
color: { type: 'object' },
opacity: { type: 'number', default: 1 },
symbologyState: { type: 'object' },
},
buildParameters: (p, id) => ({
source: id,
color: p.color ?? {},
opacity: p.opacity ?? 1,
symbologyState: p.symbologyState ?? { renderType: 'Single Symbol' },
}),
},
];

specs.forEach(spec => createLayerCommand(commands, tracker, trans, spec));
}
Loading
Loading