@jupytergis/base 0.1.6 → 0.2.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 (96) hide show
  1. package/lib/annotations/components/Annotation.d.ts +11 -0
  2. package/lib/annotations/components/Annotation.js +61 -0
  3. package/lib/annotations/components/AnnotationFloater.d.ts +7 -0
  4. package/lib/annotations/components/AnnotationFloater.js +30 -0
  5. package/lib/annotations/components/Message.d.ts +8 -0
  6. package/lib/annotations/components/Message.js +17 -0
  7. package/lib/annotations/index.d.ts +3 -0
  8. package/lib/annotations/index.js +3 -0
  9. package/lib/annotations/model.d.ts +28 -0
  10. package/lib/annotations/model.js +67 -0
  11. package/lib/classificationModes.d.ts +13 -0
  12. package/lib/classificationModes.js +326 -0
  13. package/lib/commands.js +52 -7
  14. package/lib/constants.d.ts +2 -0
  15. package/lib/constants.js +5 -1
  16. package/lib/dialogs/symbology/classificationModes.d.ts +13 -0
  17. package/lib/dialogs/symbology/classificationModes.js +326 -0
  18. package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.d.ts +11 -0
  19. package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.js +119 -0
  20. package/lib/dialogs/symbology/components/color_ramp/ColorRamp.d.ts +15 -0
  21. package/lib/dialogs/symbology/components/color_ramp/ColorRamp.js +33 -0
  22. package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.d.ts +9 -0
  23. package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.js +24 -0
  24. package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.d.ts +10 -0
  25. package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.js +11 -0
  26. package/lib/dialogs/symbology/components/color_stops/StopContainer.d.ts +9 -0
  27. package/lib/dialogs/symbology/components/color_stops/StopContainer.js +28 -0
  28. package/lib/dialogs/{components/symbology → symbology/components/color_stops}/StopRow.js +9 -2
  29. package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +12 -0
  30. package/lib/dialogs/symbology/hooks/useGetProperties.js +47 -0
  31. package/lib/dialogs/{symbologyDialog.js → symbology/symbologyDialog.js} +3 -3
  32. package/lib/dialogs/symbology/symbologyUtils.d.ts +9 -0
  33. package/lib/dialogs/symbology/symbologyUtils.js +94 -0
  34. package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +4 -0
  35. package/lib/dialogs/{components/symbology/BandRendering.js → symbology/tiff_layer/TiffRendering.js} +3 -3
  36. package/lib/dialogs/{components/symbology → symbology/tiff_layer/components}/BandRow.d.ts +1 -1
  37. package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.d.ts +9 -1
  38. package/lib/dialogs/{components/symbology → symbology/tiff_layer/types}/SingleBandPseudoColor.js +131 -83
  39. package/lib/dialogs/{components/symbology → symbology/vector_layer}/VectorRendering.d.ts +1 -1
  40. package/lib/dialogs/{components/symbology → symbology/vector_layer}/VectorRendering.js +10 -13
  41. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.d.ts +8 -0
  42. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.js +7 -0
  43. package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +4 -0
  44. package/lib/dialogs/symbology/vector_layer/types/Categorized.js +94 -0
  45. package/lib/dialogs/symbology/vector_layer/types/Graduated.js +169 -0
  46. package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/SimpleSymbol.js +8 -13
  47. package/lib/formbuilder/formselectors.js +4 -0
  48. package/lib/formbuilder/objectform/baseform.d.ts +1 -1
  49. package/lib/formbuilder/objectform/baseform.js +31 -42
  50. package/lib/formbuilder/objectform/geojsonsource.js +33 -30
  51. package/lib/formbuilder/objectform/geotiffsource.d.ts +16 -0
  52. package/lib/formbuilder/objectform/geotiffsource.js +71 -0
  53. package/lib/formbuilder/objectform/vectorlayerform.js +1 -0
  54. package/lib/formbuilder/objectform/webGlLayerForm.js +1 -0
  55. package/lib/index.d.ts +7 -4
  56. package/lib/index.js +7 -4
  57. package/lib/mainview/CollaboratorPointers.d.ts +17 -0
  58. package/lib/mainview/CollaboratorPointers.js +37 -0
  59. package/lib/mainview/FollowIndicator.d.ts +7 -0
  60. package/lib/mainview/FollowIndicator.js +9 -0
  61. package/lib/mainview/mainView.d.ts +39 -3
  62. package/lib/mainview/mainView.js +451 -41
  63. package/lib/mainview/mainviewmodel.d.ts +2 -1
  64. package/lib/mainview/mainviewmodel.js +5 -0
  65. package/lib/panelview/annotationPanel.d.ts +27 -0
  66. package/lib/panelview/annotationPanel.js +45 -0
  67. package/lib/panelview/components/filter-panel/Filter.d.ts +7 -2
  68. package/lib/panelview/components/filter-panel/Filter.js +1 -1
  69. package/lib/panelview/components/filter-panel/FilterRow.js +3 -3
  70. package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +15 -0
  71. package/lib/panelview/components/identify-panel/IdentifyPanel.js +108 -0
  72. package/lib/panelview/components/layers.js +4 -4
  73. package/lib/panelview/leftpanel.js +8 -0
  74. package/lib/panelview/rightpanel.d.ts +4 -1
  75. package/lib/panelview/rightpanel.js +28 -7
  76. package/lib/store.d.ts +9 -0
  77. package/lib/store.js +25 -0
  78. package/lib/toolbar/widget.js +12 -2
  79. package/lib/tools.d.ts +35 -0
  80. package/lib/tools.js +86 -0
  81. package/lib/types.d.ts +14 -0
  82. package/package.json +18 -20
  83. package/style/base.css +4 -8
  84. package/style/dialog.css +1 -1
  85. package/style/icons/logo_mini.svg +70 -148
  86. package/style/icons/nonvisibility.svg +2 -7
  87. package/style/icons/visibility.svg +2 -6
  88. package/style/leftPanel.css +5 -0
  89. package/style/symbologyDialog.css +104 -3
  90. package/lib/dialogs/components/symbology/BandRendering.d.ts +0 -4
  91. package/lib/dialogs/components/symbology/Graduated.js +0 -188
  92. /package/lib/dialogs/{components/symbology → symbology/components/color_stops}/StopRow.d.ts +0 -0
  93. /package/lib/dialogs/{symbologyDialog.d.ts → symbology/symbologyDialog.d.ts} +0 -0
  94. /package/lib/dialogs/{components/symbology → symbology/tiff_layer/components}/BandRow.js +0 -0
  95. /package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/Graduated.d.ts +0 -0
  96. /package/lib/dialogs/{components/symbology → symbology/vector_layer/types}/SimpleSymbol.d.ts +0 -0
