@jupytergis/base 0.3.0 → 0.4.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.js +1 -1
- package/lib/annotations/model.d.ts +6 -7
- package/lib/annotations/model.js +15 -15
- package/lib/commands.d.ts +2 -3
- package/lib/commands.js +117 -62
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +4 -1
- package/lib/dialogs/formdialog.js +2 -2
- package/lib/dialogs/layerBrowserDialog.d.ts +4 -5
- package/lib/dialogs/layerBrowserDialog.js +9 -9
- package/lib/dialogs/symbology/hooks/useGetBandInfo.d.ts +3 -8
- package/lib/dialogs/symbology/hooks/useGetBandInfo.js +16 -28
- package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +1 -1
- package/lib/dialogs/symbology/hooks/useGetProperties.js +6 -8
- package/lib/dialogs/symbology/symbologyDialog.d.ts +2 -3
- package/lib/dialogs/symbology/symbologyDialog.js +10 -9
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +1 -1
- package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +6 -6
- package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +3 -1
- package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.d.ts +1 -1
- package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +5 -4
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.d.ts +1 -1
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +8 -7
- package/lib/dialogs/symbology/vector_layer/VectorRendering.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/VectorRendering.js +18 -13
- package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/Categorized.js +30 -19
- package/lib/dialogs/symbology/vector_layer/types/Graduated.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +16 -13
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.d.ts +4 -0
- package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +77 -0
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.d.ts +1 -1
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +4 -3
- package/lib/formbuilder/creationform.d.ts +1 -2
- package/lib/formbuilder/creationform.js +4 -4
- package/lib/formbuilder/editform.d.ts +1 -2
- package/lib/formbuilder/editform.js +7 -7
- package/lib/formbuilder/formselectors.js +5 -2
- package/lib/formbuilder/objectform/baseform.d.ts +3 -4
- package/lib/formbuilder/objectform/baseform.js +2 -2
- package/lib/formbuilder/objectform/fileselectorwidget.js +13 -6
- package/lib/formbuilder/objectform/geotiffsource.d.ts +5 -1
- package/lib/formbuilder/objectform/geotiffsource.js +51 -18
- package/lib/formbuilder/objectform/heatmapLayerForm.d.ts +11 -0
- package/lib/formbuilder/objectform/heatmapLayerForm.js +60 -0
- package/lib/formbuilder/objectform/vectorlayerform.d.ts +0 -2
- package/lib/formbuilder/objectform/vectorlayerform.js +0 -59
- package/lib/mainview/TemporalSlider.d.ts +8 -0
- package/lib/mainview/TemporalSlider.js +303 -0
- package/lib/mainview/mainView.d.ts +26 -5
- package/lib/mainview/mainView.js +221 -108
- package/lib/mainview/mainviewmodel.d.ts +4 -0
- package/lib/mainview/mainviewmodel.js +4 -0
- package/lib/mainview/mainviewwidget.d.ts +0 -2
- package/lib/mainview/mainviewwidget.js +0 -2
- package/lib/panelview/annotationPanel.js +5 -5
- package/lib/panelview/components/filter-panel/Filter.js +4 -25
- package/lib/panelview/components/identify-panel/IdentifyPanel.js +1 -1
- package/lib/panelview/components/layers.js +2 -2
- package/lib/panelview/components/sources.js +1 -1
- package/lib/panelview/leftpanel.d.ts +3 -0
- package/lib/panelview/leftpanel.js +5 -1
- package/lib/panelview/model.js +8 -8
- package/lib/panelview/objectproperties.js +10 -10
- package/lib/panelview/rightpanel.d.ts +1 -1
- package/lib/panelview/rightpanel.js +10 -10
- package/lib/toolbar/widget.d.ts +1 -1
- package/lib/toolbar/widget.js +44 -32
- package/lib/tools.d.ts +6 -16
- package/lib/tools.js +54 -56
- package/lib/types.d.ts +2 -0
- package/lib/widget.d.ts +30 -6
- package/lib/widget.js +43 -9
- package/package.json +4 -3
- package/style/base.css +10 -0
- package/style/symbologyDialog.css +7 -1
- package/style/temporalSlider.css +47 -0
package/lib/commands.js
CHANGED
|
@@ -4,6 +4,7 @@ import { CreationFormDialog } from './dialogs/formdialog';
|
|
|
4
4
|
import { LayerBrowserWidget } from './dialogs/layerBrowserDialog';
|
|
5
5
|
import { SymbologyWidget } from './dialogs/symbology/symbologyDialog';
|
|
6
6
|
import keybindings from './keybindings.json';
|
|
7
|
+
import { JupyterGISDocumentWidget } from './widget';
|
|
7
8
|
function loadKeybindings(commands, keybindings) {
|
|
8
9
|
keybindings.forEach(binding => {
|
|
9
10
|
commands.addKeyBinding({
|
|
@@ -22,7 +23,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
22
23
|
const { commands } = app;
|
|
23
24
|
commands.addCommand(CommandIDs.symbology, Object.assign({ label: trans.__('Edit Symbology'), isEnabled: () => {
|
|
24
25
|
var _a, _b;
|
|
25
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
26
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
26
27
|
const localState = model === null || model === void 0 ? void 0 : model.sharedModel.awareness.getLocalState();
|
|
27
28
|
if (!model || !localState || !((_b = localState['selected']) === null || _b === void 0 ? void 0 : _b.value)) {
|
|
28
29
|
return false;
|
|
@@ -40,36 +41,37 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
40
41
|
const isValidLayer = [
|
|
41
42
|
'VectorLayer',
|
|
42
43
|
'VectorTileLayer',
|
|
43
|
-
'WebGlLayer'
|
|
44
|
+
'WebGlLayer',
|
|
45
|
+
'HeatmapLayer'
|
|
44
46
|
].includes(layer.type);
|
|
45
47
|
return isValidLayer;
|
|
46
48
|
}, execute: Private.createSymbologyDialog(tracker, state) }, icons.get(CommandIDs.symbology)));
|
|
47
49
|
commands.addCommand(CommandIDs.redo, Object.assign({ label: trans.__('Redo'), isEnabled: () => {
|
|
48
50
|
return tracker.currentWidget
|
|
49
|
-
? tracker.currentWidget.
|
|
51
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
50
52
|
: false;
|
|
51
53
|
}, execute: () => {
|
|
52
54
|
const current = tracker.currentWidget;
|
|
53
55
|
if (current) {
|
|
54
|
-
return current.
|
|
56
|
+
return current.model.sharedModel.redo();
|
|
55
57
|
}
|
|
56
58
|
} }, (_a = icons.get(CommandIDs.redo)) === null || _a === void 0 ? void 0 : _a.icon));
|
|
57
59
|
commands.addCommand(CommandIDs.undo, Object.assign({ label: trans.__('Undo'), isEnabled: () => {
|
|
58
60
|
return tracker.currentWidget
|
|
59
|
-
? tracker.currentWidget.
|
|
61
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
60
62
|
: false;
|
|
61
63
|
}, execute: () => {
|
|
62
64
|
const current = tracker.currentWidget;
|
|
63
65
|
if (current) {
|
|
64
|
-
return current.
|
|
66
|
+
return current.model.sharedModel.undo();
|
|
65
67
|
}
|
|
66
68
|
} }, icons.get(CommandIDs.undo)));
|
|
67
69
|
commands.addCommand(CommandIDs.identify, Object.assign({ label: trans.__('Identify'), isToggled: () => {
|
|
68
70
|
var _a;
|
|
69
|
-
return ((_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
71
|
+
return ((_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model.isIdentifying) || false;
|
|
70
72
|
}, isEnabled: () => {
|
|
71
73
|
return tracker.currentWidget
|
|
72
|
-
? tracker.currentWidget.
|
|
74
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
73
75
|
: false;
|
|
74
76
|
}, execute: args => {
|
|
75
77
|
const current = tracker.currentWidget;
|
|
@@ -80,22 +82,58 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
80
82
|
if (luminoEvent) {
|
|
81
83
|
const keysPressed = luminoEvent.keys;
|
|
82
84
|
if (keysPressed === null || keysPressed === void 0 ? void 0 : keysPressed.includes('Escape')) {
|
|
83
|
-
current.
|
|
85
|
+
current.model.isIdentifying = false;
|
|
84
86
|
current.node.classList.remove('jGIS-identify-tool');
|
|
85
87
|
commands.notifyCommandChanged(CommandIDs.identify);
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
current.node.classList.toggle('jGIS-identify-tool');
|
|
90
|
-
current.
|
|
92
|
+
current.model.toggleIdentify();
|
|
91
93
|
commands.notifyCommandChanged(CommandIDs.identify);
|
|
92
94
|
} }, icons.get(CommandIDs.identify)));
|
|
95
|
+
commands.addCommand(CommandIDs.temporalController, Object.assign({ label: trans.__('Temporal Controller'), isToggled: () => {
|
|
96
|
+
var _a;
|
|
97
|
+
return ((_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model.isTemporalControllerActive) || false;
|
|
98
|
+
}, isEnabled: () => {
|
|
99
|
+
var _a, _b, _c, _d;
|
|
100
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
101
|
+
if (!model) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const selectedLayers = (_c = (_b = model.localState) === null || _b === void 0 ? void 0 : _b.selected) === null || _c === void 0 ? void 0 : _c.value;
|
|
105
|
+
if (!selectedLayers) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const layerId = Object.keys(selectedLayers)[0];
|
|
109
|
+
const layerType = (_d = model.getLayer(layerId)) === null || _d === void 0 ? void 0 : _d.type;
|
|
110
|
+
if (!layerType) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
// Selection should only be one vector or heatmap layer
|
|
114
|
+
const isSelectionValid = Object.keys(selectedLayers).length === 1 &&
|
|
115
|
+
!model.getSource(layerId) &&
|
|
116
|
+
['VectorLayer', 'HeatmapLayer'].includes(layerType);
|
|
117
|
+
if (!isSelectionValid && model.isTemporalControllerActive) {
|
|
118
|
+
model.toggleTemporalController();
|
|
119
|
+
commands.notifyCommandChanged(CommandIDs.temporalController);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}, execute: () => {
|
|
124
|
+
const current = tracker.currentWidget;
|
|
125
|
+
if (!current) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
current.model.toggleTemporalController();
|
|
129
|
+
commands.notifyCommandChanged(CommandIDs.temporalController);
|
|
130
|
+
} }, icons.get(CommandIDs.temporalController)));
|
|
93
131
|
/**
|
|
94
132
|
* SOURCES and LAYERS creation commands.
|
|
95
133
|
*/
|
|
96
134
|
commands.addCommand(CommandIDs.openLayerBrowser, Object.assign({ label: trans.__('Open Layer Browser'), isEnabled: () => {
|
|
97
135
|
return tracker.currentWidget
|
|
98
|
-
? tracker.currentWidget.
|
|
136
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
99
137
|
: false;
|
|
100
138
|
}, execute: Private.createLayerBrowser(tracker, layerBrowserRegistry, formSchemaRegistry) }, icons.get(CommandIDs.openLayerBrowser)));
|
|
101
139
|
/**
|
|
@@ -103,7 +141,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
103
141
|
*/
|
|
104
142
|
commands.addCommand(CommandIDs.newRasterEntry, Object.assign({ label: trans.__('New Raster Layer'), isEnabled: () => {
|
|
105
143
|
return tracker.currentWidget
|
|
106
|
-
? tracker.currentWidget.
|
|
144
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
107
145
|
: false;
|
|
108
146
|
}, execute: Private.createEntry({
|
|
109
147
|
tracker,
|
|
@@ -121,7 +159,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
121
159
|
}) }, icons.get(CommandIDs.newRasterEntry)));
|
|
122
160
|
commands.addCommand(CommandIDs.newVectorTileEntry, Object.assign({ label: trans.__('New Vector Tile Layer'), isEnabled: () => {
|
|
123
161
|
return tracker.currentWidget
|
|
124
|
-
? tracker.currentWidget.
|
|
162
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
125
163
|
: false;
|
|
126
164
|
}, execute: Private.createEntry({
|
|
127
165
|
tracker,
|
|
@@ -136,7 +174,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
136
174
|
}) }, icons.get(CommandIDs.newVectorTileEntry)));
|
|
137
175
|
commands.addCommand(CommandIDs.newGeoJSONEntry, Object.assign({ label: trans.__('New GeoJSON layer'), isEnabled: () => {
|
|
138
176
|
return tracker.currentWidget
|
|
139
|
-
? tracker.currentWidget.
|
|
177
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
140
178
|
: false;
|
|
141
179
|
}, execute: Private.createEntry({
|
|
142
180
|
tracker,
|
|
@@ -150,7 +188,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
150
188
|
}) }, icons.get(CommandIDs.newGeoJSONEntry)));
|
|
151
189
|
commands.addCommand(CommandIDs.newHillshadeEntry, Object.assign({ label: trans.__('New Hillshade layer'), isEnabled: () => {
|
|
152
190
|
return tracker.currentWidget
|
|
153
|
-
? tracker.currentWidget.
|
|
191
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
154
192
|
: false;
|
|
155
193
|
}, execute: Private.createEntry({
|
|
156
194
|
tracker,
|
|
@@ -164,7 +202,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
164
202
|
}) }, icons.get(CommandIDs.newHillshadeEntry)));
|
|
165
203
|
commands.addCommand(CommandIDs.newImageEntry, Object.assign({ label: trans.__('New Image layer'), isEnabled: () => {
|
|
166
204
|
return tracker.currentWidget
|
|
167
|
-
? tracker.currentWidget.
|
|
205
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
168
206
|
: false;
|
|
169
207
|
}, execute: Private.createEntry({
|
|
170
208
|
tracker,
|
|
@@ -188,7 +226,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
188
226
|
}) }, icons.get(CommandIDs.newImageEntry)));
|
|
189
227
|
commands.addCommand(CommandIDs.newVideoEntry, Object.assign({ label: trans.__('New Video layer'), isEnabled: () => {
|
|
190
228
|
return tracker.currentWidget
|
|
191
|
-
? tracker.currentWidget.
|
|
229
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
192
230
|
: false;
|
|
193
231
|
}, execute: Private.createEntry({
|
|
194
232
|
tracker,
|
|
@@ -217,7 +255,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
217
255
|
? trans.__('Shapefile')
|
|
218
256
|
: trans.__('Add Shapefile Source'), isEnabled: () => {
|
|
219
257
|
return tracker.currentWidget
|
|
220
|
-
? tracker.currentWidget.
|
|
258
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
221
259
|
: false;
|
|
222
260
|
}, execute: Private.createEntry({
|
|
223
261
|
tracker,
|
|
@@ -230,7 +268,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
230
268
|
}) }, icons.get(CommandIDs.newShapefileSource)));
|
|
231
269
|
commands.addCommand(CommandIDs.newGeoTiffEntry, Object.assign({ label: trans.__('New GeoTiff layer'), isEnabled: () => {
|
|
232
270
|
return tracker.currentWidget
|
|
233
|
-
? tracker.currentWidget.
|
|
271
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
234
272
|
: false;
|
|
235
273
|
}, execute: Private.createEntry({
|
|
236
274
|
tracker,
|
|
@@ -253,7 +291,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
253
291
|
? trans.__('Raster')
|
|
254
292
|
: trans.__('New Raster Source'), isEnabled: () => {
|
|
255
293
|
return tracker.currentWidget
|
|
256
|
-
? tracker.currentWidget.
|
|
294
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
257
295
|
: false;
|
|
258
296
|
}, execute: Private.createEntry({
|
|
259
297
|
tracker,
|
|
@@ -268,7 +306,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
268
306
|
? trans.__('Raster DEM')
|
|
269
307
|
: trans.__('New Raster DEM Source'), isEnabled: () => {
|
|
270
308
|
return tracker.currentWidget
|
|
271
|
-
? tracker.currentWidget.
|
|
309
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
272
310
|
: false;
|
|
273
311
|
}, execute: Private.createEntry({
|
|
274
312
|
tracker,
|
|
@@ -283,7 +321,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
283
321
|
? trans.__('Vector')
|
|
284
322
|
: trans.__('New Vector Source'), isEnabled: () => {
|
|
285
323
|
return tracker.currentWidget
|
|
286
|
-
? tracker.currentWidget.
|
|
324
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
287
325
|
: false;
|
|
288
326
|
}, execute: Private.createEntry({
|
|
289
327
|
tracker,
|
|
@@ -298,7 +336,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
298
336
|
? trans.__('GeoJSON')
|
|
299
337
|
: trans.__('Add GeoJSON data from file'), isEnabled: () => {
|
|
300
338
|
return tracker.currentWidget
|
|
301
|
-
? tracker.currentWidget.
|
|
339
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
302
340
|
: false;
|
|
303
341
|
}, execute: Private.createEntry({
|
|
304
342
|
tracker,
|
|
@@ -313,7 +351,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
313
351
|
? trans.__('Image')
|
|
314
352
|
: trans.__('Add Image Source'), isEnabled: () => {
|
|
315
353
|
return tracker.currentWidget
|
|
316
|
-
? tracker.currentWidget.
|
|
354
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
317
355
|
: false;
|
|
318
356
|
}, execute: Private.createEntry({
|
|
319
357
|
tracker,
|
|
@@ -328,7 +366,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
328
366
|
? trans.__('Video')
|
|
329
367
|
: trans.__('Add Video Source'), isEnabled: () => {
|
|
330
368
|
return tracker.currentWidget
|
|
331
|
-
? tracker.currentWidget.
|
|
369
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
332
370
|
: false;
|
|
333
371
|
}, execute: Private.createEntry({
|
|
334
372
|
tracker,
|
|
@@ -344,7 +382,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
344
382
|
? trans.__('Raster')
|
|
345
383
|
: trans.__('Add Raster layer'), isEnabled: () => {
|
|
346
384
|
return tracker.currentWidget
|
|
347
|
-
? tracker.currentWidget.
|
|
385
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
348
386
|
: false;
|
|
349
387
|
}, execute: Private.createEntry({
|
|
350
388
|
tracker,
|
|
@@ -362,7 +400,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
362
400
|
? trans.__('Vector')
|
|
363
401
|
: trans.__('Add New Vector layer'), isEnabled: () => {
|
|
364
402
|
return tracker.currentWidget
|
|
365
|
-
? tracker.currentWidget.
|
|
403
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
366
404
|
: false;
|
|
367
405
|
}, execute: Private.createEntry({
|
|
368
406
|
tracker,
|
|
@@ -380,7 +418,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
380
418
|
? trans.__('Hillshade')
|
|
381
419
|
: trans.__('Add Hillshade layer'), isEnabled: () => {
|
|
382
420
|
return tracker.currentWidget
|
|
383
|
-
? tracker.currentWidget.
|
|
421
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
384
422
|
: false;
|
|
385
423
|
}, execute: Private.createEntry({
|
|
386
424
|
tracker,
|
|
@@ -398,7 +436,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
398
436
|
? trans.__('Image')
|
|
399
437
|
: trans.__('Add Image layer'), isEnabled: () => {
|
|
400
438
|
return tracker.currentWidget
|
|
401
|
-
? tracker.currentWidget.
|
|
439
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
402
440
|
: false;
|
|
403
441
|
}, execute: Private.createEntry({
|
|
404
442
|
tracker,
|
|
@@ -416,7 +454,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
416
454
|
? trans.__('Video')
|
|
417
455
|
: trans.__('Add Video layer'), isEnabled: () => {
|
|
418
456
|
return tracker.currentWidget
|
|
419
|
-
? tracker.currentWidget.
|
|
457
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
420
458
|
: false;
|
|
421
459
|
}, execute: Private.createEntry({
|
|
422
460
|
tracker,
|
|
@@ -432,7 +470,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
432
470
|
}) }, icons.get(CommandIDs.newVideoLayer)));
|
|
433
471
|
commands.addCommand(CommandIDs.newShapefileLayer, Object.assign({ label: trans.__('New Shapefile Layer'), isEnabled: () => {
|
|
434
472
|
return tracker.currentWidget
|
|
435
|
-
? tracker.currentWidget.
|
|
473
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
436
474
|
: false;
|
|
437
475
|
}, execute: Private.createEntry({
|
|
438
476
|
tracker,
|
|
@@ -445,6 +483,22 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
445
483
|
sourceType: 'ShapefileSource',
|
|
446
484
|
layerType: 'VectorLayer'
|
|
447
485
|
}) }, icons.get(CommandIDs.newShapefileLayer)));
|
|
486
|
+
commands.addCommand(CommandIDs.newHeatmapLayer, Object.assign({ label: args => args.from === 'contextMenu'
|
|
487
|
+
? trans.__('Heatmap')
|
|
488
|
+
: trans.__('Add HeatmapLayer'), isEnabled: () => {
|
|
489
|
+
return tracker.currentWidget
|
|
490
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
491
|
+
: false;
|
|
492
|
+
}, execute: Private.createEntry({
|
|
493
|
+
tracker,
|
|
494
|
+
formSchemaRegistry,
|
|
495
|
+
title: 'Create Heatmap Layer',
|
|
496
|
+
createLayer: true,
|
|
497
|
+
createSource: false,
|
|
498
|
+
layerData: { name: 'Custom Heatmap Layer' },
|
|
499
|
+
sourceType: 'GeoJSONSource',
|
|
500
|
+
layerType: 'HeatmapLayer'
|
|
501
|
+
}) }, icons.get(CommandIDs.newHeatmapLayer)));
|
|
448
502
|
/**
|
|
449
503
|
* LAYERS and LAYER GROUP actions.
|
|
450
504
|
*/
|
|
@@ -452,7 +506,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
452
506
|
label: trans.__('Rename Layer'),
|
|
453
507
|
execute: async () => {
|
|
454
508
|
var _a;
|
|
455
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
509
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
456
510
|
await Private.renameSelectedItem(model, 'layer', (layerId, newName) => {
|
|
457
511
|
const layer = model === null || model === void 0 ? void 0 : model.getLayer(layerId);
|
|
458
512
|
if (layer) {
|
|
@@ -466,7 +520,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
466
520
|
label: trans.__('Remove Layer'),
|
|
467
521
|
execute: () => {
|
|
468
522
|
var _a;
|
|
469
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
523
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
470
524
|
Private.removeSelectedItems(model, 'layer', selection => {
|
|
471
525
|
model === null || model === void 0 ? void 0 : model.removeLayer(selection);
|
|
472
526
|
});
|
|
@@ -476,7 +530,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
476
530
|
label: trans.__('Rename Group'),
|
|
477
531
|
execute: async () => {
|
|
478
532
|
var _a;
|
|
479
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
533
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
480
534
|
await Private.renameSelectedItem(model, 'group', (groupName, newName) => {
|
|
481
535
|
model === null || model === void 0 ? void 0 : model.renameLayerGroup(groupName, newName);
|
|
482
536
|
});
|
|
@@ -486,7 +540,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
486
540
|
label: trans.__('Remove Group'),
|
|
487
541
|
execute: async () => {
|
|
488
542
|
var _a;
|
|
489
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
543
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
490
544
|
Private.removeSelectedItems(model, 'group', selection => {
|
|
491
545
|
model === null || model === void 0 ? void 0 : model.removeLayerGroup(selection);
|
|
492
546
|
});
|
|
@@ -496,7 +550,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
496
550
|
label: args => args['label'] ? args['label'] : trans.__('Move to Root'),
|
|
497
551
|
execute: args => {
|
|
498
552
|
var _a, _b, _c;
|
|
499
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
553
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
500
554
|
const groupName = args['label'];
|
|
501
555
|
const selectedLayers = (_c = (_b = model === null || model === void 0 ? void 0 : model.localState) === null || _b === void 0 ? void 0 : _b.selected) === null || _c === void 0 ? void 0 : _c.value;
|
|
502
556
|
if (!selectedLayers) {
|
|
@@ -509,7 +563,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
509
563
|
label: trans.__('Move Selected Layers to New Group'),
|
|
510
564
|
execute: async () => {
|
|
511
565
|
var _a, _b, _c;
|
|
512
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
566
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
513
567
|
const selectedLayers = (_c = (_b = model === null || model === void 0 ? void 0 : model.localState) === null || _b === void 0 ? void 0 : _b.selected) === null || _c === void 0 ? void 0 : _c.value;
|
|
514
568
|
if (!selectedLayers) {
|
|
515
569
|
return;
|
|
@@ -566,7 +620,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
566
620
|
label: trans.__('Rename Source'),
|
|
567
621
|
execute: async () => {
|
|
568
622
|
var _a;
|
|
569
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
623
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
570
624
|
await Private.renameSelectedItem(model, 'source', (sourceId, newName) => {
|
|
571
625
|
const source = model === null || model === void 0 ? void 0 : model.getSource(sourceId);
|
|
572
626
|
if (source) {
|
|
@@ -580,7 +634,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
580
634
|
label: trans.__('Remove Source'),
|
|
581
635
|
execute: () => {
|
|
582
636
|
var _a;
|
|
583
|
-
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.
|
|
637
|
+
const model = (_a = tracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model;
|
|
584
638
|
Private.removeSelectedItems(model, 'source', selection => {
|
|
585
639
|
var _a;
|
|
586
640
|
if (!((_a = model === null || model === void 0 ? void 0 : model.getLayersBySource(selection).length) !== null && _a !== void 0 ? _a : true)) {
|
|
@@ -595,37 +649,43 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
595
649
|
// Console commands
|
|
596
650
|
commands.addCommand(CommandIDs.toggleConsole, {
|
|
597
651
|
label: trans.__('Toggle console'),
|
|
652
|
+
isVisible: () => tracker.currentWidget instanceof JupyterGISDocumentWidget,
|
|
598
653
|
isEnabled: () => {
|
|
599
654
|
return tracker.currentWidget
|
|
600
|
-
? tracker.currentWidget.
|
|
655
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
601
656
|
: false;
|
|
602
657
|
},
|
|
603
658
|
execute: async () => await Private.toggleConsole(tracker)
|
|
604
659
|
});
|
|
605
660
|
commands.addCommand(CommandIDs.executeConsole, {
|
|
606
661
|
label: trans.__('Execute console'),
|
|
662
|
+
isVisible: () => tracker.currentWidget instanceof JupyterGISDocumentWidget,
|
|
607
663
|
isEnabled: () => {
|
|
608
664
|
return tracker.currentWidget
|
|
609
|
-
? tracker.currentWidget.
|
|
665
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
610
666
|
: false;
|
|
611
667
|
},
|
|
612
668
|
execute: () => Private.executeConsole(tracker)
|
|
613
669
|
});
|
|
614
670
|
commands.addCommand(CommandIDs.removeConsole, {
|
|
615
671
|
label: trans.__('Remove console'),
|
|
672
|
+
isVisible: () => tracker.currentWidget instanceof JupyterGISDocumentWidget,
|
|
616
673
|
isEnabled: () => {
|
|
617
674
|
return tracker.currentWidget
|
|
618
|
-
? tracker.currentWidget.
|
|
675
|
+
? tracker.currentWidget.model.sharedModel.editable
|
|
619
676
|
: false;
|
|
620
677
|
},
|
|
621
678
|
execute: () => Private.removeConsole(tracker)
|
|
622
679
|
});
|
|
623
680
|
commands.addCommand(CommandIDs.invokeCompleter, {
|
|
624
681
|
label: trans.__('Display the completion helper.'),
|
|
682
|
+
isVisible: () => tracker.currentWidget instanceof JupyterGISDocumentWidget,
|
|
625
683
|
execute: () => {
|
|
626
684
|
var _a;
|
|
627
685
|
const currentWidget = tracker.currentWidget;
|
|
628
|
-
if (!currentWidget ||
|
|
686
|
+
if (!currentWidget ||
|
|
687
|
+
!completionProviderManager ||
|
|
688
|
+
!(currentWidget instanceof JupyterGISDocumentWidget)) {
|
|
629
689
|
return;
|
|
630
690
|
}
|
|
631
691
|
const id = (_a = currentWidget.content.consolePanel) === null || _a === void 0 ? void 0 : _a.id;
|
|
@@ -636,10 +696,13 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
636
696
|
});
|
|
637
697
|
commands.addCommand(CommandIDs.selectCompleter, {
|
|
638
698
|
label: trans.__('Select the completion suggestion.'),
|
|
699
|
+
isVisible: () => tracker.currentWidget instanceof JupyterGISDocumentWidget,
|
|
639
700
|
execute: () => {
|
|
640
701
|
var _a;
|
|
641
702
|
const currentWidget = tracker.currentWidget;
|
|
642
|
-
if (!currentWidget ||
|
|
703
|
+
if (!currentWidget ||
|
|
704
|
+
!completionProviderManager ||
|
|
705
|
+
!(currentWidget instanceof JupyterGISDocumentWidget)) {
|
|
643
706
|
return;
|
|
644
707
|
}
|
|
645
708
|
const id = (_a = currentWidget.content.consolePanel) === null || _a === void 0 ? void 0 : _a.id;
|
|
@@ -657,7 +720,7 @@ export function addCommands(app, tracker, translator, formSchemaRegistry, layerB
|
|
|
657
720
|
return;
|
|
658
721
|
}
|
|
659
722
|
console.log('zooming');
|
|
660
|
-
const model = tracker.currentWidget.
|
|
723
|
+
const model = tracker.currentWidget.model;
|
|
661
724
|
const selectedItems = (_a = model.localState) === null || _a === void 0 ? void 0 : _a.selected.value;
|
|
662
725
|
if (!selectedItems) {
|
|
663
726
|
return;
|
|
@@ -677,7 +740,7 @@ var Private;
|
|
|
677
740
|
return;
|
|
678
741
|
}
|
|
679
742
|
const dialog = new LayerBrowserWidget({
|
|
680
|
-
|
|
743
|
+
model: current.model,
|
|
681
744
|
registry: layerBrowserRegistry.getRegistryLayers(),
|
|
682
745
|
formSchemaRegistry
|
|
683
746
|
});
|
|
@@ -692,7 +755,7 @@ var Private;
|
|
|
692
755
|
return;
|
|
693
756
|
}
|
|
694
757
|
const dialog = new SymbologyWidget({
|
|
695
|
-
|
|
758
|
+
model: current.model,
|
|
696
759
|
state
|
|
697
760
|
});
|
|
698
761
|
await dialog.launch();
|
|
@@ -706,7 +769,7 @@ var Private;
|
|
|
706
769
|
return;
|
|
707
770
|
}
|
|
708
771
|
const dialog = new CreationFormDialog({
|
|
709
|
-
|
|
772
|
+
model: current.model,
|
|
710
773
|
title,
|
|
711
774
|
createLayer,
|
|
712
775
|
createSource,
|
|
@@ -749,8 +812,8 @@ var Private;
|
|
|
749
812
|
}
|
|
750
813
|
Private.getUserInputForRename = getUserInputForRename;
|
|
751
814
|
function removeSelectedItems(model, itemTypeToRemove, removeFunction) {
|
|
752
|
-
var _a;
|
|
753
|
-
const selected = (_a = model === null || model === void 0 ? void 0 : model.localState) === null || _a === void 0 ? void 0 : _a.selected.value;
|
|
815
|
+
var _a, _b;
|
|
816
|
+
const selected = (_b = (_a = model === null || model === void 0 ? void 0 : model.localState) === null || _a === void 0 ? void 0 : _a.selected) === null || _b === void 0 ? void 0 : _b.value;
|
|
754
817
|
if (!selected) {
|
|
755
818
|
console.info('Nothing selected');
|
|
756
819
|
return;
|
|
@@ -804,7 +867,7 @@ var Private;
|
|
|
804
867
|
Private.renameSelectedItem = renameSelectedItem;
|
|
805
868
|
function executeConsole(tracker) {
|
|
806
869
|
const current = tracker.currentWidget;
|
|
807
|
-
if (!current) {
|
|
870
|
+
if (!current || !(current instanceof JupyterGISDocumentWidget)) {
|
|
808
871
|
return;
|
|
809
872
|
}
|
|
810
873
|
current.content.executeConsole();
|
|
@@ -812,7 +875,7 @@ var Private;
|
|
|
812
875
|
Private.executeConsole = executeConsole;
|
|
813
876
|
function removeConsole(tracker) {
|
|
814
877
|
const current = tracker.currentWidget;
|
|
815
|
-
if (!current) {
|
|
878
|
+
if (!current || !(current instanceof JupyterGISDocumentWidget)) {
|
|
816
879
|
return;
|
|
817
880
|
}
|
|
818
881
|
current.content.removeConsole();
|
|
@@ -820,18 +883,10 @@ var Private;
|
|
|
820
883
|
Private.removeConsole = removeConsole;
|
|
821
884
|
async function toggleConsole(tracker) {
|
|
822
885
|
const current = tracker.currentWidget;
|
|
823
|
-
if (!current) {
|
|
886
|
+
if (!current || !(current instanceof JupyterGISDocumentWidget)) {
|
|
824
887
|
return;
|
|
825
888
|
}
|
|
826
|
-
|
|
827
|
-
let realPath = '';
|
|
828
|
-
if (currentPath.length > 1) {
|
|
829
|
-
realPath = currentPath[1];
|
|
830
|
-
}
|
|
831
|
-
else {
|
|
832
|
-
realPath = currentPath[0];
|
|
833
|
-
}
|
|
834
|
-
await current.content.toggleConsole(realPath);
|
|
889
|
+
await current.content.toggleConsole(current.model.filePath);
|
|
835
890
|
}
|
|
836
891
|
Private.toggleConsole = toggleConsole;
|
|
837
892
|
})(Private || (Private = {}));
|
package/lib/constants.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare namespace CommandIDs {
|
|
|
8
8
|
const undo = "jupytergis:undo";
|
|
9
9
|
const symbology = "jupytergis:symbology";
|
|
10
10
|
const identify = "jupytergis:identify";
|
|
11
|
+
const temporalController = "jupytergis:temporalController";
|
|
11
12
|
const openLayerBrowser = "jupytergis:openLayerBrowser";
|
|
12
13
|
const newRasterEntry = "jupytergis:newRasterEntry";
|
|
13
14
|
const newVectorTileEntry = "jupytergis:newVectorTileEntry";
|
|
@@ -31,6 +32,7 @@ export declare namespace CommandIDs {
|
|
|
31
32
|
const newVideoLayer = "jupytergis:newVideoLayer";
|
|
32
33
|
const newShapefileLayer = "jupytergis:newShapefileLayer";
|
|
33
34
|
const newWebGlTileLayer = "jupytergis:newWebGlTileLayer";
|
|
35
|
+
const newHeatmapLayer = "jupytergis:newHeatmapLayer";
|
|
34
36
|
const renameLayer = "jupytergis:renameLayer";
|
|
35
37
|
const removeLayer = "jupytergis:removeLayer";
|
|
36
38
|
const renameGroup = "jupytergis:renameGroup";
|
package/lib/constants.js
CHANGED
|
@@ -10,6 +10,7 @@ export var CommandIDs;
|
|
|
10
10
|
CommandIDs.undo = 'jupytergis:undo';
|
|
11
11
|
CommandIDs.symbology = 'jupytergis:symbology';
|
|
12
12
|
CommandIDs.identify = 'jupytergis:identify';
|
|
13
|
+
CommandIDs.temporalController = 'jupytergis:temporalController';
|
|
13
14
|
// Layers and sources creation commands
|
|
14
15
|
CommandIDs.openLayerBrowser = 'jupytergis:openLayerBrowser';
|
|
15
16
|
// Layer and source
|
|
@@ -37,6 +38,7 @@ export var CommandIDs;
|
|
|
37
38
|
CommandIDs.newVideoLayer = 'jupytergis:newVideoLayer';
|
|
38
39
|
CommandIDs.newShapefileLayer = 'jupytergis:newShapefileLayer';
|
|
39
40
|
CommandIDs.newWebGlTileLayer = 'jupytergis:newWebGlTileLayer';
|
|
41
|
+
CommandIDs.newHeatmapLayer = 'jupytergis:newHeatmapLayer';
|
|
40
42
|
// Layer and group actions
|
|
41
43
|
CommandIDs.renameLayer = 'jupytergis:renameLayer';
|
|
42
44
|
CommandIDs.removeLayer = 'jupytergis:removeLayer';
|
|
@@ -82,7 +84,8 @@ const iconObject = {
|
|
|
82
84
|
[CommandIDs.newShapefileLayer]: { iconClass: 'fa fa-file' },
|
|
83
85
|
[CommandIDs.newGeoTiffEntry]: { iconClass: 'fa fa-image' },
|
|
84
86
|
[CommandIDs.symbology]: { iconClass: 'fa fa-brush' },
|
|
85
|
-
[CommandIDs.identify]: { iconClass: 'fa fa-info' }
|
|
87
|
+
[CommandIDs.identify]: { iconClass: 'fa fa-info' },
|
|
88
|
+
[CommandIDs.temporalController]: { iconClass: 'fa fa-clock' }
|
|
86
89
|
};
|
|
87
90
|
/**
|
|
88
91
|
* The registered icons
|
|
@@ -16,7 +16,7 @@ export const CreationFormWrapper = (props) => {
|
|
|
16
16
|
formErrorSignal.current = formChanged;
|
|
17
17
|
setReady(true);
|
|
18
18
|
});
|
|
19
|
-
return (ready && (React.createElement(CreationForm, {
|
|
19
|
+
return (ready && (React.createElement(CreationForm, { model: props.model, formSchemaRegistry: props.formSchemaRegistry, createLayer: props.createLayer, createSource: props.createSource, layerType: props.layerType, sourceType: props.sourceType, sourceData: props.sourceData, layerData: props.layerData, ok: okSignal.current, cancel: props.cancel, formErrorSignal: formErrorSignal.current, dialogOptions: props.dialogOptions })));
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
22
|
* Form for creating a source, a layer or both at the same time
|
|
@@ -29,7 +29,7 @@ export class CreationFormDialog extends Dialog {
|
|
|
29
29
|
const okSignalPromise = new PromiseDelegate();
|
|
30
30
|
const formErrorSignalPromise = new PromiseDelegate();
|
|
31
31
|
const body = (React.createElement("div", { style: { overflow: 'auto' } },
|
|
32
|
-
React.createElement(CreationFormWrapper, {
|
|
32
|
+
React.createElement(CreationFormWrapper, { model: options.model, formSchemaRegistry: options.formSchemaRegistry, createLayer: options.createLayer, createSource: options.createSource, layerType: options.layerType, sourceType: options.sourceType, sourceData: options.sourceData, layerData: options.layerData, okSignalPromise: okSignalPromise, cancel: cancelCallback, formErrorSignalPromise: formErrorSignalPromise, dialogOptions: options })));
|
|
33
33
|
super({
|
|
34
34
|
title: options.title,
|
|
35
35
|
body,
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { IJGISFormSchemaRegistry, IJupyterGISModel, IRasterLayerGalleryEntry } from '@jupytergis/schema';
|
|
2
2
|
import { Dialog } from '@jupyterlab/apputils';
|
|
3
3
|
import { PromiseDelegate } from '@lumino/coreutils';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
6
4
|
import { Signal } from '@lumino/signaling';
|
|
5
|
+
import React from 'react';
|
|
7
6
|
interface ILayerBrowserDialogProps {
|
|
8
|
-
|
|
7
|
+
model: IJupyterGISModel;
|
|
9
8
|
registry: IRasterLayerGalleryEntry[];
|
|
10
9
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
11
10
|
okSignalPromise: PromiseDelegate<Signal<Dialog<any>, number>>;
|
|
12
11
|
cancel: () => void;
|
|
13
12
|
}
|
|
14
|
-
export declare const LayerBrowserComponent: ({
|
|
13
|
+
export declare const LayerBrowserComponent: ({ model, registry, formSchemaRegistry, okSignalPromise, cancel }: ILayerBrowserDialogProps) => React.JSX.Element;
|
|
15
14
|
export interface ILayerBrowserOptions {
|
|
16
|
-
|
|
15
|
+
model: IJupyterGISModel;
|
|
17
16
|
registry: IRasterLayerGalleryEntry[];
|
|
18
17
|
formSchemaRegistry: IJGISFormSchemaRegistry;
|
|
19
18
|
}
|