@jupytergis/schema 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/model.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { ICollaborativeDrive } from '@jupyter/collaborative-drive';
2
1
  import { MapChange } from '@jupyter/ydoc';
3
2
  import { IChangedArgs } from '@jupyterlab/coreutils';
4
3
  import { DocumentRegistry } from '@jupyterlab/docregistry';
@@ -6,9 +5,10 @@ import { PartialJSONObject } from '@lumino/coreutils';
6
5
  import { ISignal, Signal } from '@lumino/signaling';
7
6
  import { GeoJSON } from './_interface/geojsonsource';
8
7
  import { IJGISContent, IJGISLayer, IJGISLayerGroup, IJGISLayerTree, IJGISLayers, IJGISOptions, IJGISSource, IJGISSources } from './_interface/jgis';
9
- import { IJGISLayerDocChange, IJGISLayerTreeDocChange, IJGISSourceDocChange, IJupyterGISClientState, IJupyterGISDoc, IJupyterGISModel, ISelection, IUserData } from './interfaces';
8
+ import { IViewPortState, Pointer, IAnnotationModel, IJGISLayerDocChange, IJGISLayerTreeDocChange, IJGISSourceDocChange, IJupyterGISClientState, IJupyterGISDoc, IJupyterGISModel, ISelection, IUserData, IDict } from './interfaces';
9
+ import { Contents } from '@jupyterlab/services';
10
10
  export declare class JupyterGISModel implements IJupyterGISModel {
11
- constructor(options: DocumentRegistry.IModelOptions<IJupyterGISDoc>);
11
+ constructor(options: JupyterGISModel.IOptions);
12
12
  private _onSharedModelChanged;
13
13
  readonly collaborative: boolean;
14
14
  get sharedModel(): IJupyterGISDoc;
@@ -30,6 +30,14 @@ export declare class JupyterGISModel implements IJupyterGISModel {
30
30
  get sharedLayerTreeChanged(): ISignal<IJupyterGISDoc, IJGISLayerTreeDocChange>;
31
31
  get sharedSourcesChanged(): ISignal<IJupyterGISDoc, IJGISSourceDocChange>;
32
32
  get disposed(): ISignal<JupyterGISModel, void>;
33
+ get sharedMetadataChanged(): ISignal<this, MapChange>;
34
+ get zoomToAnnotationSignal(): ISignal<this, string>;
35
+ set isIdentifying(isIdentifying: boolean);
36
+ get isIdentifying(): boolean;
37
+ centerOnAnnotation(id: string): void;
38
+ private _metadataChangedHandler;
39
+ addMetadata(key: string, value: string): void;
40
+ removeMetadata(key: string): void;
33
41
  dispose(): void;
34
42
  toString(): string;
35
43
  fromString(data: string): void;
@@ -38,7 +46,7 @@ export declare class JupyterGISModel implements IJupyterGISModel {
38
46
  initialize(): void;
39
47
  getWorker(): Worker;
40
48
  getContent(): IJGISContent;
41
- setDrive(value: ICollaborativeDrive, filePath: string): void;
49
+ setContentsManager(value: Contents.IManager | undefined, filePath: string): void;
42
50
  getLayers(): IJGISLayers;
43
51
  getSources(): IJGISSources;
44
52
  getLayerTree(): IJGISLayerTree;
@@ -89,9 +97,12 @@ export declare class JupyterGISModel implements IJupyterGISModel {
89
97
  removeLayer(layer_id: string): void;
90
98
  setOptions(value: IJGISOptions): void;
91
99
  getOptions(): IJGISOptions;
100
+ syncViewport(viewport?: IViewPortState, emitter?: string): void;
101
+ syncPointer(pointer?: Pointer, emitter?: string): void;
92
102
  syncSelected(value: {
93
103
  [key: string]: ISelection;
94
104
  }, emitter?: string): void;
105
+ syncIdentifiedFeatures(features: IDict<any>, emitter?: string): void;
95
106
  setUserToFollow(userId?: number): void;
96
107
  getClientId(): number;
97
108
  /**
@@ -111,15 +122,18 @@ export declare class JupyterGISModel implements IJupyterGISModel {
111
122
  }, group: IJGISLayerGroup): void;
112
123
  private _removeLayerTreeLayer;
113
124
  private _removeLayerTreeGroup;
125
+ private _removeLayerTreeItem;
114
126
  renameLayerGroup(groupName: string, newName: string): void;
115
127
  removeLayerGroup(groupName: string): void;
128
+ toggleIdentify(): void;
116
129
  private _getLayerTreeInfo;
117
130
  private _onClientStateChanged;
118
131
  readonly defaultKernelName: string;
119
132
  readonly defaultKernelLanguage: string;
133
+ readonly annotationModel?: IAnnotationModel;
120
134
  private _sharedModel;
121
135
  private _filePath;
122
- private _drive?;
136
+ private _contentsManager?;
123
137
  private _dirty;
124
138
  private _readOnly;
125
139
  private _isDisposed;
@@ -130,6 +144,9 @@ export declare class JupyterGISModel implements IJupyterGISModel {
130
144
  private _stateChanged;
131
145
  private _themeChanged;
132
146
  private _clientStateChanged;
147
+ private _sharedMetadataChanged;
148
+ private _zoomToAnnotationSignal;
149
+ private _isIdentifying;
133
150
  static worker: Worker;
134
151
  }
135
152
  export declare namespace JupyterGISModel {
@@ -137,4 +154,7 @@ export declare namespace JupyterGISModel {
137
154
  * Function to get the ordered list of layers according to the tree.
138
155
  */
139
156
  function getOrderedLayerIds(model: IJupyterGISModel): string[];
157
+ interface IOptions extends DocumentRegistry.IModelOptions<IJupyterGISDoc> {
158
+ annotationModel?: IAnnotationModel;
159
+ }
140
160
  }
package/lib/model.js CHANGED
@@ -16,11 +16,9 @@ export class JupyterGISModel {
16
16
  this._onClientStateChanged = (changed) => {
17
17
  const clients = this.sharedModel.awareness.getStates();
18
18
  this._clientStateChanged.emit(clients);
19
- this._sharedModel.awareness.on('change', (update) => {
20
- if (update.added.length || update.removed.length) {
21
- this._userChanged.emit(this.users);
22
- }
23
- });
19
+ if (changed.added.length || changed.removed.length) {
20
+ this._userChanged.emit(this.users);
21
+ }
24
22
  };
25
23
  this.defaultKernelName = '';
26
24
  this.defaultKernelLanguage = '';
@@ -33,7 +31,10 @@ export class JupyterGISModel {
33
31
  this._stateChanged = new Signal(this);
34
32
  this._themeChanged = new Signal(this);
35
33
  this._clientStateChanged = new Signal(this);
36
- const { sharedModel } = options;
34
+ this._sharedMetadataChanged = new Signal(this);
35
+ this._zoomToAnnotationSignal = new Signal(this);
36
+ this._isIdentifying = false;
37
+ const { annotationModel, sharedModel } = options;
37
38
  if (sharedModel) {
38
39
  this._sharedModel = sharedModel;
39
40
  }
@@ -42,6 +43,8 @@ export class JupyterGISModel {
42
43
  this._sharedModel.changed.connect(this._onSharedModelChanged);
43
44
  }
44
45
  this.sharedModel.awareness.on('change', this._onClientStateChanged);
46
+ this._sharedModel.metadataChanged.connect(this._metadataChangedHandler, this);
47
+ this.annotationModel = annotationModel;
45
48
  }
46
49
  get sharedModel() {
47
50
  return this._sharedModel;
@@ -109,6 +112,30 @@ export class JupyterGISModel {
109
112
  get disposed() {
110
113
  return this._disposed;
111
114
  }
115
+ get sharedMetadataChanged() {
116
+ return this._sharedMetadataChanged;
117
+ }
118
+ get zoomToAnnotationSignal() {
119
+ return this._zoomToAnnotationSignal;
120
+ }
121
+ set isIdentifying(isIdentifying) {
122
+ this._isIdentifying = isIdentifying;
123
+ }
124
+ get isIdentifying() {
125
+ return this._isIdentifying;
126
+ }
127
+ centerOnAnnotation(id) {
128
+ this._zoomToAnnotationSignal.emit(id);
129
+ }
130
+ _metadataChangedHandler(_, args) {
131
+ this._sharedMetadataChanged.emit(args);
132
+ }
133
+ addMetadata(key, value) {
134
+ this.sharedModel.setMetadata(key, value);
135
+ }
136
+ removeMetadata(key) {
137
+ this.sharedModel.removeMetadata(key);
138
+ }
112
139
  dispose() {
113
140
  if (this._isDisposed) {
114
141
  return;
@@ -134,7 +161,7 @@ export class JupyterGISModel {
134
161
  console.warn(errorMsg);
135
162
  }
136
163
  this.sharedModel.transact(() => {
137
- var _a, _b, _c, _d;
164
+ var _a, _b, _c, _d, _e;
138
165
  this.sharedModel.sources = (_a = jsonData.sources) !== null && _a !== void 0 ? _a : {};
139
166
  this.sharedModel.layers = (_b = jsonData.layers) !== null && _b !== void 0 ? _b : {};
140
167
  this.sharedModel.layerTree = (_c = jsonData.layerTree) !== null && _c !== void 0 ? _c : [];
@@ -146,6 +173,7 @@ export class JupyterGISModel {
146
173
  pitch: 0,
147
174
  projection: 'EPSG:3857'
148
175
  };
176
+ this.sharedModel.metadata = (_e = jsonData.metadata) !== null && _e !== void 0 ? _e : {};
149
177
  });
150
178
  this.dirty = true;
151
179
  }
@@ -166,11 +194,12 @@ export class JupyterGISModel {
166
194
  sources: this.sharedModel.sources,
167
195
  layers: this.sharedModel.layers,
168
196
  layerTree: this.sharedModel.layerTree,
169
- options: this.sharedModel.options
197
+ options: this.sharedModel.options,
198
+ metadata: this.sharedModel.metadata
170
199
  };
171
200
  }
172
- setDrive(value, filePath) {
173
- this._drive = value;
201
+ setContentsManager(value, filePath) {
202
+ this._contentsManager = value;
174
203
  this._filePath = filePath;
175
204
  }
176
205
  getLayers() {
@@ -225,22 +254,17 @@ export class JupyterGISModel {
225
254
  * @returns a promise to the GeoJSON data.
226
255
  */
227
256
  async readGeoJSON(filepath) {
228
- if (!this._drive) {
257
+ if (!this._contentsManager) {
229
258
  return;
230
259
  }
231
- let dir = PathExt.dirname(this._filePath);
232
- if (dir.includes(':')) {
233
- dir = dir.split(':')[1];
234
- }
235
- const absolutePath = PathExt.join(dir, filepath);
236
- return this._drive
237
- .get(absolutePath)
238
- .then(contentModel => {
239
- return JSON.parse(contentModel.content);
240
- })
241
- .catch(e => {
242
- throw e;
260
+ const absolutePath = PathExt.resolve(PathExt.dirname(this._filePath), filepath);
261
+ const file = await this._contentsManager.get(absolutePath, {
262
+ content: true
243
263
  });
264
+ if (typeof file.content === 'string') {
265
+ return JSON.parse(file.content);
266
+ }
267
+ return file.content;
244
268
  }
245
269
  /**
246
270
  * Add a layer group in the layer tree.
@@ -289,10 +313,28 @@ export class JupyterGISModel {
289
313
  getOptions() {
290
314
  return this._sharedModel.options;
291
315
  }
316
+ syncViewport(viewport, emitter) {
317
+ this.sharedModel.awareness.setLocalStateField('viewportState', {
318
+ value: viewport,
319
+ emitter
320
+ });
321
+ }
322
+ syncPointer(pointer, emitter) {
323
+ this.sharedModel.awareness.setLocalStateField('pointer', {
324
+ value: pointer,
325
+ emitter
326
+ });
327
+ }
292
328
  syncSelected(value, emitter) {
293
329
  this.sharedModel.awareness.setLocalStateField('selected', {
294
330
  value,
295
- emitter: emitter
331
+ emitter
332
+ });
333
+ }
334
+ syncIdentifiedFeatures(features, emitter) {
335
+ this.sharedModel.awareness.setLocalStateField('identifiedFeatures', {
336
+ value: features,
337
+ emitter
296
338
  });
297
339
  }
298
340
  setUserToFollow(userId) {
@@ -385,29 +427,22 @@ export class JupyterGISModel {
385
427
  this._addLayerTreeItem(group);
386
428
  }
387
429
  _removeLayerTreeLayer(layerTree, layerIdToRemove) {
388
- // Iterate over each item in the layerTree
389
- for (let i = 0; i < layerTree.length; i++) {
390
- const currentItem = layerTree[i];
391
- // Check if the current item is a string and matches the target
392
- if (typeof currentItem === 'string' && currentItem === layerIdToRemove) {
393
- // Remove the item from the array
394
- layerTree.splice(i, 1);
395
- // Decrement i to ensure the next iteration processes the remaining items correctly
396
- i--;
397
- }
398
- else if (typeof currentItem !== 'string' && 'layers' in currentItem) {
399
- // If the current item is a group, recursively call the function on its layers
400
- this._removeLayerTreeLayer(currentItem.layers, layerIdToRemove);
401
- }
402
- }
430
+ this._removeLayerTreeItem(layerTree, layerIdToRemove, true);
403
431
  this.sharedModel.layerTree = layerTree;
404
432
  }
405
433
  _removeLayerTreeGroup(layerTree, groupName) {
434
+ this._removeLayerTreeItem(layerTree, groupName, false);
435
+ this.sharedModel.layerTree = layerTree;
436
+ }
437
+ _removeLayerTreeItem(layerTree, target, isLayer) {
406
438
  // Iterate over each item in the layerTree
407
439
  for (let i = 0; i < layerTree.length; i++) {
408
440
  const currentItem = layerTree[i];
441
+ const matches = isLayer
442
+ ? typeof currentItem === 'string' && currentItem === target
443
+ : typeof currentItem !== 'string' && currentItem.name === target;
409
444
  // Check if the current item is a string and matches the target
410
- if (typeof currentItem !== 'string' && currentItem.name === groupName) {
445
+ if (matches) {
411
446
  // Remove the item from the array
412
447
  layerTree.splice(i, 1);
413
448
  // Decrement i to ensure the next iteration processes the remaining items correctly
@@ -415,10 +450,9 @@ export class JupyterGISModel {
415
450
  }
416
451
  else if (typeof currentItem !== 'string' && 'layers' in currentItem) {
417
452
  // If the current item is a group, recursively call the function on its layers
418
- this._removeLayerTreeGroup(currentItem.layers, groupName);
453
+ this._removeLayerTreeItem(currentItem.layers, target, isLayer);
419
454
  }
420
455
  }
421
- this.sharedModel.layerTree = layerTree;
422
456
  }
423
457
  renameLayerGroup(groupName, newName) {
424
458
  const layerTreeInfo = this._getLayerTreeInfo(groupName);
@@ -451,6 +485,9 @@ export class JupyterGISModel {
451
485
  this._sharedModel.updateLayerTreeItem(layerTreeInfo.mainGroupIndex, updatedLayerTree[layerTreeInfo.mainGroupIndex]);
452
486
  }
453
487
  }
488
+ toggleIdentify() {
489
+ this._isIdentifying = !this._isIdentifying;
490
+ }
454
491
  _getLayerTreeInfo(groupName) {
455
492
  const layerTree = this.getLayerTree();
456
493
  const indexesPath = Private.findItemPath(layerTree, groupName);