@@ -0,0 +1,169 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { VectorClassifications } from '../../classificationModes';
3
+ import ColorRamp from '../../components/color_ramp/ColorRamp';
4
+ import ValueSelect from '../components/ValueSelect';
5
+ import StopContainer from '../../components/color_stops/StopContainer';
6
+ import { useGetProperties } from '../../hooks/useGetProperties';
7
+ import { Utils, VectorUtils } from '../../symbologyUtils';
8
+ const Graduated = ({ context, state, okSignalPromise, cancel, layerId }) => {
9
+ const modeOptions = [
10
+ 'quantile',
11
+ 'equal interval',
12
+ 'jenks',
13
+ 'pretty',
14
+ 'logarithmic'
15
+ ];
16
+ const selectedValueRef = useRef();
17
+ const selectedMethodRef = useRef();
18
+ const stopRowsRef = useRef();
19
+ const colorRampOptionsRef = useRef();
20
+ const [selectedValue, setSelectedValue] = useState('');
21
+ const [selectedMethod, setSelectedMethod] = useState('color');
22
+ const [stopRows, setStopRows] = useState([]);
23
+ const [methodOptions, setMethodOptions] = useState(['color']);
24
+ const [colorRampOptions, setColorRampOptions] = useState();
25
+ if (!layerId) {
26
+ return;
27
+ }
28
+ const layer = context.model.getLayer(layerId);
29
+ if (!(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
30
+ return;
31
+ }
32
+ const { featureProps } = useGetProperties({
33
+ layerId,
34
+ model: context.model
35
+ });
36
+ useEffect(() => {
37
+ var _a, _b;
38
+ let stopOutputPairs = [];
39
+ const layerParams = layer.parameters;
40
+ const method = (_b = (_a = layerParams.symbologyState) === null || _a === void 0 ? void 0 : _a.method) !== null && _b !== void 0 ? _b : 'color';
41
+ if (method === 'color') {
42
+ stopOutputPairs = VectorUtils.buildColorInfo(layer);
43
+ }
44
+ if (method === 'radius') {
45
+ stopOutputPairs = VectorUtils.buildRadiusInfo(layer);
46
+ }
47
+ setStopRows(stopOutputPairs);
48
+ okSignalPromise.promise.then(okSignal => {
49
+ okSignal.connect(handleOk, this);
50
+ });
51
+ return () => {
52
+ okSignalPromise.promise.then(okSignal => {
53
+ okSignal.disconnect(handleOk, this);
54
+ });
55
+ };
56
+ }, []);
57
+ useEffect(() => {
58
+ selectedValueRef.current = selectedValue;
59
+ selectedMethodRef.current = selectedMethod;
60
+ stopRowsRef.current = stopRows;
61
+ colorRampOptionsRef.current = colorRampOptions;
62
+ }, [selectedValue, selectedMethod, stopRows, colorRampOptions]);
63
+ useEffect(() => {
64
+ populateOptions();
65
+ }, [featureProps]);
66
+ const populateOptions = async () => {
67
+ var _a, _b, _c, _d, _e;
68
+ // Set up method options
69
+ if (((_a = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _a === void 0 ? void 0 : _a.type) === 'circle') {
70
+ const options = ['color', 'radius'];
71
+ setMethodOptions(options);
72
+ }
73
+ const layerParams = layer.parameters;
74
+ const value = (_c = (_b = layerParams.symbologyState) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : Object.keys(featureProps)[0];
75
+ const method = (_e = (_d = layerParams.symbologyState) === null || _d === void 0 ? void 0 : _d.method) !== null && _e !== void 0 ? _e : 'color';
76
+ setSelectedValue(value);
77
+ setSelectedMethod(method);
78
+ };
79
+ const handleOk = () => {
80
+ var _a, _b, _c, _d;
81
+ if (!layer.parameters) {
82
+ return;
83
+ }
84
+ const colorExpr = [];
85
+ colorExpr.push('interpolate');
86
+ colorExpr.push(['linear']);
87
+ colorExpr.push(['get', selectedValueRef.current]);
88
+ (_a = stopRowsRef.current) === null || _a === void 0 ? void 0 : _a.map(stop => {
89
+ colorExpr.push(stop.stop);
90
+ colorExpr.push(stop.output);
91
+ });
92
+ const newStyle = Object.assign({}, layer.parameters.color);
93
+ if (selectedMethodRef.current === 'color') {
94
+ if (layer.parameters.type === 'fill') {
95
+ newStyle['fill-color'] = colorExpr;
96
+ }
97
+ if (layer.parameters.type === 'line') {
98
+ newStyle['stroke-color'] = colorExpr;
99
+ }
100
+ if (layer.parameters.type === 'circle') {
101
+ newStyle['circle-fill-color'] = colorExpr;
102
+ }
103
+ }
104
+ if (selectedMethodRef.current === 'radius') {
105
+ if (layer.parameters.type === 'circle') {
106
+ newStyle['circle-radius'] = colorExpr;
107
+ }
108
+ }
109
+ const symbologyState = {
110
+ renderType: 'Graduated',
111
+ value: selectedValueRef.current,
112
+ method: selectedMethodRef.current,
113
+ colorRamp: (_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.selectedRamp,
114
+ nClasses: (_c = colorRampOptionsRef.current) === null || _c === void 0 ? void 0 : _c.numberOfShades,
115
+ mode: (_d = colorRampOptionsRef.current) === null || _d === void 0 ? void 0 : _d.selectedMode
116
+ };
117
+ layer.parameters.symbologyState = symbologyState;
118
+ layer.parameters.color = newStyle;
119
+ context.model.sharedModel.updateLayer(layerId, layer);
120
+ cancel();
121
+ };
122
+ const buildColorInfoFromClassification = (selectedMode, numberOfShades, selectedRamp) => {
123
+ setColorRampOptions({
124
+ selectedRamp,
125
+ numberOfShades,
126
+ selectedMode
127
+ });
128
+ let stops;
129
+ const values = Array.from(featureProps[selectedValue]);
130
+ switch (selectedMode) {
131
+ case 'quantile':
132
+ stops = VectorClassifications.calculateQuantileBreaks(values, +numberOfShades);
133
+ break;
134
+ case 'equal interval':
135
+ stops = VectorClassifications.calculateEqualIntervalBreaks(values, +numberOfShades);
136
+ break;
137
+ case 'jenks':
138
+ stops = VectorClassifications.calculateJenksBreaks(values, +numberOfShades);
139
+ break;
140
+ case 'pretty':
141
+ stops = VectorClassifications.calculatePrettyBreaks(values, +numberOfShades);
142
+ break;
143
+ case 'logarithmic':
144
+ stops = VectorClassifications.calculateLogarithmicBreaks(values, +numberOfShades);
145
+ break;
146
+ default:
147
+ console.warn('No mode selected');
148
+ return;
149
+ }
150
+ let stopOutputPairs = [];
151
+ if (selectedMethod === 'radius') {
152
+ for (let i = 0; i < +numberOfShades; i++) {
153
+ stopOutputPairs.push({ stop: stops[i], output: stops[i] });
154
+ }
155
+ }
156
+ else {
157
+ stopOutputPairs = Utils.getValueColorPairs(stops, selectedRamp, +numberOfShades);
158
+ }
159
+ setStopRows(stopOutputPairs);
160
+ };
161
+ return (React.createElement("div", { className: "jp-gis-layer-symbology-container" },
162
+ React.createElement(ValueSelect, { featureProperties: featureProps, selectedValue: selectedValue, setSelectedValue: setSelectedValue }),
163
+ React.createElement("div", { className: "jp-gis-symbology-row" },
164
+ React.createElement("label", { htmlFor: 'vector-method-select' }, "Method:"),
165
+ React.createElement("select", { name: 'vector-method-select', onChange: event => setSelectedMethod(event.target.value), className: "jp-mod-styled" }, methodOptions.map((method, index) => (React.createElement("option", { key: index, value: method, selected: method === selectedMethod, className: "jp-mod-styled" }, method))))),
166
+ React.createElement(ColorRamp, { layerParams: layer.parameters, modeOptions: modeOptions, classifyFunc: buildColorInfoFromClassification, showModeRow: true }),
167
+ React.createElement(StopContainer, { selectedMethod: selectedMethod, stopRows: stopRows, setStopRows: setStopRows })));
168
+ };
169
+ export default Graduated;
@@ -1,9 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { parseColor } from '../../../tools';
2
+ import { parseColor } from '../../../../tools';
3
3
  const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
4
4
  const styleRef = useRef();
5
- const layerStateRef = useRef();
6
- const [layerState, setLayerState] = useState();
7
5
  const [useCircleStuff, setUseCircleStuff] = useState(false);
8
6
  const [style, setStyle] = useState({
9
7
  fillColor: '#3399CC',
@@ -31,16 +29,11 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
31
29
  // Read values from file if we chose them using the single symbol thing
32
30
  // but if we're switching to simple symbol, use defaults
33
31
  const initStyle = async () => {
32
+ var _a;
34
33
  if (!layer.parameters) {
35
34
  return;
36
35
  }
37
- const layerState = await state.fetch(`jupytergis:${layerId}`);
38
- if (!layerState) {
39
- return;
40
- }
41
- setLayerState(layerState);
42
- const renderType = layerState
43
- .renderType;
36
+ const renderType = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.symbologyState.renderType;
44
37
  if (renderType === 'Single Symbol') {
45
38
  // Read from current color or use defaults
46
39
  const parsedStyle = parseColor(layer.parameters.type, layer.parameters.color);
@@ -61,14 +54,12 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
61
54
  }, []);
62
55
  useEffect(() => {
63
56
  styleRef.current = style;
64
- layerStateRef.current = layerState;
65
- }, [style, layerState]);
57
+ }, [style]);
66
58
  const handleOk = () => {
67
59
  var _a, _b, _c, _d, _e, _f;
68
60
  if (!layer.parameters) {
69
61
  return;
70
62
  }
71
- state.save(`jupytergis:${layerId}`, Object.assign(Object.assign({}, layerStateRef.current), { renderType: 'Single Symbol' }));
72
63
  const styleExpr = {};
73
64
  const prefix = layer.parameters.type === 'circle' ? 'circle-' : '';
74
65
  if (layer.parameters.type === 'circle') {
@@ -79,6 +70,10 @@ const SimpleSymbol = ({ context, state, okSignalPromise, cancel, layerId }) => {
79
70
  styleExpr[`${prefix}stroke-width`] = (_d = styleRef.current) === null || _d === void 0 ? void 0 : _d.strokeWidth;
80
71
  styleExpr[`${prefix}stroke-line-join`] = (_e = styleRef.current) === null || _e === void 0 ? void 0 : _e.joinStyle;
81
72
  styleExpr[`${prefix}stroke-line-cap`] = (_f = styleRef.current) === null || _f === void 0 ? void 0 : _f.capStyle;
73
+ const symbologyState = {
74
+ renderType: 'Single Symbol'
75
+ };
76
+ layer.parameters.symbologyState = symbologyState;
82
77
  layer.parameters.color = styleExpr;
83
78
  context.model.sharedModel.updateLayer(layerId, layer);
84
79
  cancel();
@@ -5,6 +5,7 @@ import { LayerPropertiesForm } from './objectform/layerform';
5
5
  import { TileSourcePropertiesForm } from './objectform/tilesourceform';
6
6
  import { VectorLayerPropertiesForm } from './objectform/vectorlayerform';
7
7
  import { WebGlLayerPropertiesForm } from './objectform/webGlLayerForm';
8
+ import { GeoTiffSourcePropertiesForm } from './objectform/geotiffsource';
8
9
  export function getLayerTypeForm(layerType) {
9
10
  let LayerForm = LayerPropertiesForm;
10
11
  switch (layerType) {
@@ -28,6 +29,9 @@ export function getSourceTypeForm(sourceType) {
28
29
  case 'GeoJSONSource':
29
30
  SourceForm = GeoJSONSourcePropertiesForm;
30
31
  break;
32
+ case 'GeoTiffSource':
33
+ SourceForm = GeoTiffSourcePropertiesForm;
34
+ break;
31
35
  case 'RasterSource':
32
36
  case 'VectorTileSource':
33
37
  SourceForm = TileSourcePropertiesForm;
@@ -52,7 +52,6 @@ export interface IBaseFormProps {
52
52
  */
53
53
  formErrorSignal?: Signal<Dialog<any>, boolean>;
54
54
  }
55
- export declare const LuminoSchemaForm: (props: React.PropsWithChildren<any>) => JSX.Element;
56
55
  /**
57
56
  * Generate a form to edit a layer/source type. This class is meant to be sub-classed to create more refined forms for specific layers/sources.
58
57
  *
@@ -61,6 +60,7 @@ export declare const LuminoSchemaForm: (props: React.PropsWithChildren<any>) =>
61
60
  export declare class BaseForm extends React.Component<IBaseFormProps, IBaseFormStates> {
62
61
  constructor(props: IBaseFormProps);
63
62
  componentDidUpdate(prevProps: IBaseFormProps, prevState: IBaseFormStates): void;
63
+ componentDidMount(): void;
64
64
  protected processSchema(data: IDict<any> | undefined, schema: IDict, uiSchema: IDict): void;
65
65
  /**
66
66
  * Remove a specific entry from the form. Can be used in subclasses if needed while under processSchema.
@@ -1,35 +1,21 @@
1
- import { SchemaForm } from '@deathbeds/jupyterlab-rjsf';
2
- import { MessageLoop } from '@lumino/messaging';
3
- import { Widget } from '@lumino/widgets';
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { FormComponent } from '@jupyterlab/ui-components';
13
+ import validatorAjv8 from '@rjsf/validator-ajv8';
4
14
  import * as React from 'react';
5
15
  import { deepCopy } from '../../tools';
6
- // Reusing the datalayer/jupyter-react component:
7
- // https://github.com/datalayer/jupyter-react/blob/main/packages/react/src/jupyter/lumino/Lumino.tsx
8
- export const LuminoSchemaForm = (props) => {
9
- const ref = React.useRef(null);
10
- const { children } = props;
11
- React.useEffect(() => {
12
- const widget = children;
13
- try {
14
- MessageLoop.sendMessage(widget, Widget.Msg.BeforeAttach);
15
- ref.current.insertBefore(widget.node, null);
16
- MessageLoop.sendMessage(widget, Widget.Msg.AfterAttach);
17
- }
18
- catch (e) {
19
- console.warn('Exception while attaching Lumino widget.', e);
20
- }
21
- return () => {
22
- try {
23
- if (widget.isAttached || widget.node.isConnected) {
24
- Widget.detach(widget);
25
- }
26
- }
27
- catch (e) {
28
- console.warn('Exception while detaching Lumino widget.', e);
29
- }
30
- };
31
- }, [children]);
32
- return React.createElement("div", { ref: ref });
16
+ const WrappedFormComponent = (props) => {
17
+ const { fields } = props, rest = __rest(props, ["fields"]);
18
+ return (React.createElement(FormComponent, Object.assign({}, rest, { validator: validatorAjv8, fields: Object.assign({}, fields) })));
33
19
  };
34
20
  /**
35
21
  * Generate a form to edit a layer/source type. This class is meant to be sub-classed to create more refined forms for specific layers/sources.
@@ -52,6 +38,13 @@ export class BaseForm extends React.Component {
52
38
  this.setState(old => (Object.assign(Object.assign({}, old), { schema })));
53
39
  }
54
40
  }
41
+ componentDidMount() {
42
+ if (this.props.formErrorSignal) {
43
+ const extraErrors = Object.keys(Object.assign({}, this.state.extraErrors)).length > 0;
44
+ this.setState(old => (Object.assign(Object.assign({}, old), this.state.extraErrors)));
45
+ this.props.formErrorSignal.emit(extraErrors);
46
+ }
47
+ }
55
48
  processSchema(data, schema, uiSchema) {
56
49
  if (!schema['properties']) {
57
50
  return;
@@ -146,19 +139,15 @@ export class BaseForm extends React.Component {
146
139
  var _a;
147
140
  (_a = submitRef.current) === null || _a === void 0 ? void 0 : _a.click();
148
141
  });
149
- const formSchema = new SchemaForm(schema, {
150
- liveValidate: true,
151
- formData,
152
- onChange: this.onFormChange.bind(this),
153
- onSubmit: this.onFormSubmit.bind(this),
154
- onBlur: this.onFormBlur.bind(this),
155
- uiSchema,
156
- children: (React.createElement("button", { ref: submitRef, type: "submit", style: { display: 'none' } })),
157
- extraErrors: this.state.extraErrors
158
- });
159
142
  return (React.createElement("div", { className: "jGIS-property-panel", "data-path": (_b = this.props.filePath) !== null && _b !== void 0 ? _b : '' },
160
- React.createElement("div", { className: "jGIS-property-outer" },
161
- React.createElement(LuminoSchemaForm, null, formSchema)),
143
+ React.createElement("div", { className: "jGIS-property-outer", onKeyUp: (e) => {
144
+ var _a;
145
+ if (e.key === 'Enter') {
146
+ e.preventDefault();
147
+ (_a = submitRef.current) === null || _a === void 0 ? void 0 : _a.click();
148
+ }
149
+ } },
150
+ React.createElement(WrappedFormComponent, { schema: schema, uiSchema: uiSchema, formData: formData, onSubmit: this.onFormSubmit.bind(this), onChange: this.onFormChange.bind(this), onBlur: this.onFormBlur.bind(this), liveValidate: true, children: React.createElement("button", { ref: submitRef, type: "submit", style: { display: 'none' } }), extraErrors: this.state.extraErrors })),
162
151
  !this.props.ok && (React.createElement("div", { className: "jGIS-property-buttons" },
163
152
  React.createElement("button", { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", onClick: () => { var _a; return (_a = submitRef.current) === null || _a === void 0 ? void 0 : _a.click(); } },
164
153
  React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Ok"))))));
@@ -1,6 +1,6 @@
1
1
  import { showErrorMessage } from '@jupyterlab/apputils';
2
2
  import { Ajv } from 'ajv';
3
- import * as geojson from 'geojson-schema/GeoJSON.json';
3
+ import * as geojson from '@jupytergis/schema/src/schema/geojson.json';
4
4
  import { BaseForm } from './baseform';
5
5
  /**
6
6
  * The form to modify a GeoJSON source.
@@ -45,36 +45,39 @@ export class GeoJSONSourcePropertiesForm extends BaseForm {
45
45
  * @param path - the path to validate.
46
46
  */
47
47
  async _validatePath(path) {
48
- const extraErrors = {
49
- path: {
50
- __errors: []
48
+ var _a;
49
+ const extraErrors = this.state.extraErrors;
50
+ let error = '';
51
+ let valid = false;
52
+ if (path) {
53
+ try {
54
+ const geoJSONData = await this.props.model.readGeoJSON(path);
55
+ valid = this._validate(geoJSONData);
56
+ if (!valid) {
57
+ error = `"${path}" is not a valid GeoJSON file`;
58
+ }
51
59
  }
52
- };
53
- this.props.model
54
- .readGeoJSON(path)
55
- .then(async (geoJSONData) => {
56
- var _a;
57
- const valid = this._validate(geoJSONData);
58
- if (!valid) {
59
- extraErrors.path.__errors = [`"${path}" is not a valid GeoJSON file`];
60
- (_a = this._validate.errors) === null || _a === void 0 ? void 0 : _a.reverse().forEach(error => {
61
- extraErrors.path.__errors.push(error.message);
62
- });
60
+ catch (e) {
61
+ error = `"${path}" is not a valid GeoJSON file: ${e}`;
63
62
  }
64
- else {
65
- delete extraErrors.path;
66
- }
67
- this.setState({ extraErrors });
68
- if (this.props.formErrorSignal) {
69
- this.props.formErrorSignal.emit(!valid);
70
- }
71
- })
72
- .catch(e => {
73
- extraErrors.path.__errors = [`Cannot read "${path}"`];
74
- this.setState({ extraErrors });
75
- if (this.props.formErrorSignal) {
76
- this.props.formErrorSignal.emit(true);
77
- }
78
- });
63
+ }
64
+ else {
65
+ error = 'Path is required';
66
+ }
67
+ if (!valid) {
68
+ extraErrors.path = {
69
+ __errors: [error]
70
+ };
71
+ (_a = this._validate.errors) === null || _a === void 0 ? void 0 : _a.reverse().forEach(error => {
72
+ extraErrors.path.__errors.push(error.message);
73
+ });
74
+ this.setState(old => (Object.assign(Object.assign({}, old), { extraErrors })));
75
+ }
76
+ else {
77
+ this.setState(old => (Object.assign(Object.assign({}, old), { extraErrors: Object.assign(Object.assign({}, extraErrors), { path: { __errors: [] } }) })));
78
+ }
79
+ if (this.props.formErrorSignal) {
80
+ this.props.formErrorSignal.emit(!valid);
81
+ }
79
82
  }
80
83
  }
@@ -0,0 +1,16 @@
1
+ import { IChangeEvent, ISubmitEvent } from '@rjsf/core';
2
+ import { BaseForm, IBaseFormProps } from './baseform';
3
+ /**
4
+ * The form to modify a GeoTiff source.
5
+ */
6
+ export declare class GeoTiffSourcePropertiesForm extends BaseForm {
7
+ constructor(props: IBaseFormProps);
8
+ protected onFormChange(e: IChangeEvent): void;
9
+ protected onFormSubmit(e: ISubmitEvent<any>): void;
10
+ /**
11
+ * Validate the URLs, ensuring that there is at least one object with required fields.
12
+ *
13
+ * @param urls - the URLs array to validate.
14
+ */
15
+ private _validateUrls;
16
+ }
@@ -0,0 +1,71 @@
1
+ import { showErrorMessage } from '@jupyterlab/apputils';
2
+ import { BaseForm } from './baseform';
3
+ /**
4
+ * The form to modify a GeoTiff source.
5
+ */
6
+ export class GeoTiffSourcePropertiesForm extends BaseForm {
7
+ constructor(props) {
8
+ var _a, _b;
9
+ super(props);
10
+ this._validateUrls((_b = (_a = props.sourceData) === null || _a === void 0 ? void 0 : _a.urls) !== null && _b !== void 0 ? _b : []);
11
+ }
12
+ onFormChange(e) {
13
+ var _a;
14
+ super.onFormChange(e);
15
+ if ((_a = e.formData) === null || _a === void 0 ? void 0 : _a.urls) {
16
+ this._validateUrls(e.formData.urls);
17
+ }
18
+ }
19
+ onFormSubmit(e) {
20
+ var _a, _b, _c;
21
+ if (((_c = (_b = (_a = this.state.extraErrors) === null || _a === void 0 ? void 0 : _a.urls) === null || _b === void 0 ? void 0 : _b.__errors) === null || _c === void 0 ? void 0 : _c.length) >= 1) {
22
+ showErrorMessage('Invalid URLs', this.state.extraErrors.urls.__errors[0]);
23
+ return;
24
+ }
25
+ super.onFormSubmit(e);
26
+ }
27
+ /**
28
+ * Validate the URLs, ensuring that there is at least one object with required fields.
29
+ *
30
+ * @param urls - the URLs array to validate.
31
+ */
32
+ async _validateUrls(urls) {
33
+ const extraErrors = this.state.extraErrors;
34
+ const errors = [];
35
+ let valid = true;
36
+ if (urls && urls.length > 0) {
37
+ for (let i = 0; i < urls.length; i++) {
38
+ const { url, min, max } = urls[i];
39
+ if (!url || typeof url !== 'string' || url.trim() === '') {
40
+ errors.push(`URL at index ${i} is required and must be a valid string.`);
41
+ valid = false;
42
+ }
43
+ if (min === undefined || typeof min !== 'number') {
44
+ errors.push(`Min value at index ${i} is required and must be a number.`);
45
+ valid = false;
46
+ }
47
+ if (max === undefined || typeof max !== 'number') {
48
+ errors.push(`Max value at index ${i} is required and must be a number.`);
49
+ valid = false;
50
+ }
51
+ if (typeof min === 'number' && typeof max === 'number' && max <= min) {
52
+ errors.push(`Max value at index ${i} must be greater than Min.`);
53
+ valid = false;
54
+ }
55
+ }
56
+ }
57
+ else {
58
+ errors.push('At least one valid URL with min/max values is required.');
59
+ valid = false;
60
+ }
61
+ if (!valid) {
62
+ this.setState(old => (Object.assign(Object.assign({}, old), { extraErrors: Object.assign(Object.assign({}, extraErrors), { urls: { __errors: errors } }) })));
63
+ }
64
+ else {
65
+ this.setState(old => (Object.assign(Object.assign({}, old), { extraErrors: Object.assign(Object.assign({}, extraErrors), { urls: { __errors: [] } }) })));
66
+ }
67
+ if (this.props.formErrorSignal) {
68
+ this.props.formErrorSignal.emit(!valid);
69
+ }
70
+ }
71
+ }
@@ -44,6 +44,7 @@ export class VectorLayerPropertiesForm extends LayerPropertiesForm {
44
44
  }
45
45
  processSchema(data, schema, uiSchema) {
46
46
  this.removeFormEntry('color', data, schema, uiSchema);
47
+ this.removeFormEntry('symbologyState', data, schema, uiSchema);
47
48
  super.processSchema(data, schema, uiSchema);
48
49
  if (!data) {
49
50
  return;
@@ -5,6 +5,7 @@ import { LayerPropertiesForm } from './layerform';
5
5
  export class WebGlLayerPropertiesForm extends LayerPropertiesForm {
6
6
  processSchema(data, schema, uiSchema) {
7
7
  this.removeFormEntry('color', data, schema, uiSchema);
8
+ this.removeFormEntry('symbologyState', data, schema, uiSchema);
8
9
  super.processSchema(data, schema, uiSchema);
9
10
  }
10
11
  }
package/lib/index.d.ts CHANGED
@@ -1,11 +1,14 @@
1
+ export * from './classificationModes';
1
2
  export * from './commands';
2
3
  export * from './constants';
3
4
  export * from './dialogs/formdialog';
5
+ export * from './formbuilder/objectform/baseform';
6
+ export * from './icons';
4
7
  export * from './mainview';
8
+ export * from './panelview';
9
+ export * from './store';
10
+ export * from './toolbar';
5
11
  export * from './tools';
6
- export * from './icons';
7
12
  export * from './types';
8
13
  export * from './widget';
9
- export * from './formbuilder/objectform/baseform';
10
- export * from './panelview';
11
- export * from './toolbar';
14
+ export * from './annotations';
package/lib/index.js CHANGED
@@ -1,11 +1,14 @@
1
+ export * from './classificationModes';
1
2
  export * from './commands';
2
3
  export * from './constants';
3
4
  export * from './dialogs/formdialog';
5
+ export * from './formbuilder/objectform/baseform';
6
+ export * from './icons';
4
7
  export * from './mainview';
8
+ export * from './panelview';
9
+ export * from './store';
10
+ export * from './toolbar';
5
11
  export * from './tools';
6
- export * from './icons';
7
12
  export * from './types';
8
13
  export * from './widget';
9
- export * from './formbuilder/objectform/baseform';
10
- export * from './panelview';
11
- export * from './toolbar';
14
+ export * from './annotations';
@@ -0,0 +1,17 @@
1
+ import { IDict, JgisCoordinates } from '@jupytergis/schema';
2
+ import React from 'react';
3
+ interface ICollaboratorPointersProps {
4
+ clients: IDict<ClientPointer>;
5
+ }
6
+ export type ClientPointer = {
7
+ username: string;
8
+ displayName: string;
9
+ color: string;
10
+ coordinates: JgisCoordinates;
11
+ lonLat: {
12
+ latitude: number;
13
+ longitude: number;
14
+ };
15
+ };
16
+ declare const CollaboratorPointers: ({ clients }: ICollaboratorPointersProps) => React.JSX.Element;
17
+ export default CollaboratorPointers;
@@ -0,0 +1,37 @@
1
+ import { faArrowPointer, faWindowMinimize } from '@fortawesome/free-solid-svg-icons';
2
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import React, { useState } from 'react';
4
+ const CollaboratorPointers = ({ clients }) => {
5
+ const [isOpen, setIsOpen] = useState(false);
6
+ return (React.createElement(React.Fragment, null, clients &&
7
+ Object.values(clients).map(client => (React.createElement("div", { className: "jGIS-Popup-Wrapper", style: {
8
+ left: `${client.coordinates.x}px`,
9
+ top: `${client.coordinates.y}px`
10
+ } },
11
+ React.createElement("div", { key: client.username, className: "jGIS-Remote-Pointer", style: {
12
+ color: client.color,
13
+ cursor: 'pointer'
14
+ }, onClick: () => {
15
+ setIsOpen(!isOpen);
16
+ } },
17
+ React.createElement(FontAwesomeIcon, { icon: faArrowPointer, className: "jGIS-Remote-Pointer-Icon" })),
18
+ React.createElement("div", { style: {
19
+ visibility: isOpen ? 'visible' : 'hidden',
20
+ background: client.color
21
+ }, className: "jGIS-Remote-Pointer-Popup jGIS-Floating-Pointer-Popup" },
22
+ React.createElement("div", { className: "jGIS-Popup-Topbar", onClick: () => {
23
+ setIsOpen(false);
24
+ } },
25
+ React.createElement(FontAwesomeIcon, { icon: faWindowMinimize, className: "jGIS-Popup-TopBarIcon" })),
26
+ React.createElement("div", { className: "jGIS-Remote-Pointer-Popup-Name" }, client.displayName),
27
+ React.createElement("div", { className: "jGIS-Remote-Pointer-Popup-Coordinates" },
28
+ React.createElement("br", null),
29
+ "Pointer Location:",
30
+ React.createElement("br", null),
31
+ "Longitude: ",
32
+ client.lonLat.longitude.toFixed(2),
33
+ React.createElement("br", null),
34
+ "Latitude: ",
35
+ client.lonLat.latitude.toFixed(2))))))));
36
+ };
37
+ export default CollaboratorPointers;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { User } from '@jupyterlab/services';
3
+ interface IFollowIndicatorProps {
4
+ remoteUser: User.IIdentity | null | undefined;
5
+ }
6
+ export declare function FollowIndicator({ remoteUser }: IFollowIndicatorProps): React.JSX.Element | null;
7
+ export {};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ export function FollowIndicator({ remoteUser }) {
3
+ return (remoteUser === null || remoteUser === void 0 ? void 0 : remoteUser.display_name) ? (React.createElement("div", { style: {
4
+ position: 'absolute',
5
+ top: 1,
6
+ right: 3,
7
+ background: remoteUser.color
8
+ } }, `Following ${remoteUser.display_name}`)) : null;
9
+ }