@jupytergis/base 0.7.0 → 0.8.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/commands/index.js +7 -1
- package/lib/dialogs/symbology/hooks/useGetProperties.js +53 -19
- package/lib/dialogs/symbology/vector_layer/VectorRendering.js +3 -3
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +4 -2
- package/lib/formbuilder/objectform/source/geojsonsource.d.ts +3 -1
- package/lib/formbuilder/objectform/source/geojsonsource.js +20 -4
- package/lib/mainview/mainView.js +50 -6
- package/lib/panelview/leftpanel.js +5 -3
- package/lib/panelview/rightpanel.js +5 -1
- package/package.json +2 -2
package/lib/commands/index.js
CHANGED
|
@@ -85,6 +85,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
85
85
|
'VectorLayer',
|
|
86
86
|
'ShapefileLayer',
|
|
87
87
|
'WebGlLayer',
|
|
88
|
+
'VectorTileLayer',
|
|
88
89
|
].includes(selectedLayer.type);
|
|
89
90
|
const isIdentifying = current.model.isIdentifying;
|
|
90
91
|
if (isIdentifying && !canIdentify) {
|
|
@@ -98,7 +99,12 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
98
99
|
if (!selectedLayer) {
|
|
99
100
|
return false;
|
|
100
101
|
}
|
|
101
|
-
return [
|
|
102
|
+
return [
|
|
103
|
+
'VectorLayer',
|
|
104
|
+
'ShapefileLayer',
|
|
105
|
+
'WebGlLayer',
|
|
106
|
+
'VectorTileLayer',
|
|
107
|
+
].includes(selectedLayer.type);
|
|
102
108
|
}, execute: args => {
|
|
103
109
|
const current = tracker.currentWidget;
|
|
104
110
|
if (!current) {
|
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
// import { GeoJSONFeature } from 'geojson';
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { loadFile } from "../../../tools";
|
|
4
|
+
async function getGeoJsonProperties({ source, model, }) {
|
|
5
|
+
var _a;
|
|
6
|
+
const result = {};
|
|
7
|
+
const data = await loadFile({
|
|
8
|
+
filepath: (_a = source.parameters) === null || _a === void 0 ? void 0 : _a.path,
|
|
9
|
+
type: 'GeoJSONSource',
|
|
10
|
+
model,
|
|
11
|
+
});
|
|
12
|
+
if (!data) {
|
|
13
|
+
throw new Error('Failed to read GeoJSON data');
|
|
14
|
+
}
|
|
15
|
+
data.features.forEach((feature) => {
|
|
16
|
+
if (feature.properties) {
|
|
17
|
+
for (const [key, value] of Object.entries(feature.properties)) {
|
|
18
|
+
if (!result[key]) {
|
|
19
|
+
result[key] = new Set();
|
|
20
|
+
}
|
|
21
|
+
result[key].add(value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function getVectorTileProperties({ model, sourceId, }) {
|
|
28
|
+
const result = {};
|
|
29
|
+
const features = model.getFeaturesForCurrentTile({ sourceId });
|
|
30
|
+
features.forEach(feature => {
|
|
31
|
+
var _a;
|
|
32
|
+
const props = (_a = feature.getProperties) === null || _a === void 0 ? void 0 : _a.call(feature);
|
|
33
|
+
if (props) {
|
|
34
|
+
for (const [key, value] of Object.entries(props)) {
|
|
35
|
+
if (!result[key]) {
|
|
36
|
+
result[key] = new Set();
|
|
37
|
+
}
|
|
38
|
+
result[key].add(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
4
44
|
export const useGetProperties = ({ layerId, model, }) => {
|
|
5
45
|
const [featureProperties, setFeatureProperties] = useState({});
|
|
6
46
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -16,30 +56,24 @@ export const useGetProperties = ({ layerId, model, }) => {
|
|
|
16
56
|
if (!source) {
|
|
17
57
|
throw new Error('Source not found');
|
|
18
58
|
}
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
model
|
|
23
|
-
}
|
|
24
|
-
if (
|
|
25
|
-
|
|
59
|
+
const sourceType = source === null || source === void 0 ? void 0 : source.type;
|
|
60
|
+
let result = {};
|
|
61
|
+
if (sourceType === 'GeoJSONSource') {
|
|
62
|
+
result = await getGeoJsonProperties({ source, model });
|
|
63
|
+
}
|
|
64
|
+
else if (sourceType === 'VectorTileSource') {
|
|
65
|
+
const sourceId = (_b = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _b === void 0 ? void 0 : _b.source;
|
|
66
|
+
result = getVectorTileProperties({ model, sourceId });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
throw new Error(`Unsupported source type: ${sourceType}`);
|
|
26
70
|
}
|
|
27
|
-
const result = {};
|
|
28
|
-
data.features.forEach((feature) => {
|
|
29
|
-
if (feature.properties) {
|
|
30
|
-
Object.entries(feature.properties).forEach(([key, value]) => {
|
|
31
|
-
if (!(key in result)) {
|
|
32
|
-
result[key] = new Set();
|
|
33
|
-
}
|
|
34
|
-
result[key].add(value);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
71
|
setFeatureProperties(result);
|
|
39
|
-
setIsLoading(false);
|
|
40
72
|
}
|
|
41
73
|
catch (err) {
|
|
42
74
|
setError(err);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
43
77
|
setIsLoading(false);
|
|
44
78
|
}
|
|
45
79
|
};
|
|
@@ -15,19 +15,19 @@ const RENDER_TYPE_OPTIONS = {
|
|
|
15
15
|
Canonical: {
|
|
16
16
|
component: Canonical,
|
|
17
17
|
attributeChecker: getColorCodeFeatureAttributes,
|
|
18
|
-
supportedLayerTypes: ['VectorLayer', 'HeatmapLayer'],
|
|
18
|
+
supportedLayerTypes: ['VectorLayer', 'VectorTileLayer', 'HeatmapLayer'],
|
|
19
19
|
isTabbed: false,
|
|
20
20
|
},
|
|
21
21
|
Graduated: {
|
|
22
22
|
component: Graduated,
|
|
23
23
|
attributeChecker: getNumericFeatureAttributes,
|
|
24
|
-
supportedLayerTypes: ['VectorLayer', 'HeatmapLayer'],
|
|
24
|
+
supportedLayerTypes: ['VectorLayer', 'VectorTileLayer', 'HeatmapLayer'],
|
|
25
25
|
isTabbed: true,
|
|
26
26
|
},
|
|
27
27
|
Categorized: {
|
|
28
28
|
component: Categorized,
|
|
29
29
|
attributeChecker: getNumericFeatureAttributes,
|
|
30
|
-
supportedLayerTypes: ['VectorLayer', 'HeatmapLayer'],
|
|
30
|
+
supportedLayerTypes: ['VectorLayer', 'VectorTileLayer', 'HeatmapLayer'],
|
|
31
31
|
isTabbed: true,
|
|
32
32
|
},
|
|
33
33
|
Heatmap: {
|
|
@@ -126,13 +126,15 @@ const Graduated = ({ model, state, okSignalPromise, cancel, layerId, symbologyTa
|
|
|
126
126
|
});
|
|
127
127
|
newStyle['fill-color'] = colorExpr;
|
|
128
128
|
newStyle['circle-fill-color'] = colorExpr;
|
|
129
|
+
newStyle['stroke-color'] = colorExpr;
|
|
130
|
+
newStyle['circle-stroke-color'] = colorExpr;
|
|
129
131
|
}
|
|
130
132
|
else {
|
|
131
133
|
newStyle['fill-color'] = undefined;
|
|
132
134
|
newStyle['circle-fill-color'] = undefined;
|
|
135
|
+
newStyle['stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
136
|
+
newStyle['circle-stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
133
137
|
}
|
|
134
|
-
newStyle['stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
135
|
-
newStyle['circle-stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
136
138
|
newStyle['stroke-width'] = colorManualStyleRef.current.strokeWidth;
|
|
137
139
|
newStyle['circle-stroke-width'] = colorManualStyleRef.current.strokeWidth;
|
|
138
140
|
// Apply radius symbology
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IDict } from '@jupytergis/schema';
|
|
2
|
+
import { ISubmitEvent } from '@rjsf/core';
|
|
2
3
|
import { PathBasedSourcePropertiesForm } from './pathbasedsource';
|
|
3
4
|
import { ISourceFormProps } from './sourceform';
|
|
4
5
|
/**
|
|
@@ -13,5 +14,6 @@ export declare class GeoJSONSourcePropertiesForm extends PathBasedSourceProperti
|
|
|
13
14
|
*
|
|
14
15
|
* @param path - the path to validate.
|
|
15
16
|
*/
|
|
16
|
-
protected _validatePath(path: string): Promise<void>;
|
|
17
|
+
protected _validatePath(path: string | undefined): Promise<void>;
|
|
18
|
+
protected onFormSubmit(e: ISubmitEvent<any>): void;
|
|
17
19
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as geojson from '@jupytergis/schema/src/schema/geojson.json';
|
|
2
|
+
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
2
3
|
import { Ajv } from 'ajv';
|
|
3
4
|
import { loadFile } from "../../../tools";
|
|
4
5
|
import { PathBasedSourcePropertiesForm } from './pathbasedsource';
|
|
@@ -17,6 +18,10 @@ export class GeoJSONSourcePropertiesForm extends PathBasedSourcePropertiesForm {
|
|
|
17
18
|
if ((data === null || data === void 0 ? void 0 : data.path) !== '') {
|
|
18
19
|
this.removeFormEntry('data', data, schema, uiSchema);
|
|
19
20
|
}
|
|
21
|
+
if (this.props.formContext === 'create') {
|
|
22
|
+
schema.properties.path.description =
|
|
23
|
+
'The local path to a GeoJSON file. (If no path/url is provided, an empty GeoJSON is created.)';
|
|
24
|
+
}
|
|
20
25
|
super.processSchema(data, schema, uiSchema);
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
@@ -28,7 +33,7 @@ export class GeoJSONSourcePropertiesForm extends PathBasedSourcePropertiesForm {
|
|
|
28
33
|
var _a;
|
|
29
34
|
const extraErrors = this.state.extraErrors;
|
|
30
35
|
let error = '';
|
|
31
|
-
let valid =
|
|
36
|
+
let valid = true;
|
|
32
37
|
if (path) {
|
|
33
38
|
try {
|
|
34
39
|
const geoJSONData = await loadFile({
|
|
@@ -45,9 +50,6 @@ export class GeoJSONSourcePropertiesForm extends PathBasedSourcePropertiesForm {
|
|
|
45
50
|
error = `"${path}" is not a valid GeoJSON file: ${e}`;
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
|
-
else {
|
|
49
|
-
error = 'Path is required';
|
|
50
|
-
}
|
|
51
53
|
if (!valid) {
|
|
52
54
|
extraErrors.path = {
|
|
53
55
|
__errors: [error],
|
|
@@ -64,4 +66,18 @@ export class GeoJSONSourcePropertiesForm extends PathBasedSourcePropertiesForm {
|
|
|
64
66
|
this.props.formErrorSignal.emit(!valid);
|
|
65
67
|
}
|
|
66
68
|
}
|
|
69
|
+
onFormSubmit(e) {
|
|
70
|
+
var _a, _b, _c;
|
|
71
|
+
if (((_c = (_b = (_a = this.state.extraErrors) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.__errors) === null || _c === void 0 ? void 0 : _c.length) >= 1) {
|
|
72
|
+
showErrorMessage('Invalid file', this.state.extraErrors.path.__errors[0]);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!e.formData.path) {
|
|
76
|
+
e.formData.data = {
|
|
77
|
+
type: 'FeatureCollection',
|
|
78
|
+
features: [],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
super.onFormSubmit(e);
|
|
82
|
+
}
|
|
67
83
|
}
|
package/lib/mainview/mainView.js
CHANGED
|
@@ -3,7 +3,7 @@ import { showErrorMessage } from '@jupyterlab/apputils';
|
|
|
3
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
4
4
|
import { UUID } from '@lumino/coreutils';
|
|
5
5
|
import { ContextMenu } from '@lumino/widgets';
|
|
6
|
-
import { Collection, Map as OlMap, View, getUid } from 'ol';
|
|
6
|
+
import { Collection, Map as OlMap, View, getUid, } from 'ol';
|
|
7
7
|
import Feature from 'ol/Feature';
|
|
8
8
|
import { FullScreen, ScaleLine } from 'ol/control';
|
|
9
9
|
import { singleClick } from 'ol/events/condition';
|
|
@@ -14,10 +14,9 @@ import { Heatmap as HeatmapLayer, Image as ImageLayer, Layer, Vector as VectorLa
|
|
|
14
14
|
import TileLayer from 'ol/layer/Tile';
|
|
15
15
|
import { fromLonLat, get as getProjection, toLonLat, transformExtent, } from 'ol/proj';
|
|
16
16
|
import { register } from 'ol/proj/proj4.js';
|
|
17
|
-
import RenderFeature from 'ol/render/Feature';
|
|
18
|
-
import { GeoTIFF as GeoTIFFSource, ImageTile as ImageTileSource, Vector as VectorSource, VectorTile as VectorTileSource, XYZ as XYZSource, } from 'ol/source';
|
|
17
|
+
import RenderFeature, { toGeometry } from 'ol/render/Feature';
|
|
18
|
+
import { GeoTIFF as GeoTIFFSource, ImageTile as ImageTileSource, Vector as VectorSource, VectorTile as VectorTileSource, XYZ as XYZSource, Tile as TileSource, } from 'ol/source';
|
|
19
19
|
import Static from 'ol/source/ImageStatic';
|
|
20
|
-
import TileSource from 'ol/source/Tile';
|
|
21
20
|
import { Circle, Fill, Stroke, Style } from 'ol/style';
|
|
22
21
|
//@ts-expect-error no types for ol-pmtiles
|
|
23
22
|
import { PMTilesRasterSource, PMTilesVectorSource } from 'ol-pmtiles';
|
|
@@ -665,7 +664,8 @@ export class MainView extends React.Component {
|
|
|
665
664
|
switch (source.type) {
|
|
666
665
|
case 'RasterSource': {
|
|
667
666
|
const sourceParameters = source.parameters;
|
|
668
|
-
const pmTiles = sourceParameters.url.endsWith('.pmtiles')
|
|
667
|
+
const pmTiles = sourceParameters.url.endsWith('.pmtiles') ||
|
|
668
|
+
sourceParameters.url.endsWith('pmtiles.gz');
|
|
669
669
|
const url = this.computeSourceUrl(source);
|
|
670
670
|
if (!pmTiles) {
|
|
671
671
|
newSource = new XYZSource({
|
|
@@ -698,7 +698,8 @@ export class MainView extends React.Component {
|
|
|
698
698
|
}
|
|
699
699
|
case 'VectorTileSource': {
|
|
700
700
|
const sourceParameters = source.parameters;
|
|
701
|
-
const pmTiles = sourceParameters.url.endsWith('.pmtiles')
|
|
701
|
+
const pmTiles = sourceParameters.url.endsWith('.pmtiles') ||
|
|
702
|
+
sourceParameters.url.endsWith('pmtiles.gz');
|
|
702
703
|
const url = this.computeSourceUrl(source);
|
|
703
704
|
if (!pmTiles) {
|
|
704
705
|
newSource = new VectorTileSource({
|
|
@@ -717,6 +718,16 @@ export class MainView extends React.Component {
|
|
|
717
718
|
url: url,
|
|
718
719
|
});
|
|
719
720
|
}
|
|
721
|
+
newSource.on('tileloadend', (event) => {
|
|
722
|
+
const tile = event.tile;
|
|
723
|
+
const features = tile.getFeatures();
|
|
724
|
+
if (features && features.length > 0) {
|
|
725
|
+
this._model.syncTileFeatures({
|
|
726
|
+
sourceId: id,
|
|
727
|
+
features,
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
});
|
|
720
731
|
break;
|
|
721
732
|
}
|
|
722
733
|
case 'GeoJSONSource': {
|
|
@@ -1581,6 +1592,39 @@ export class MainView extends React.Component {
|
|
|
1581
1592
|
const layerId = Object.keys(selectedLayer)[0];
|
|
1582
1593
|
const jgisLayer = this._model.getLayer(layerId);
|
|
1583
1594
|
switch (jgisLayer === null || jgisLayer === void 0 ? void 0 : jgisLayer.type) {
|
|
1595
|
+
case 'VectorTileLayer': {
|
|
1596
|
+
const geometries = [];
|
|
1597
|
+
const features = [];
|
|
1598
|
+
this._Map.forEachFeatureAtPixel(e.pixel, (feature) => {
|
|
1599
|
+
let geom;
|
|
1600
|
+
if (feature instanceof RenderFeature) {
|
|
1601
|
+
geom = toGeometry(feature);
|
|
1602
|
+
}
|
|
1603
|
+
else if ('getGeometry' in feature) {
|
|
1604
|
+
geom = feature.getGeometry();
|
|
1605
|
+
}
|
|
1606
|
+
const props = feature.getProperties();
|
|
1607
|
+
if (geom) {
|
|
1608
|
+
geometries.push(geom);
|
|
1609
|
+
}
|
|
1610
|
+
features.push(Object.assign({}, props));
|
|
1611
|
+
return true;
|
|
1612
|
+
});
|
|
1613
|
+
if (features.length > 0) {
|
|
1614
|
+
this._model.syncIdentifiedFeatures(features, this._mainViewModel.id);
|
|
1615
|
+
}
|
|
1616
|
+
if (geometries.length > 0) {
|
|
1617
|
+
for (const geom of geometries) {
|
|
1618
|
+
this._model.highlightFeatureSignal.emit(geom);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
else {
|
|
1622
|
+
const coordinate = this._Map.getCoordinateFromPixel(e.pixel);
|
|
1623
|
+
const point = new Point(coordinate);
|
|
1624
|
+
this._model.highlightFeatureSignal.emit(point);
|
|
1625
|
+
}
|
|
1626
|
+
break;
|
|
1627
|
+
}
|
|
1584
1628
|
case 'WebGlLayer': {
|
|
1585
1629
|
const layer = this.getLayer(layerId);
|
|
1586
1630
|
const data = layer.getData(e.pixel);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { PageConfig } from '@jupyterlab/coreutils';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
import { LayersBodyComponent } from './components/layers';
|
|
3
4
|
import { PanelTabs, TabsContent, TabsList, TabsTrigger, } from '../shared/components/Tabs';
|
|
4
5
|
import StacPanel from '../stacBrowser/components/StacPanel';
|
|
5
6
|
import FilterComponent from './components/filter-panel/Filter';
|
|
6
7
|
export const LeftPanel = (props) => {
|
|
8
|
+
const hideStacPanel = PageConfig.getOption('HIDE_STAC_PANEL') === 'true';
|
|
7
9
|
const tabInfo = [
|
|
8
10
|
{ name: 'layers', title: 'Layers' },
|
|
9
|
-
{ name: 'stac', title: 'Stac Browser' },
|
|
11
|
+
...(hideStacPanel ? [] : [{ name: 'stac', title: 'Stac Browser' }]),
|
|
10
12
|
{ name: 'filters', title: 'Filters' },
|
|
11
13
|
];
|
|
12
14
|
const [curTab, setCurTab] = React.useState(tabInfo[0].name);
|
|
@@ -24,8 +26,8 @@ export const LeftPanel = (props) => {
|
|
|
24
26
|
})),
|
|
25
27
|
React.createElement(TabsContent, { value: "layers", className: "jgis-panel-tab-content jp-gis-layerPanel" },
|
|
26
28
|
React.createElement(LayersBodyComponent, { model: props.model, commands: props.commands, state: props.state })),
|
|
27
|
-
React.createElement(TabsContent, { value: "stac" },
|
|
28
|
-
React.createElement(StacPanel, { model: props.model })),
|
|
29
|
+
!hideStacPanel && (React.createElement(TabsContent, { value: "stac" },
|
|
30
|
+
React.createElement(StacPanel, { model: props.model }))),
|
|
29
31
|
React.createElement(TabsContent, { value: "filters", className: "jgis-panel-tab-content" },
|
|
30
32
|
React.createElement(FilterComponent, { model: props.model }),
|
|
31
33
|
","))));
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { PageConfig } from '@jupyterlab/coreutils';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
import { AnnotationsPanel } from './annotationPanel';
|
|
3
4
|
import { IdentifyPanelComponent } from './components/identify-panel/IdentifyPanel';
|
|
4
5
|
import { ObjectPropertiesReact } from './objectproperties';
|
|
5
6
|
import { PanelTabs, TabsContent, TabsList, TabsTrigger, } from '../shared/components/Tabs';
|
|
6
7
|
export const RightPanel = props => {
|
|
8
|
+
const hideAnnotationPanel = PageConfig.getOption('HIDE_ANNOTATION_PANEL') === 'true';
|
|
7
9
|
const [selectedObjectProperties, setSelectedObjectProperties] = React.useState(undefined);
|
|
8
10
|
const tabInfo = [
|
|
9
11
|
{ name: 'objectProperties', title: 'Object Properties' },
|
|
10
|
-
|
|
12
|
+
...(hideAnnotationPanel
|
|
13
|
+
? []
|
|
14
|
+
: [{ name: 'annotations', title: 'Annotations' }]),
|
|
11
15
|
{ name: 'identifyPanel', title: 'Identify Features' },
|
|
12
16
|
];
|
|
13
17
|
const [curTab, setCurTab] = React.useState(tabInfo[0].name);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupytergis/base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "A JupyterLab extension for 3D modelling.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@jupyter/collaboration": "^3.1.0",
|
|
45
45
|
"@jupyter/react-components": "^0.16.6",
|
|
46
46
|
"@jupyter/ydoc": "^2.0.0 || ^3.0.0",
|
|
47
|
-
"@jupytergis/schema": "^0.
|
|
47
|
+
"@jupytergis/schema": "^0.8.1",
|
|
48
48
|
"@jupyterlab/application": "^4.3.0",
|
|
49
49
|
"@jupyterlab/apputils": "^4.3.0",
|
|
50
50
|
"@jupyterlab/completer": "^4.3.0",
|