@jupytergis/base 0.6.2 → 0.8.0

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.
Files changed (60) hide show
  1. package/lib/annotations/components/Annotation.d.ts +2 -3
  2. package/lib/annotations/components/Annotation.js +2 -9
  3. package/lib/commands/BaseCommandIDs.d.ts +1 -0
  4. package/lib/commands/BaseCommandIDs.js +1 -0
  5. package/lib/commands/index.js +15 -0
  6. package/lib/constants.js +1 -0
  7. package/lib/dialogs/symbology/components/color_ramp/ColorRamp.js +1 -1
  8. package/lib/dialogs/symbology/hooks/useGetProperties.js +53 -19
  9. package/lib/dialogs/symbology/vector_layer/VectorRendering.js +3 -3
  10. package/lib/dialogs/symbology/vector_layer/types/Graduated.js +4 -2
  11. package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +2 -2
  12. package/lib/formbuilder/formselectors.js +3 -0
  13. package/lib/formbuilder/objectform/source/geojsonsource.d.ts +3 -1
  14. package/lib/formbuilder/objectform/source/geojsonsource.js +20 -4
  15. package/lib/index.d.ts +1 -1
  16. package/lib/index.js +1 -1
  17. package/lib/keybindings.json +2 -2
  18. package/lib/mainview/mainView.d.ts +8 -1
  19. package/lib/mainview/mainView.js +33 -4
  20. package/lib/mainview/mainviewwidget.d.ts +11 -4
  21. package/lib/mainview/mainviewwidget.js +3 -2
  22. package/lib/menus.js +4 -0
  23. package/lib/panelview/annotationPanel.d.ts +3 -17
  24. package/lib/panelview/annotationPanel.js +5 -22
  25. package/lib/panelview/components/filter-panel/Filter.d.ts +2 -19
  26. package/lib/panelview/components/filter-panel/Filter.js +26 -59
  27. package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +6 -14
  28. package/lib/panelview/components/identify-panel/IdentifyPanel.js +14 -52
  29. package/lib/panelview/components/layers.d.ts +10 -12
  30. package/lib/panelview/components/layers.js +109 -79
  31. package/lib/panelview/index.d.ts +0 -1
  32. package/lib/panelview/index.js +0 -1
  33. package/lib/panelview/leftpanel.d.ts +8 -47
  34. package/lib/panelview/leftpanel.js +32 -154
  35. package/lib/panelview/objectproperties.d.ts +20 -15
  36. package/lib/panelview/objectproperties.js +12 -34
  37. package/lib/panelview/rightpanel.d.ts +8 -22
  38. package/lib/panelview/rightpanel.js +32 -77
  39. package/lib/shared/components/Tabs.d.ts +7 -1
  40. package/lib/shared/components/Tabs.js +6 -1
  41. package/lib/stacBrowser/components/{StacPanelView.d.ts → StacPanel.d.ts} +2 -2
  42. package/lib/stacBrowser/components/{StacPanelView.js → StacPanel.js} +3 -3
  43. package/lib/stacBrowser/index.d.ts +1 -1
  44. package/lib/stacBrowser/index.js +1 -1
  45. package/lib/tools.js +26 -0
  46. package/lib/types.d.ts +1 -9
  47. package/lib/widget.d.ts +8 -3
  48. package/lib/widget.js +8 -4
  49. package/package.json +4 -2
  50. package/style/base.css +18 -2
  51. package/style/shared/tabs.css +16 -2
  52. package/style/stacBrowser.css +0 -6
  53. package/style/tabPanel.css +91 -0
  54. package/style/temporalSlider.css +1 -0
  55. package/lib/panelview/model.d.ts +0 -19
  56. package/lib/panelview/model.js +0 -30
  57. package/lib/stacBrowser/StacBrowser.d.ts +0 -7
  58. package/lib/stacBrowser/StacBrowser.js +0 -16
  59. package/lib/stacBrowser/StacPanel.d.ts +0 -14
  60. package/lib/stacBrowser/StacPanel.js +0 -16
@@ -1,10 +1,9 @@
1
- import { IAnnotationModel } from '@jupytergis/schema';
1
+ import { IAnnotationModel, IJupyterGISModel } from '@jupytergis/schema';
2
2
  import React from 'react';
