@jupytergis/base 0.1.7 → 0.2.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/annotations/components/Annotation.d.ts +11 -0
- package/lib/annotations/components/Annotation.js +61 -0
- package/lib/annotations/components/AnnotationFloater.d.ts +7 -0
- package/lib/annotations/components/AnnotationFloater.js +30 -0
- package/lib/annotations/components/Message.d.ts +8 -0
- package/lib/annotations/components/Message.js +17 -0
- package/lib/annotations/index.d.ts +3 -0
- package/lib/annotations/index.js +3 -0
- package/lib/annotations/model.d.ts +28 -0
- package/lib/annotations/model.js +67 -0
- package/lib/commands.js +51 -6
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +5 -1
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +25 -33
- package/lib/formbuilder/formselectors.js +4 -0
- package/lib/formbuilder/objectform/baseform.d.ts +1 -1
- package/lib/formbuilder/objectform/baseform.js +31 -42
- package/lib/formbuilder/objectform/geojsonsource.js +33 -30
- package/lib/formbuilder/objectform/geotiffsource.d.ts +16 -0
- package/lib/formbuilder/objectform/geotiffsource.js +71 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/mainview/CollaboratorPointers.d.ts +17 -0
- package/lib/mainview/CollaboratorPointers.js +37 -0
- package/lib/mainview/FollowIndicator.d.ts +7 -0
- package/lib/mainview/FollowIndicator.js +9 -0
- package/lib/mainview/mainView.d.ts +36 -2
- package/lib/mainview/mainView.js +393 -28
- package/lib/mainview/mainviewmodel.d.ts +2 -1
- package/lib/mainview/mainviewmodel.js +5 -0
- package/lib/panelview/annotationPanel.d.ts +27 -0
- package/lib/panelview/annotationPanel.js +45 -0
- package/lib/panelview/components/filter-panel/Filter.d.ts +7 -2
- package/lib/panelview/components/filter-panel/Filter.js +1 -1
- package/lib/panelview/components/filter-panel/FilterRow.js +3 -3
- package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +15 -0
- package/lib/panelview/components/identify-panel/IdentifyPanel.js +108 -0
- package/lib/panelview/components/layers.js +4 -4
- package/lib/panelview/leftpanel.js +8 -0
- package/lib/panelview/rightpanel.d.ts +4 -1
- package/lib/panelview/rightpanel.js +28 -7
- package/lib/toolbar/widget.js +11 -1
- package/lib/tools.d.ts +35 -0
- package/lib/tools.js +86 -0
- package/package.json +5 -6
- package/style/base.css +4 -8
- package/style/dialog.css +1 -1
- package/style/icons/logo_mini.svg +70 -148
- package/style/icons/nonvisibility.svg +2 -7
- package/style/icons/visibility.svg +2 -6
- package/style/leftPanel.css +5 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
2
2
|
import { Ajv } from 'ajv';
|
|
3
|
-
import * as geojson from '
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
+
}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -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
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { IJGISLayer, IJGISSource } from '@jupytergis/schema';
|
|
1
|
+
import { IAnnotation, IDict, IJGISLayer, IJGISSource } from '@jupytergis/schema';
|
|
2
2
|
import { User } from '@jupyterlab/services';
|
|
3
3
|
import BaseLayer from 'ol/layer/Base';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { MainViewModel } from './mainviewmodel';
|
|
6
|
+
import { ClientPointer } from './CollaboratorPointers';
|
|
6
7
|
interface IProps {
|
|
7
8
|
viewModel: MainViewModel;
|
|
8
9
|
}
|
|
@@ -12,13 +13,17 @@ interface IStates {
|
|
|
12
13
|
lightTheme: boolean;
|
|
13
14
|
remoteUser?: User.IIdentity | null;
|
|
14
15
|
firstLoad: boolean;
|
|
16
|
+
annotations: IDict<IAnnotation>;
|
|
17
|
+
clientPointers: IDict<ClientPointer>;
|
|
15
18
|
}
|
|
16
19
|
export declare class MainView extends React.Component<IProps, IStates> {
|
|
17
20
|
constructor(props: IProps);
|
|
18
21
|
componentDidMount(): Promise<void>;
|
|
19
22
|
componentWillUnmount(): void;
|
|
20
23
|
generateScene(): Promise<void>;
|
|
24
|
+
addContextMenu: () => void;
|
|
21
25
|
private _loadShapefileAsGeoJSON;
|
|
26
|
+
private _loadGeoTIFFWithCache;
|
|
22
27
|
/**
|
|
23
28
|
* Add a source in the map.
|
|
24
29
|
*
|
|
@@ -46,6 +51,12 @@ export declare class MainView extends React.Component<IProps, IStates> {
|
|
|
46
51
|
* @param layerIds - the list of layers in the depth order (beneath first).
|
|
47
52
|
*/
|
|
48
53
|
updateLayers(layerIds: string[]): void;
|
|
54
|
+
/**
|
|
55
|
+
* Updates the position and existence of layers in the OL map based on the layer IDs.
|
|
56
|
+
*
|
|
57
|
+
* @param layerIds - An array of layer IDs that should be present on the map.
|
|
58
|
+
* @returns {} Nothing is returned.
|
|
59
|
+
*/
|
|
49
60
|
private _updateLayersImpl;
|
|
50
61
|
/**
|
|
51
62
|
* Build the map layer.
|
|
@@ -95,17 +106,39 @@ export declare class MainView extends React.Component<IProps, IStates> {
|
|
|
95
106
|
* @param id Layer to retrieve
|
|
96
107
|
*/
|
|
97
108
|
private getLayer;
|
|
109
|
+
/**
|
|
110
|
+
* Convenience method to get a specific layer index from OpenLayers Map
|
|
111
|
+
* @param id Layer to retrieve
|
|
112
|
+
*/
|
|
113
|
+
private getLayerIndex;
|
|
98
114
|
/**
|
|
99
115
|
* Convenience method to get list layer IDs from the OpenLayers Map
|
|
100
116
|
*/
|
|
101
|
-
private
|
|
117
|
+
private getLayerIDs;
|
|
118
|
+
/**
|
|
119
|
+
* Move layer `id` in the stack to `index`.
|
|
120
|
+
*
|
|
121
|
+
* @param id - id of the layer.
|
|
122
|
+
* @param index - expected index of the layer.
|
|
123
|
+
*/
|
|
124
|
+
moveLayer(id: string, index: number): void;
|
|
102
125
|
private _onLayersChanged;
|
|
103
126
|
private _onLayerTreeChange;
|
|
104
127
|
private _onSourcesChange;
|
|
105
128
|
private _onSharedModelStateChange;
|
|
129
|
+
private _onSharedMetadataChanged;
|
|
130
|
+
private _computeAnnotationPosition;
|
|
131
|
+
private _updateAnnotation;
|
|
132
|
+
private _onZoomToAnnotation;
|
|
133
|
+
private _moveToPosition;
|
|
134
|
+
private _onPointerMove;
|
|
135
|
+
private _syncPointer;
|
|
136
|
+
private _identifyFeature;
|
|
106
137
|
private _handleThemeChange;
|
|
107
138
|
private _handleWindowResize;
|
|
108
139
|
render(): JSX.Element;
|
|
140
|
+
private _clickCoords;
|
|
141
|
+
private _commands;
|
|
109
142
|
private _initializedPosition;
|
|
110
143
|
private divRef;
|
|
111
144
|
private _Map;
|
|
@@ -115,5 +148,6 @@ export declare class MainView extends React.Component<IProps, IStates> {
|
|
|
115
148
|
private _sources;
|
|
116
149
|
private _sourceToLayerMap;
|
|
117
150
|
private _documentPath?;
|
|
151
|
+
private _contextMenu;
|
|
118
152
|
}
|
|
119
153
|
export {};
|