3
- import { IControlPanelModel } from "../../types";
4
3
  export interface IAnnotationProps {
5
4
  itemId: string;
6
5
  annotationModel: IAnnotationModel;
7
- rightPanelModel?: IControlPanelModel;
6
+ jgisModel?: IJupyterGISModel;
8
7
  children?: JSX.Element[] | JSX.Element;
9
8
  }
10
9
  declare const Annotation: React.FC<IAnnotationProps>;
@@ -4,17 +4,10 @@ import { showDialog, Dialog } from '@jupyterlab/apputils';
4
4
  import { Button } from '@jupyterlab/ui-components';
5
5
  import React, { useMemo, useState } from 'react';
6
6
  import { Message } from './Message';
7
- const Annotation = ({ itemId, annotationModel, rightPanelModel, children, }) => {
7
+ const Annotation = ({ itemId, annotationModel, jgisModel, children, }) => {
8
8
  const [messageContent, setMessageContent] = useState('');
9
- const [jgisModel, setJgisModel] = useState(rightPanelModel === null || rightPanelModel === void 0 ? void 0 : rightPanelModel.jGISModel);
10
9
  const annotation = annotationModel.getAnnotation(itemId);
11
10
  const contents = useMemo(() => { var _a; return (_a = annotation === null || annotation === void 0 ? void 0 : annotation.contents) !== null && _a !== void 0 ? _a : []; }, [annotation]);
12
- /**
13
- * Update the model when it changes.
14
- */
15
- rightPanelModel === null || rightPanelModel === void 0 ? void 0 : rightPanelModel.documentChanged.connect((_, widget) => {
16
- setJgisModel(widget === null || widget === void 0 ? void 0 : widget.model);
17
- });
18
11
  const handleSubmit = () => {
19
12
  annotationModel.addContent(itemId, messageContent);
20
13
  setMessageContent('');
@@ -53,7 +46,7 @@ const Annotation = ({ itemId, annotationModel, rightPanelModel, children, }) =>
53
46
  React.createElement("div", { className: "jGIS-Annotation-Buttons" },
54
47
  React.createElement(Button, { className: "jp-mod-styled jp-mod-warn", onClick: handleDelete },
55
48
  React.createElement(FontAwesomeIcon, { icon: faTrash })),
56
- rightPanelModel && (React.createElement(Button, { className: "jp-mod-styled jp-mod-accept", onClick: centerOnAnnotation },
49
+ jgisModel && (React.createElement(Button, { className: "jp-mod-styled jp-mod-accept", onClick: centerOnAnnotation },
57
50
  React.createElement(FontAwesomeIcon, { icon: faArrowsToDot }))),
58
51
  React.createElement(Button, { className: "jp-mod-styled jp-mod-accept", onClick: handleSubmit },
59
52
  React.createElement(FontAwesomeIcon, { icon: faPaperPlane })))));
@@ -14,6 +14,7 @@ export declare const newHillshadeEntry = "jupytergis:newHillshadeEntry";
14
14
  export declare const newImageEntry = "jupytergis:newImageEntry";
15
15
  export declare const newVideoEntry = "jupytergis:newVideoEntry";
16
16
  export declare const newGeoTiffEntry = "jupytergis:newGeoTiffEntry";
17
+ export declare const newGeoParquetEntry = "jupytergis:newGeoParquetEntry";
17
18
  export declare const renameLayer = "jupytergis:renameLayer";
18
19
  export declare const removeLayer = "jupytergis:removeLayer";
19
20
  export declare const renameGroup = "jupytergis:renameGroup";
@@ -21,6 +21,7 @@ export const newHillshadeEntry = 'jupytergis:newHillshadeEntry';
21
21
  export const newImageEntry = 'jupytergis:newImageEntry';
22
22
  export const newVideoEntry = 'jupytergis:newVideoEntry';
23
23
  export const newGeoTiffEntry = 'jupytergis:newGeoTiffEntry';
24
+ export const newGeoParquetEntry = 'jupytergis:newGeoParquetEntry';
24
25
  // Layer and group actions
25
26
  export const renameLayer = 'jupytergis:renameLayer';
26
27
  export const removeLayer = 'jupytergis:removeLayer';
@@ -198,6 +198,21 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
198
198
  sourceType: 'VectorTileSource',
199
199
  layerType: 'VectorTileLayer',
200
200
  }) }, icons.get(CommandIDs.newVectorTileEntry)));
201
+ commands.addCommand(CommandIDs.newGeoParquetEntry, Object.assign({ label: trans.__('New GeoParquet Layer'), isEnabled: () => {
202
+ return tracker.currentWidget
203
+ ? tracker.currentWidget.model.sharedModel.editable
204
+ : false;
205
+ }, execute: Private.createEntry({
206
+ tracker,
207
+ formSchemaRegistry,
208
+ title: 'Create GeoParquet Layer',
209
+ createLayer: true,
210
+ createSource: true,
211
+ sourceData: { name: 'Custom GeoParquet Source' },
212
+ layerData: { name: 'Custom GeoParquet Layer' },
213
+ sourceType: 'GeoParquetSource',
214
+ layerType: 'VectorLayer',
215
+ }) }, icons.get(CommandIDs.newGeoParquetEntry)));
201
216
  commands.addCommand(CommandIDs.newGeoJSONEntry, Object.assign({ label: trans.__('New GeoJSON layer'), isEnabled: () => {
202
217
  return tracker.currentWidget
203
218
  ? tracker.currentWidget.model.sharedModel.editable
package/lib/constants.js CHANGED
@@ -30,6 +30,7 @@ const iconObject = {
30
30
  [CommandIDs.newVideoEntry]: { iconClass: 'fa fa-video' },
31
31
  [CommandIDs.newShapefileEntry]: { iconClass: 'fa fa-file' },
32
32
  [CommandIDs.newGeoTiffEntry]: { iconClass: 'fa fa-image' },
33
+ [CommandIDs.newGeoParquetEntry]: { iconClass: 'fa fa-file' },
33
34
  [CommandIDs.symbology]: { iconClass: 'fa fa-brush' },
34
35
  [CommandIDs.identify]: { icon: infoIcon },
35
36
  [CommandIDs.temporalController]: { icon: clockIcon },
@@ -20,7 +20,7 @@ const ColorRamp = ({ layerParams, modeOptions, classifyFunc, showModeRow, showRa
20
20
  }
21
21
  setNumberOfShades(nClasses ? nClasses : '9');
22
22
  setSelectedMode(singleBandMode ? singleBandMode : 'equal interval');
23
- setSelectedRamp(colorRamp ? colorRamp : 'cool');
23
+ setSelectedRamp(colorRamp ? colorRamp : 'viridis');
24
24
  };
25
25
  return (React.createElement("div", { className: "jp-gis-color-ramp-container" },
26
26
  showRampSelector && (React.createElement("div", { className: "jp-gis-symbology-row" },
@@ -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 data = await loadFile({
20
- filepath: (_b = source.parameters) === null || _b === void 0 ? void 0 : _b.path,
21
- type: 'GeoJSONSource',
22
- model: model,
23
- });
24
- if (!data) {
25
- throw new Error('Failed to read GeoJSON data');
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
@@ -14,7 +14,7 @@ const Heatmap = ({ model, state, okSignalPromise, cancel, layerId, }) => {
14
14
  radius: 8,
15
15
  blur: 15,
16
16
  });
17
- const selectedRampRef = useRef('cool');
17
+ const selectedRampRef = useRef('viridis');
18
18
  const heatmapOptionsRef = useRef({
19
19
  radius: 8,
20
20
  blur: 15,
@@ -40,7 +40,7 @@ const Heatmap = ({ model, state, okSignalPromise, cancel, layerId, }) => {
40
40
  if ((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState) {
41
41
  colorRamp = layer.parameters.symbologyState.colorRamp;
42
42
  }
43
- setSelectedRamp(colorRamp ? colorRamp : 'cool');
43
+ setSelectedRamp(colorRamp ? colorRamp : 'viridis');
44
44
  };
45
45
  const handleOk = () => {
46
46
  if (!layer.parameters) {
@@ -38,6 +38,9 @@ export function getSourceTypeForm(sourceType) {
38
38
  case 'VectorTileSource':
39
39
  SourceForm = TileSourcePropertiesForm;
40
40
  break;
41
+ case 'GeoParquetSource':
42
+ SourceForm = PathBasedSourcePropertiesForm;
43
+ break;
41
44
  // ADD MORE FORM TYPES HERE
42
45
  }
43
46
  return SourceForm;
@@ -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 = false;
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/index.d.ts CHANGED
@@ -8,8 +8,8 @@ export * from './icons';
8
8
  export * from './mainview';
9
9
  export * from './menus';
10
10
  export * from './panelview';
11
- export * from './stacBrowser';
12
11
  export * from './store';
12
+ export * from './stacBrowser';
13
13
  export * from './toolbar';
14
14
  export * from './tools';
15
15
  export * from './types';
package/lib/index.js CHANGED
@@ -8,8 +8,8 @@ export * from './icons';
8
8
  export * from './mainview';
9
9
  export * from './menus';
10
10
  export * from './panelview';
11
- export * from './stacBrowser';
12
11
  export * from './store';
12
+ export * from './stacBrowser';
13
13
  export * from './toolbar';
14
14
  export * from './tools';
15
15
  export * from './types';
@@ -37,7 +37,7 @@
37
37
  {
38
38
  "command": "jupytergis:renameLayer",
39
39
  "keys": ["F2"],
40
- "selector": ".data-jgis-keybinding .jp-gis-layerItem"
40
+ "selector": ".jp-gis-layerItem"
41
41
  },
42
42
  {
43
43
  "command": "jupytergis:removeGroup",
@@ -47,7 +47,7 @@
47
47
  {
48
48
  "command": "jupytergis:renameGroup",
49
49
  "keys": ["F2"],
50
- "selector": ".data-jgis-keybinding .jp-gis-layerGroupHeader"
50
+ "selector": ".jp-gis-layerGroupHeader"
51
51
  },
52
52
  {
53
53
  "command": "jupytergis:executeConsole",
@@ -1,11 +1,15 @@
1
- import { IAnnotation, IDict, IJGISFilterItem, IJGISLayer, IJGISSource } from '@jupytergis/schema';
1
+ import { IAnnotation, IAnnotationModel, IDict, IJGISFilterItem, IJGISFormSchemaRegistry, IJGISLayer, IJGISSource } from '@jupytergis/schema';
2
2
  import { User } from '@jupyterlab/services';
3
+ import { IStateDB } from '@jupyterlab/statedb';
3
4
  import { Layer } from 'ol/layer';
4
5
  import * as React from 'react';
5
6
  import { ClientPointer } from './CollaboratorPointers';
6
7
  import { MainViewModel } from './mainviewmodel';
7
8
  interface IProps {
8
9
  viewModel: MainViewModel;
10
+ state?: IStateDB;
11
+ formSchemaRegistry?: IJGISFormSchemaRegistry;
12
+ annotationModel?: IAnnotationModel;
9
13
  }
10
14
  interface IStates {
11
15
  id: string;
@@ -194,5 +198,8 @@ export declare class MainView extends React.Component<IProps, IStates> {
194
198
  private _originalFeatures;
195
199
  private _highlightLayer;
196
200
  private _updateCenter;
201
+ private _state?;
202
+ private _formSchemaRegistry?;
203
+ private _annotationModel?;
197
204
  }
198
205
  export {};
@@ -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';
@@ -15,9 +15,8 @@ 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
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';
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';
@@ -33,6 +32,7 @@ import { debounce, isLightTheme, loadFile, throttle } from "../tools";
33
32
  import CollaboratorPointers from './CollaboratorPointers';
34
33
  import { FollowIndicator } from './FollowIndicator';
35
34
  import TemporalSlider from './TemporalSlider';
35
+ import { LeftPanel, RightPanel } from '../panelview';
36
36
  export class MainView extends React.Component {
37
37
  constructor(props) {
38
38
  super(props);
@@ -441,6 +441,9 @@ export class MainView extends React.Component {
441
441
  this._ready = false;
442
442
  this._sourceToLayerMap = new Map();
443
443
  this._originalFeatures = {};
444
+ this._state = props.state;
445
+ this._formSchemaRegistry = props.formSchemaRegistry;
446
+ this._annotationModel = props.annotationModel;
444
447
  // Enforce the map to take the full available width in the case of Jupyter Notebook viewer
445
448
  const el = document.getElementById('main-panel');
446
449
  if (el) {
@@ -713,6 +716,13 @@ export class MainView extends React.Component {
713
716
  url: url,
714
717
  });
715
718
  }
719
+ newSource.on('tileloadend', (event) => {
720
+ const tile = event.tile;
721
+ const features = tile.getFeatures();
722
+ if (features && features.length > 0) {
723
+ this._model.syncTileFeatures({ sourceId: id, features });
724
+ }
725
+ });
716
726
  break;
717
727
  }
718
728
  case 'GeoJSONSource': {
@@ -819,6 +829,23 @@ export class MainView extends React.Component {
819
829
  });
820
830
  break;
821
831
  }
832
+ case 'GeoParquetSource': {
833
+ const parameters = source.parameters;
834
+ const geojson = await loadFile({
835
+ filepath: parameters.path,
836
+ type: 'GeoParquetSource',
837
+ model: this._model,
838
+ });
839
+ const geojsonData = Array.isArray(geojson) ? geojson[0] : geojson;
840
+ const format = new GeoJSON();
841
+ newSource = new VectorSource({
842
+ features: format.readFeatures(geojsonData, {
843
+ dataProjection: parameters.projection,
844
+ featureProjection: this._Map.getView().getProjection(),
845
+ }),
846
+ });
847
+ break;
848
+ }
822
849
  }
823
850
  newSource.set('id', id);
824
851
  // _sources is a list of OpenLayers sources
@@ -1642,6 +1669,8 @@ export class MainView extends React.Component {
1642
1669
  width: '100%',
1643
1670
  height: '100%',
1644
1671
  } })),
1645
- React.createElement(StatusBar, { jgisModel: this._model, loading: this.state.loadingLayer, projection: this.state.viewProjection, scale: this.state.scale }))));
1672
+ React.createElement(StatusBar, { jgisModel: this._model, loading: this.state.loadingLayer, projection: this.state.viewProjection, scale: this.state.scale })),
1673
+ this._state && (React.createElement(LeftPanel, { model: this._model, commands: this._mainViewModel.commands, state: this._state })),
1674
+ this._formSchemaRegistry && this._annotationModel && (React.createElement(RightPanel, { model: this._model, formSchemaRegistry: this._formSchemaRegistry, annotationModel: this._annotationModel }))));
1646
1675
  }
1647
1676
  }
@@ -1,12 +1,19 @@
1
+ import { IAnnotationModel, IJGISFormSchemaRegistry } from '@jupytergis/schema';
1
2
  import { ReactWidget } from '@jupyterlab/apputils';
3
+ import { IStateDB } from '@jupyterlab/statedb';
2
4
  import { MainViewModel } from './mainviewmodel';
5
+ export interface IOptions {
6
+ mainViewModel: MainViewModel;
7
+ state?: IStateDB;
8
+ formSchemaRegistry?: IJGISFormSchemaRegistry;
9
+ annotationModel?: IAnnotationModel;
10
+ }
3
11
  export declare class JupyterGISMainViewPanel extends ReactWidget {
4
12
  /**
5
13
  * Construct a `JupyterGISPanel`.
6
14
  */
7
- constructor(options: {
8
- mainViewModel: MainViewModel;
9
- });
15
+ constructor(options: IOptions);
10
16
  render(): JSX.Element;
11
- private _mainViewModel;
17
+ private _state?;
18
+ private _options;
12
19
  }
@@ -7,10 +7,11 @@ export class JupyterGISMainViewPanel extends ReactWidget {
7
7
  */
8
8
  constructor(options) {
9
9
  super();
10
- this._mainViewModel = options.mainViewModel;
10
+ this._state = options.state;
11
11
  this.addClass('jp-jupytergis-panel');
12
+ this._options = options;
12
13
  }
13
14
  render() {
14
- return React.createElement(MainView, { viewModel: this._mainViewModel });
15
+ return (React.createElement(MainView, { state: this._state, viewModel: this._options.mainViewModel, formSchemaRegistry: this._options.formSchemaRegistry, annotationModel: this._options.annotationModel }));
15
16
  }
16
17
  }
package/lib/menus.js CHANGED
@@ -18,6 +18,10 @@ export const vectorSubMenu = (commands) => {
18
18
  type: 'command',
19
19
  command: CommandIDs.newShapefileEntry,
20
20
  });
21
+ subMenu.addItem({
22
+ type: 'command',
23
+ command: CommandIDs.newGeoParquetEntry,
24
+ });
21
25
  return subMenu;
22
26
  };
23
27
  export const rasterSubMenu = (commands) => {
@@ -1,27 +1,13 @@
1
- import { IAnnotationModel } from '@jupytergis/schema';
2
- import { PanelWithToolbar } from '@jupyterlab/ui-components';
1
+ import { IAnnotationModel, IJupyterGISModel } from '@jupytergis/schema';
3
2
  import { Component } from 'react';
4
- import { IControlPanelModel } from "../types";
5
3
  interface IAnnotationPanelProps {
6
4
  annotationModel: IAnnotationModel;
7
- rightPanelModel: IControlPanelModel;
5
+ jgisModel: IJupyterGISModel;
8
6
  }
9
7
  export declare class AnnotationsPanel extends Component<IAnnotationPanelProps> {
10
8
  constructor(props: IAnnotationPanelProps);
11
9
  render(): JSX.Element;
12
10
  private _annotationModel;
13
- private _rightPanelModel;
14
- }
15
- export declare class Annotations extends PanelWithToolbar {
16
- constructor(options: Annotations.IOptions);
17
- private _widget;
18
- private _annotationModel;
19
- private _rightPanelModel;
20
- }
21
- export declare namespace Annotations {
22
- interface IOptions {
23
- annotationModel: IAnnotationModel;
24
- rightPanelModel: IControlPanelModel;
25
- }
11
+ private _jgisModel;
26
12
  }
27
13
  export {};
@@ -1,22 +1,16 @@
1
- import { PanelWithToolbar, ReactWidget } from '@jupyterlab/ui-components';
2
1
  import React, { Component } from 'react';
3
2
  import Annotation from "../annotations/components/Annotation";
4
3
  export class AnnotationsPanel extends Component {
5
4
  constructor(props) {
5
+ var _a, _b;
6
6
  super(props);
7
7
  const updateCallback = () => {
8
8
  this.forceUpdate();
9
9
  };
10
10
  this._annotationModel = props.annotationModel;
11
- this._rightPanelModel = props.rightPanelModel;
12
- this._annotationModel.modelChanged.connect(async () => {
13
- // await this._annotationModel?.context?.ready;
14
- var _a, _b, _c, _d;
15
- (_b = (_a = this._annotationModel) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.sharedMetadataChanged.disconnect(updateCallback);
16
- this._annotationModel = props.annotationModel;
17
- (_d = (_c = this._annotationModel) === null || _c === void 0 ? void 0 : _c.model) === null || _d === void 0 ? void 0 : _d.sharedMetadataChanged.connect(updateCallback);
18
- this.forceUpdate();
19
- });
11
+ this._jgisModel = props.jgisModel;
12
+ (_b = (_a = this._annotationModel) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.sharedMetadataChanged.connect(updateCallback);
13
+ this.forceUpdate();
20
14
  }
21
15
  render() {
22
16
  var _a;
@@ -26,20 +20,9 @@ export class AnnotationsPanel extends Component {
26
20
  }
27
21
  const annotations = annotationIds.map((id) => {
28
22
  return (React.createElement("div", null,
29
- React.createElement(Annotation, { rightPanelModel: this._rightPanelModel, annotationModel: this._annotationModel, itemId: id }),
23
+ React.createElement(Annotation, { jgisModel: this._jgisModel, annotationModel: this._annotationModel, itemId: id }),
30
24
  React.createElement("hr", { className: "jGIS-Annotations-Separator" })));
31
25
  });
32
26
  return React.createElement("div", { className: "jgis-scrollable" }, annotations);
33
27
  }
34
28
  }
35
- export class Annotations extends PanelWithToolbar {
36
- constructor(options) {
37
- super({});
38
- this.title.label = 'Annotations';
39
- this.addClass('jgis-scrollable');
40
- this._annotationModel = options.annotationModel;
41
- this._rightPanelModel = options.rightPanelModel;
42
- this._widget = ReactWidget.create(React.createElement(AnnotationsPanel, { rightPanelModel: this._rightPanelModel, annotationModel: this._annotationModel }));
43
- this.addWidget(this._widget);
44
- }
45
- }
@@ -1,24 +1,7 @@
1
- import { IJupyterGISTracker } from '@jupytergis/schema';
2
- import { Panel } from '@lumino/widgets';
1
+ import { IJupyterGISModel } from '@jupytergis/schema';
3
2
  import React from 'react';
4
- import { IControlPanelModel } from "../../../types";
5
- /**
6
- * The filters panel widget.
7
- */
8
- export declare class FilterPanel extends Panel {
9
- constructor(options: FilterPanel.IOptions);
10
- private _model;
11
- private _tracker;
12
- }
13
- export declare namespace FilterPanel {
14
- interface IOptions {
15
- model: IControlPanelModel;
16
- tracker: IJupyterGISTracker;
17
- }
18
- }
19
3
  interface IFilterComponentProps {
20
- model: IControlPanelModel;
21
- tracker: IJupyterGISTracker;
4
+ model: IJupyterGISModel;
22
5
  }
23
6
  declare const FilterComponent: React.FC<IFilterComponentProps>;
24
7
  export default FilterComponent;