ol-wfst 1.0.7 → 3.0.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.
- package/CHANGELOG.md +26 -1
- package/README.md +125 -48
- package/dist/@enums.d.ts +12 -0
- package/dist/@enums.d.ts.map +1 -0
- package/dist/assets/i18n/en.d.ts +3 -0
- package/dist/assets/i18n/en.d.ts.map +1 -0
- package/dist/assets/i18n/es.d.ts +3 -0
- package/dist/assets/i18n/es.d.ts.map +1 -0
- package/dist/assets/i18n/index.d.ts +3 -0
- package/dist/assets/i18n/index.d.ts.map +1 -0
- package/dist/css/ol-wfst.bootstrap5.css +863 -0
- package/dist/css/ol-wfst.bootstrap5.min.css +1 -0
- package/dist/css/ol-wfst.css +172 -127
- package/dist/css/ol-wfst.min.css +1 -1
- package/dist/ol-wfst.d.ts +143 -86
- package/dist/ol-wfst.d.ts.map +1 -0
- package/dist/ol-wfst.js +5313 -4575
- package/dist/ol-wfst.js.map +1 -0
- package/dist/ol-wfst.min.js +16 -1
- package/dist/ol-wfst.min.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/lib/@enums.d.ts +12 -0
- package/lib/@enums.d.ts.map +1 -0
- package/lib/assets/i18n/en.d.ts +3 -0
- package/lib/assets/i18n/en.d.ts.map +1 -0
- package/lib/assets/i18n/es.d.ts +3 -0
- package/lib/assets/i18n/es.d.ts.map +1 -0
- package/lib/assets/i18n/index.d.ts +3 -0
- package/lib/assets/i18n/index.d.ts.map +1 -0
- package/lib/ol-wfst.d.ts +143 -86
- package/lib/ol-wfst.d.ts.map +1 -0
- package/lib/ol-wfst.js +2126 -2195
- package/lib/ol-wfst.js.map +1 -0
- package/lib/style/css/ol-gisify.css +267 -0
- package/lib/style/css/ol-wfst.bootstrap5.css +863 -0
- package/lib/style/scss/-ol-wfst.bootstrap5.scss +10 -0
- package/lib/{css/ol-wfst.css → style/scss/ol-wfst.scss} +7 -2
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +70 -66
- package/dist/css/bootstrap-modal.min.css +0 -7
- package/lib/css/bootstrap-modal.min.css +0 -7
package/lib/ol-wfst.js
CHANGED
|
@@ -1,22 +1,45 @@
|
|
|
1
|
-
import GeometryType from 'ol/geom/GeometryType';
|
|
2
|
-
import OverlayPositioning from 'ol/OverlayPositioning';
|
|
3
1
|
import TileState from 'ol/TileState';
|
|
4
|
-
import {
|
|
2
|
+
import { GeometryCollection, Circle as Circle$1, Polygon, MultiLineString, MultiPolygon, MultiPoint } from 'ol/geom';
|
|
5
3
|
import { Style, Circle, Fill, Stroke } from 'ol/style';
|
|
6
4
|
import { Control } from 'ol/control';
|
|
7
|
-
import {
|
|
8
|
-
import { Feature, Overlay } from 'ol';
|
|
5
|
+
import { Modify, Snap, Select, Draw } from 'ol/interaction';
|
|
6
|
+
import { Collection, Feature, Overlay } from 'ol';
|
|
9
7
|
import { WFS, GeoJSON, KML } from 'ol/format';
|
|
10
8
|
import { Vector, Tile } from 'ol/layer';
|
|
11
9
|
import { Vector as Vector$1, TileWMS } from 'ol/source';
|
|
12
10
|
import { bbox, all } from 'ol/loadingstrategy';
|
|
13
11
|
import { fromCircle } from 'ol/geom/Polygon';
|
|
14
12
|
import { getCenter } from 'ol/extent';
|
|
15
|
-
import {
|
|
13
|
+
import { primaryAction, never } from 'ol/events/condition';
|
|
16
14
|
import { transformExtent } from 'ol/proj';
|
|
17
15
|
import { unByKey } from 'ol/Observable';
|
|
18
16
|
import Modal from 'modal-vanilla';
|
|
19
17
|
|
|
18
|
+
/*! *****************************************************************************
|
|
19
|
+
Copyright (c) Microsoft Corporation.
|
|
20
|
+
|
|
21
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
22
|
+
purpose with or without fee is hereby granted.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
25
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
26
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
27
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
28
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
29
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
30
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
31
|
+
***************************************************************************** */
|
|
32
|
+
|
|
33
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
34
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
35
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
36
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
37
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
38
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
20
43
|
var img = "data:image/svg+xml,%3csvg version='1.1' xmlns='http://www.w3.org/2000/svg' width='768' height='768' viewBox='0 0 768 768'%3e %3cpath d='M663 225l-58.5 58.5-120-120 58.5-58.5q9-9 22.5-9t22.5 9l75 75q9 9 9 22.5t-9 22.5zM96 552l354-354 120 120-354 354h-120v-120z'%3e%3c/path%3e%3c/svg%3e";
|
|
21
44
|
|
|
22
45
|
var img$1 = "data:image/svg+xml,%3csvg version='1.1' xmlns='http://www.w3.org/2000/svg' width='448' height='448' viewBox='0 0 448 448'%3e %3cpath d='M222 296l29-29-38-38-29 29v14h24v24h14zM332 116c-2.25-2.25-6-2-8.25 0.25l-87.5 87.5c-2.25 2.25-2.5 6-0.25 8.25s6 2 8.25-0.25l87.5-87.5c2.25-2.25 2.5-6 0.25-8.25zM352 264.5v47.5c0 39.75-32.25 72-72 72h-208c-39.75 0-72-32.25-72-72v-208c0-39.75 32.25-72 72-72h208c10 0 20 2 29.25 6.25 2.25 1 4 3.25 4.5 5.75 0.5 2.75-0.25 5.25-2.25 7.25l-12.25 12.25c-2.25 2.25-5.25 3-8 2-3.75-1-7.5-1.5-11.25-1.5h-208c-22 0-40 18-40 40v208c0 22 18 40 40 40h208c22 0 40-18 40-40v-31.5c0-2 0.75-4 2.25-5.5l16-16c2.5-2.5 5.75-3 8.75-1.75s5 4 5 7.25zM328 80l72 72-168 168h-72v-72zM439 113l-23 23-72-72 23-23c9.25-9.25 24.75-9.25 34 0l38 38c9.25 9.25 9.25 24.75 0 34z'%3e%3c/path%3e%3c/svg%3e";
|
|
@@ -29,120 +52,106 @@ var img$4 = "data:image/svg+xml,%3csvg version='1.1' xmlns='http://www.w3.org/20
|
|
|
29
52
|
|
|
30
53
|
var img$5 = "data:image/svg+xml,%3csvg version='1.1' xmlns='http://www.w3.org/2000/svg' width='768' height='768' viewBox='0 0 768 768'%3e%3cpath d='M379.5 288h4.5q39 0 67.5 28.5t28.5 67.5v6zM241.5 313.5q-18 36-18 70.5 0 66 47.25 113.25t113.25 47.25q34.5 0 70.5-18l-49.5-49.5q-12 3-21 3-39 0-67.5-28.5t-28.5-67.5q0-9 3-21zM64.5 136.5l40.5-40.5 567 567-40.5 40.5q-7.5-7.5-47.25-46.5t-60.75-60q-64.5 27-139.5 27-118.5 0-214.5-66t-138-174q16.5-39 51.75-86.25t68.25-72.75q-18-18-50.25-51t-36.75-37.5zM384 223.5q-30 0-58.5 12l-69-69q58.5-22.5 127.5-22.5 118.5 0 213.75 66t137.25 174q-36 88.5-109.5 151.5l-93-93q12-28.5 12-58.5 0-66-47.25-113.25t-113.25-47.25z'%3e%3c/path%3e%3c/svg%3e";
|
|
31
54
|
|
|
32
|
-
var
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
var GeometryType;
|
|
56
|
+
(function (GeometryType) {
|
|
57
|
+
GeometryType["Point"] = "Point";
|
|
58
|
+
GeometryType["LineString"] = "LineString";
|
|
59
|
+
GeometryType["LinearRing"] = "LinearRing";
|
|
60
|
+
GeometryType["Polygon"] = "Polygon";
|
|
61
|
+
GeometryType["MultiPoint"] = "MultiPoint";
|
|
62
|
+
GeometryType["MultiLineString"] = "MultiLineString";
|
|
63
|
+
GeometryType["MultiPolygon"] = "MultiPolygon";
|
|
64
|
+
GeometryType["GeometryCollection"] = "GeometryCollection";
|
|
65
|
+
GeometryType["Circle"] = "Circle";
|
|
66
|
+
})(GeometryType || (GeometryType = {}));
|
|
67
|
+
|
|
68
|
+
const es = {
|
|
69
|
+
labels: {
|
|
70
|
+
select: 'Seleccionar',
|
|
71
|
+
addElement: 'Modo dibujo',
|
|
72
|
+
editElement: 'Editar elemento',
|
|
73
|
+
save: 'Guardar',
|
|
74
|
+
delete: 'Eliminar',
|
|
75
|
+
cancel: 'Cancelar',
|
|
76
|
+
apply: 'Aplicar cambios',
|
|
77
|
+
upload: 'Subir',
|
|
78
|
+
editMode: 'Modo Edición',
|
|
79
|
+
confirmDelete: '¿Estás seguro de borrar el elemento?',
|
|
80
|
+
geomTypeNotSupported: 'Geometría no compatible con la capa',
|
|
81
|
+
editFields: 'Editar campos',
|
|
82
|
+
editGeom: 'Editar geometría',
|
|
83
|
+
selectDrawType: 'Tipo de geometría para dibujar',
|
|
84
|
+
uploadToLayer: 'Subir archivo a la capa seleccionada',
|
|
85
|
+
uploadFeatures: 'Subida de elementos a la capa',
|
|
86
|
+
validFeatures: 'Válidas',
|
|
87
|
+
invalidFeatures: 'Invalidas',
|
|
88
|
+
loading: 'Cargando...',
|
|
89
|
+
toggleVisibility: 'Cambiar visibilidad de la capa',
|
|
90
|
+
close: 'Cerrar'
|
|
91
|
+
},
|
|
92
|
+
errors: {
|
|
93
|
+
capabilities: 'No se pudieron obtener las Capabilidades del GeoServer',
|
|
94
|
+
wfst: 'El GeoServer no tiene soporte a Transacciones',
|
|
95
|
+
layer: 'No se pudieron obtener datos de la capa',
|
|
96
|
+
noValidGeometry: 'No se encontraron geometrías válidas para agregar a esta capa',
|
|
97
|
+
geoserver: 'No se pudieron obtener datos desde el GeoServer',
|
|
98
|
+
badFormat: 'Formato no soportado',
|
|
99
|
+
badFile: 'Error al leer elementos del archivo',
|
|
100
|
+
lockFeature: 'No se pudieron bloquear elementos en el GeoServer.',
|
|
101
|
+
transaction: 'Error al hacer transacción con el GeoServer. HTTP status:',
|
|
102
|
+
getFeatures: 'Error al obtener elemento desde el GeoServer. HTTP status:'
|
|
103
|
+
}
|
|
67
104
|
};
|
|
68
105
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const en = {
|
|
107
|
+
labels: {
|
|
108
|
+
select: 'Select',
|
|
109
|
+
addElement: 'Toggle Draw mode',
|
|
110
|
+
editElement: 'Edit feature',
|
|
111
|
+
save: 'Save',
|
|
112
|
+
delete: 'Delete',
|
|
113
|
+
cancel: 'Cancel',
|
|
114
|
+
apply: 'Apply changes',
|
|
115
|
+
upload: 'Upload',
|
|
116
|
+
editMode: 'Edit Mode',
|
|
117
|
+
confirmDelete: 'Are you sure to delete the feature?',
|
|
118
|
+
geomTypeNotSupported: 'Geometry not supported by layer',
|
|
119
|
+
editFields: 'Edit fields',
|
|
120
|
+
editGeom: 'Edit geometry',
|
|
121
|
+
selectDrawType: 'Geometry type to draw',
|
|
122
|
+
uploadToLayer: 'Upload file to selected layer',
|
|
123
|
+
uploadFeatures: 'Uploaded features to layer',
|
|
124
|
+
validFeatures: 'Valid geometries',
|
|
125
|
+
invalidFeatures: 'Invalid',
|
|
126
|
+
loading: 'Loading...',
|
|
127
|
+
toggleVisibility: 'Toggle layer visibility',
|
|
128
|
+
close: 'Close'
|
|
129
|
+
},
|
|
130
|
+
errors: {
|
|
131
|
+
capabilities: 'GeoServer Capabilities could not be downloaded.',
|
|
132
|
+
wfst: 'The GeoServer does not support Transactions',
|
|
133
|
+
layer: 'Could not get data from layer',
|
|
134
|
+
noValidGeometry: 'No valid geometries found to add to this layer',
|
|
135
|
+
geoserver: 'Could not get data from the GeoServer',
|
|
136
|
+
badFormat: 'Unsupported format',
|
|
137
|
+
badFile: 'Error reading items from file',
|
|
138
|
+
lockFeature: 'No se pudieron bloquear elementos en el GeoServer. HTTP status:',
|
|
139
|
+
transaction: 'Error when doing Transaction with GeoServer. HTTP status:',
|
|
140
|
+
getFeatures: 'Error getting elements from GeoServer. HTTP status:'
|
|
141
|
+
}
|
|
104
142
|
};
|
|
105
143
|
|
|
106
|
-
var
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
144
|
+
var i18n = /*#__PURE__*/Object.freeze({
|
|
145
|
+
__proto__: null,
|
|
146
|
+
es: es,
|
|
147
|
+
en: en
|
|
110
148
|
});
|
|
111
149
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
120
|
-
function fulfilled(value) {
|
|
121
|
-
try {
|
|
122
|
-
step(generator.next(value));
|
|
123
|
-
} catch (e) {
|
|
124
|
-
reject(e);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function rejected(value) {
|
|
129
|
-
try {
|
|
130
|
-
step(generator["throw"](value));
|
|
131
|
-
} catch (e) {
|
|
132
|
-
reject(e);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function step(result) {
|
|
137
|
-
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
141
|
-
});
|
|
142
|
-
}; // Ol
|
|
143
|
-
// Axis ordering: latitude/longitude
|
|
144
|
-
|
|
145
|
-
var DEFAULT_GEOSERVER_SRS = 'urn:x-ogc:def:crs:EPSG:4326';
|
|
150
|
+
// https://docs.geoserver.org/latest/en/user/services/wfs/axis_order.html
|
|
151
|
+
// Axis ordering: latitude/longitude
|
|
152
|
+
const DEFAULT_GEOSERVER_SRS = 'EPSG:3857';
|
|
153
|
+
const DEFAULT_LANGUAGE = 'en';
|
|
154
|
+
const controlElement = document.createElement('div');
|
|
146
155
|
/**
|
|
147
156
|
* Tiny WFST-T client to insert (drawing/uploading), modify and delete
|
|
148
157
|
* features on GeoServers using OpenLayers. Layers with these types
|
|
@@ -151,2108 +160,2030 @@ var DEFAULT_GEOSERVER_SRS = 'urn:x-ogc:def:crs:EPSG:4326';
|
|
|
151
160
|
* "LineString", "MultiLineString", "Polygon" and "MultiPolygon".
|
|
152
161
|
*
|
|
153
162
|
* @constructor
|
|
154
|
-
* @
|
|
163
|
+
* @fires getCapabilities
|
|
164
|
+
* @fires describeFeatureType
|
|
165
|
+
* @fires allDescribeFeatureTypeLoaded
|
|
166
|
+
* @fires getFeature
|
|
167
|
+
* @fires modifystart
|
|
168
|
+
* @fires modifyend
|
|
169
|
+
* @fires drawstart
|
|
170
|
+
* @fires drawend
|
|
171
|
+
* @extends {ol/control/Control~Control}
|
|
155
172
|
* @param opt_options Wfst options, see [Wfst Options](#options) for more details.
|
|
156
|
-
*/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
yield this._getGeoserverLayersData(this.options.layers, this.options.geoServerUrl);
|
|
233
|
-
|
|
234
|
-
this._createLayers(this.options.layers);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
this._initMapElements(this.options.showControl, this.options.active);
|
|
238
|
-
} catch (err) {
|
|
239
|
-
this._hideLoading();
|
|
240
|
-
|
|
241
|
-
this._showError(err.message);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Creates a base control
|
|
247
|
-
*
|
|
248
|
-
* @private
|
|
249
|
-
*/
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
_createBaseControl() {
|
|
253
|
-
this._controlWidgetToolsDiv = document.createElement('div');
|
|
254
|
-
this._controlWidgetToolsDiv.className = 'ol-wfst--tools-control';
|
|
255
|
-
this._controlWidgetTools = new Control({
|
|
256
|
-
element: this._controlWidgetToolsDiv
|
|
257
|
-
});
|
|
258
|
-
this.map.addControl(this._controlWidgetTools);
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Get the capabilities from the GeoServer and check
|
|
262
|
-
* all the available operations.
|
|
263
|
-
*
|
|
264
|
-
* @private
|
|
265
|
-
*/
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
_connectToGeoServerAndGetCapabilities() {
|
|
269
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
-
/**
|
|
271
|
-
* @private
|
|
272
|
-
*/
|
|
273
|
-
var getCapabilities = () => __awaiter(this, void 0, void 0, function* () {
|
|
274
|
-
var params = new URLSearchParams({
|
|
275
|
-
service: 'wfs',
|
|
276
|
-
version: '1.3.0',
|
|
277
|
-
request: 'GetCapabilities',
|
|
278
|
-
exceptions: 'application/json'
|
|
279
|
-
});
|
|
280
|
-
var url_fetch = this.options.geoServerUrl + '?' + params.toString();
|
|
281
|
-
|
|
282
|
-
try {
|
|
283
|
-
var response = yield fetch(url_fetch, {
|
|
284
|
-
headers: this.options.headers
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
if (!response.ok) {
|
|
288
|
-
throw new Error('');
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
var data = yield response.text();
|
|
292
|
-
var capabilities = new window.DOMParser().parseFromString(data, 'text/xml');
|
|
293
|
-
return capabilities;
|
|
294
|
-
} catch (err) {
|
|
295
|
-
throw new Error(this._i18n.errors.capabilities);
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
this._geoServerCapabilities = yield getCapabilities(); // Available operations in the geoserver
|
|
300
|
-
|
|
301
|
-
var operations = this._geoServerCapabilities.getElementsByTagName('ows:Operation');
|
|
302
|
-
|
|
303
|
-
Array.from(operations).forEach(operation => {
|
|
304
|
-
if (operation.getAttribute('name') === 'Transaction') {
|
|
305
|
-
this._hasTransaction = true;
|
|
306
|
-
} else if (operation.getAttribute('name') === 'LockFeature') {
|
|
307
|
-
this._hasLockFeature = true;
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
if (!this._hasTransaction) {
|
|
312
|
-
throw new Error(this._i18n.errors.wfst);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return true;
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Request and store data layers obtained by DescribeFeatureType
|
|
320
|
-
*
|
|
321
|
-
* @param layers
|
|
322
|
-
* @param geoServerUrl
|
|
323
|
-
* @private
|
|
324
|
-
*/
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
_getGeoserverLayersData(layers, geoServerUrl) {
|
|
328
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
329
|
-
var getLayerData = layerName => __awaiter(this, void 0, void 0, function* () {
|
|
330
|
-
var params = new URLSearchParams({
|
|
331
|
-
service: 'wfs',
|
|
332
|
-
version: '1.1.0',
|
|
333
|
-
request: 'DescribeFeatureType',
|
|
334
|
-
typeName: layerName,
|
|
335
|
-
outputFormat: 'application/json',
|
|
336
|
-
exceptions: 'application/json'
|
|
337
|
-
});
|
|
338
|
-
var url_fetch = geoServerUrl + '?' + params.toString();
|
|
339
|
-
var response = yield fetch(url_fetch, {
|
|
340
|
-
headers: this.options.headers
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
if (!response.ok) {
|
|
344
|
-
throw new Error('');
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return yield response.json();
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
for (var layer of layers) {
|
|
351
|
-
var layerName = layer.name;
|
|
352
|
-
var layerLabel = layer.label || layerName;
|
|
353
|
-
|
|
354
|
-
try {
|
|
355
|
-
var data = yield getLayerData(layerName);
|
|
356
|
-
|
|
357
|
-
if (data) {
|
|
358
|
-
console.log(data);
|
|
359
|
-
var targetNamespace = data.targetNamespace;
|
|
360
|
-
var properties = data.featureTypes[0].properties; // Find the geometry field
|
|
361
|
-
|
|
362
|
-
var geom = properties.find(el => el.type.indexOf('gml:') >= 0);
|
|
363
|
-
this._geoServerData[layerName] = {
|
|
364
|
-
namespace: targetNamespace,
|
|
365
|
-
properties: properties,
|
|
366
|
-
geomType: geom.localType,
|
|
367
|
-
geomField: geom.name
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
} catch (err) {
|
|
371
|
-
this._showError("".concat(this._i18n.errors.layer, " \"").concat(layerLabel, "\""));
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Create map layers in wfs o wms modes.
|
|
378
|
-
*
|
|
379
|
-
* @param layers
|
|
380
|
-
* @private
|
|
381
|
-
*/
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
_createLayers(layers) {
|
|
385
|
-
var _this = this;
|
|
386
|
-
|
|
387
|
-
var layerLoaded = 0;
|
|
388
|
-
var layersNumber = 0; // Only count visibles
|
|
389
|
-
|
|
173
|
+
*/
|
|
174
|
+
class Wfst extends Control {
|
|
175
|
+
constructor(opt_options) {
|
|
176
|
+
super({
|
|
177
|
+
target: null,
|
|
178
|
+
element: controlElement
|
|
179
|
+
});
|
|
180
|
+
// Check if the selected language exists
|
|
181
|
+
this._i18n =
|
|
182
|
+
opt_options.language && opt_options.language in i18n
|
|
183
|
+
? i18n[opt_options.language]
|
|
184
|
+
: i18n[DEFAULT_LANGUAGE];
|
|
185
|
+
if (opt_options.i18n) {
|
|
186
|
+
// Merge custom translations
|
|
187
|
+
this._i18n = Object.assign(Object.assign({}, this._i18n), opt_options.i18n);
|
|
188
|
+
}
|
|
189
|
+
// Default options
|
|
190
|
+
const defaultOptions = {
|
|
191
|
+
geoServerUrl: null,
|
|
192
|
+
geoServerAdvanced: {
|
|
193
|
+
getCapabilitiesVersion: '1.3.0',
|
|
194
|
+
getFeatureVersion: '1.0.0',
|
|
195
|
+
describeFeatureTypeVersion: '1.1.0',
|
|
196
|
+
lockFeatureVersion: '1.1.0',
|
|
197
|
+
wfsTransactionVersion: '1.1.0',
|
|
198
|
+
projection: DEFAULT_GEOSERVER_SRS
|
|
199
|
+
},
|
|
200
|
+
headers: {},
|
|
201
|
+
layers: null,
|
|
202
|
+
evtType: 'singleclick',
|
|
203
|
+
active: true,
|
|
204
|
+
showControl: true,
|
|
205
|
+
useLockFeature: true,
|
|
206
|
+
minZoom: 9,
|
|
207
|
+
language: DEFAULT_LANGUAGE,
|
|
208
|
+
uploadFormats: '.geojson,.json,.kml',
|
|
209
|
+
processUpload: null,
|
|
210
|
+
beforeInsertFeature: null,
|
|
211
|
+
modal: {
|
|
212
|
+
animateClass: 'fade',
|
|
213
|
+
animateInClass: 'show',
|
|
214
|
+
transition: 300,
|
|
215
|
+
backdropTransition: 150,
|
|
216
|
+
templates: {
|
|
217
|
+
dialog: '<div class="modal-dialog modal-dialog-centered"></div>',
|
|
218
|
+
headerClose: `<button type="button" class="btn-close" data-dismiss="modal" aria-label="${this._i18n.labels.close}"><span aria-hidden="true">×</span></button>`
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
this._options = deepObjectAssign(defaultOptions, opt_options);
|
|
223
|
+
this._mapLayers = [];
|
|
224
|
+
this._countRequests = 0;
|
|
225
|
+
this._isEditModeOn = false;
|
|
226
|
+
// GeoServer
|
|
227
|
+
this._hasLockFeature = false;
|
|
228
|
+
this._hasTransaction = false;
|
|
229
|
+
this._geoServerCapabilities = null;
|
|
230
|
+
this._geoServerData = {};
|
|
231
|
+
// Editing
|
|
232
|
+
this._editedFeatures = new Set();
|
|
233
|
+
this._layerToInsertElements = this._options.layers[0].name; // By default, the first layer is ready to accept new draws
|
|
234
|
+
this._insertFeatures = [];
|
|
235
|
+
this._updateFeatures = [];
|
|
236
|
+
this._deleteFeatures = [];
|
|
237
|
+
// Formats
|
|
238
|
+
this._formatWFS = new WFS();
|
|
239
|
+
this._formatGeoJSON = new GeoJSON();
|
|
240
|
+
this._formatKml = new KML({
|
|
241
|
+
extractStyles: false,
|
|
242
|
+
showPointNames: false
|
|
243
|
+
});
|
|
244
|
+
this._xs = new XMLSerializer();
|
|
245
|
+
this._controlWidgetToolsDiv = controlElement;
|
|
246
|
+
this._controlWidgetToolsDiv.className = 'ol-wfst--tools-control';
|
|
247
|
+
this._initAsyncOperations();
|
|
248
|
+
}
|
|
390
249
|
/**
|
|
391
|
-
* When all the data is loaded, hide the loading
|
|
392
250
|
* @private
|
|
393
|
-
*/
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this.
|
|
400
|
-
|
|
401
|
-
|
|
251
|
+
*/
|
|
252
|
+
_onLoad() {
|
|
253
|
+
this._map = super.getMap();
|
|
254
|
+
this._view = this._map.getView();
|
|
255
|
+
this._viewport = this._map.getViewport();
|
|
256
|
+
// State
|
|
257
|
+
this._isVisible = this._view.getZoom() > this._options.minZoom;
|
|
258
|
+
this._createLayers(this._options.layers);
|
|
259
|
+
this._initMapElements(this._options.showControl, this._options.active);
|
|
260
|
+
}
|
|
402
261
|
/**
|
|
262
|
+
* Connect to the GeoServer and retrieve metadata about the service (GetCapabilities).
|
|
263
|
+
* Get each layer specs (DescribeFeatureType) and create the layers and map controls.
|
|
403
264
|
*
|
|
404
|
-
* @param
|
|
265
|
+
* @param layers
|
|
266
|
+
* @param showControl
|
|
267
|
+
* @param active
|
|
405
268
|
* @private
|
|
406
|
-
*/
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
params['BUFFER'] = buffer;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
var source = new TileWMS({
|
|
428
|
-
url: this.options.geoServerUrl,
|
|
429
|
-
params: params,
|
|
430
|
-
serverType: 'geoserver',
|
|
431
|
-
tileLoadFunction: (tile, src) => __awaiter(this, void 0, void 0, function* () {
|
|
432
|
-
try {
|
|
433
|
-
var response = yield fetch(src, {
|
|
434
|
-
headers: this.options.headers
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
if (!response.ok) {
|
|
438
|
-
throw new Error('');
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
var data = yield response.blob();
|
|
442
|
-
|
|
443
|
-
if (data !== undefined) {
|
|
444
|
-
tile.getImage().src = URL.createObjectURL(data);
|
|
445
|
-
} else {
|
|
446
|
-
throw new Error('');
|
|
447
|
-
}
|
|
448
|
-
} catch (err) {
|
|
449
|
-
tile.setState(TileState.ERROR);
|
|
450
|
-
} finally {
|
|
451
|
-
addLayerLoaded();
|
|
452
|
-
}
|
|
453
|
-
})
|
|
454
|
-
});
|
|
455
|
-
var layer_options = Object.assign({
|
|
456
|
-
name: layerName,
|
|
457
|
-
type: '_wms_',
|
|
458
|
-
minZoom: this.options.minZoom,
|
|
459
|
-
source: source,
|
|
460
|
-
visible: true,
|
|
461
|
-
zIndex: 4
|
|
462
|
-
}, layerParams);
|
|
463
|
-
var layer = new Tile(layer_options);
|
|
464
|
-
return layer;
|
|
465
|
-
};
|
|
269
|
+
*/
|
|
270
|
+
_initAsyncOperations() {
|
|
271
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
try {
|
|
273
|
+
// @ts-expect-error
|
|
274
|
+
this.on('allDescribeFeatureTypeLoaded', this._onLoad);
|
|
275
|
+
this._showLoading();
|
|
276
|
+
yield this._connectToGeoServerAndGetCapabilities();
|
|
277
|
+
if (this._options.layers) {
|
|
278
|
+
yield this._getGeoserverLayersData(this._options.layers, this._options.geoServerUrl);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
this._hideLoading();
|
|
283
|
+
this._showError(err.message, err);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
466
287
|
/**
|
|
288
|
+
* Get the capabilities from the GeoServer and check
|
|
289
|
+
* all the available operations.
|
|
467
290
|
*
|
|
468
|
-
* @
|
|
291
|
+
* @fires capabilitiesLoaded
|
|
469
292
|
* @private
|
|
470
|
-
*/
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
});
|
|
524
|
-
source.addFeatures(features);
|
|
525
|
-
} catch (err) {
|
|
526
|
-
this._showError(this._i18n.errors.geoserver);
|
|
527
|
-
|
|
528
|
-
console.error(err);
|
|
529
|
-
source.removeLoadedExtent(extent);
|
|
530
|
-
} finally {
|
|
531
|
-
addLayerLoaded();
|
|
532
|
-
}
|
|
533
|
-
})
|
|
534
|
-
});
|
|
535
|
-
var layer_options = Object.assign({
|
|
536
|
-
name: layerName,
|
|
537
|
-
type: '_wfs_',
|
|
538
|
-
minZoom: this.options.minZoom,
|
|
539
|
-
source: source,
|
|
540
|
-
visible: true,
|
|
541
|
-
zIndex: 2
|
|
542
|
-
}, layerParams);
|
|
543
|
-
var layer = new Vector(layer_options);
|
|
544
|
-
return layer;
|
|
545
|
-
};
|
|
546
|
-
|
|
547
|
-
var _loop = function _loop(layerParams) {
|
|
548
|
-
var layerName = layerParams.name; // Only create the layer if we can get the GeoserverData
|
|
549
|
-
|
|
550
|
-
if (_this._geoServerData[layerName]) {
|
|
551
|
-
var layer;
|
|
552
|
-
|
|
553
|
-
var _layerParams = _this.options.layers.find(e => e.name === layerName);
|
|
554
|
-
|
|
555
|
-
var mode = _layerParams.mode; // If mode is undefined, by default use wfs
|
|
556
|
-
|
|
557
|
-
if (!mode) {
|
|
558
|
-
_layerParams.mode = 'wfs';
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
if (_layerParams.mode === 'wfs') {
|
|
562
|
-
layer = newWfsLayer(_layerParams);
|
|
563
|
-
} else {
|
|
564
|
-
layer = newWmsLayer(_layerParams);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (layer.getVisible()) layersNumber++;
|
|
568
|
-
|
|
569
|
-
_this.map.addLayer(layer);
|
|
570
|
-
|
|
571
|
-
_this._mapLayers[layerName] = layer;
|
|
572
|
-
}
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
for (var layerParams of layers) {
|
|
576
|
-
_loop(layerParams);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
/**
|
|
580
|
-
* Create the edit layer to allow modify elements, add interactions,
|
|
581
|
-
* map controls and keyboard handlers.
|
|
582
|
-
*
|
|
583
|
-
* @param showControl
|
|
584
|
-
* @param active
|
|
585
|
-
* @private
|
|
586
|
-
*/
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
_initMapElements(showControl, active) {
|
|
590
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
591
|
-
// VectorLayer to store features on editing and isnerting
|
|
592
|
-
this._createEditLayer();
|
|
593
|
-
|
|
594
|
-
this._addInteractions();
|
|
595
|
-
|
|
596
|
-
this._addHandlers();
|
|
597
|
-
|
|
598
|
-
if (showControl) {
|
|
599
|
-
this._addMapControl();
|
|
600
|
-
} // By default, init in edit mode
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
this.activateEditMode(active);
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* @private
|
|
608
|
-
*/
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
_addInteractions() {
|
|
612
|
-
// Select the wfs feature already downloaded
|
|
613
|
-
var prepareWfsInteraction = () => {
|
|
614
|
-
// Interaction to select wfs layer elements
|
|
615
|
-
this.interactionWfsSelect = new Select({
|
|
616
|
-
hitTolerance: 10,
|
|
617
|
-
style: feature => this._styleFunction(feature),
|
|
618
|
-
toggleCondition: never,
|
|
619
|
-
filter: (feature, layer) => {
|
|
620
|
-
return !this._isEditModeOn && layer && layer.get('type') === '_wfs_';
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
this.map.addInteraction(this.interactionWfsSelect);
|
|
624
|
-
this.interactionWfsSelect.on('select', (_ref) => {
|
|
625
|
-
var {
|
|
626
|
-
selected,
|
|
627
|
-
deselected,
|
|
628
|
-
mapBrowserEvent
|
|
629
|
-
} = _ref;
|
|
630
|
-
var coordinate = mapBrowserEvent.coordinate;
|
|
631
|
-
|
|
632
|
-
if (selected.length) {
|
|
633
|
-
selected.forEach(feature => {
|
|
634
|
-
if (!this._editedFeatures.has(String(feature.getId()))) {
|
|
635
|
-
// Remove the feature from the original layer
|
|
636
|
-
var layer = this.interactionWfsSelect.getLayer(feature);
|
|
637
|
-
layer.getSource().removeFeature(feature);
|
|
638
|
-
|
|
639
|
-
this._addFeatureToEdit(feature, coordinate);
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
if (deselected.length) {
|
|
645
|
-
if (!this._isEditModeOn) {
|
|
646
|
-
deselected.forEach(feature => {
|
|
647
|
-
// Trigger deselect
|
|
648
|
-
// This is necessary for those times where two features overlap.
|
|
649
|
-
this.interactionSelectModify.getFeatures().remove(feature);
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
});
|
|
654
|
-
};
|
|
293
|
+
*/
|
|
294
|
+
_connectToGeoServerAndGetCapabilities() {
|
|
295
|
+
const _super = Object.create(null, {
|
|
296
|
+
dispatchEvent: { get: () => super.dispatchEvent }
|
|
297
|
+
});
|
|
298
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
299
|
+
/**
|
|
300
|
+
* @private
|
|
301
|
+
*/
|
|
302
|
+
const getCapabilities = () => __awaiter(this, void 0, void 0, function* () {
|
|
303
|
+
const params = new URLSearchParams({
|
|
304
|
+
service: 'wfs',
|
|
305
|
+
version: this._options.geoServerAdvanced.getCapabilitiesVersion,
|
|
306
|
+
request: 'GetCapabilities',
|
|
307
|
+
exceptions: 'application/json'
|
|
308
|
+
});
|
|
309
|
+
const url_fetch = this._options.geoServerUrl + '?' + params.toString();
|
|
310
|
+
try {
|
|
311
|
+
const response = yield fetch(url_fetch, {
|
|
312
|
+
headers: this._options.headers
|
|
313
|
+
});
|
|
314
|
+
if (!response.ok) {
|
|
315
|
+
throw new Error('');
|
|
316
|
+
}
|
|
317
|
+
const data = yield response.text();
|
|
318
|
+
const capabilities = new window.DOMParser().parseFromString(data, 'text/xml');
|
|
319
|
+
return capabilities;
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
throw new Error(this._i18n.errors.capabilities);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
this._geoServerCapabilities = yield getCapabilities();
|
|
326
|
+
// Available operations in the geoserver
|
|
327
|
+
const operations = this._geoServerCapabilities.getElementsByTagName('ows:Operation');
|
|
328
|
+
Array.from(operations).forEach((operation) => {
|
|
329
|
+
if (operation.getAttribute('name') === 'Transaction') {
|
|
330
|
+
this._hasTransaction = true;
|
|
331
|
+
}
|
|
332
|
+
else if (operation.getAttribute('name') === 'LockFeature') {
|
|
333
|
+
this._hasLockFeature = true;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
if (!this._hasTransaction) {
|
|
337
|
+
throw new Error(this._i18n.errors.wfst);
|
|
338
|
+
}
|
|
339
|
+
_super.dispatchEvent.call(this, {
|
|
340
|
+
type: 'getCapabilities',
|
|
341
|
+
// @ts-expect-error
|
|
342
|
+
data: this._geoServerCapabilities
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
}
|
|
655
346
|
/**
|
|
656
|
-
*
|
|
347
|
+
* Request and store data layers obtained by DescribeFeatureType
|
|
348
|
+
*
|
|
349
|
+
* @param layers
|
|
350
|
+
* @param geoServerUrl
|
|
657
351
|
* @private
|
|
658
|
-
*/
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}));
|
|
728
|
-
};
|
|
729
|
-
|
|
730
|
-
if (this.options.layers.find(layer => layer.mode === 'wfs')) {
|
|
731
|
-
prepareWfsInteraction();
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
if (this.options.layers.find(layer => layer.mode === 'wms')) {
|
|
735
|
-
prepareWmsInteraction();
|
|
736
|
-
} // Interaction to allow select features in the edit layer
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
this.interactionSelectModify = new Select({
|
|
740
|
-
style: feature => this._styleFunction(feature),
|
|
741
|
-
layers: [this._editLayer],
|
|
742
|
-
toggleCondition: never,
|
|
743
|
-
removeCondition: () => this._isEditModeOn ? true : false // Prevent deselect on clicking outside the feature
|
|
744
|
-
|
|
745
|
-
});
|
|
746
|
-
this.map.addInteraction(this.interactionSelectModify);
|
|
747
|
-
this.interactionModify = new Modify({
|
|
748
|
-
style: () => {
|
|
749
|
-
if (this._isEditModeOn) {
|
|
750
|
-
return new Style({
|
|
751
|
-
image: new Circle({
|
|
752
|
-
radius: 6,
|
|
753
|
-
fill: new Fill({
|
|
754
|
-
color: '#ff0000'
|
|
755
|
-
}),
|
|
756
|
-
stroke: new Stroke({
|
|
757
|
-
width: 2,
|
|
758
|
-
color: 'rgba(5, 5, 5, 0.9)'
|
|
759
|
-
})
|
|
760
|
-
})
|
|
761
|
-
});
|
|
762
|
-
} else {
|
|
763
|
-
return;
|
|
764
|
-
}
|
|
765
|
-
},
|
|
766
|
-
features: this.interactionSelectModify.getFeatures(),
|
|
767
|
-
condition: evt => {
|
|
768
|
-
return primaryAction(evt) && this._isEditModeOn;
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
this.map.addInteraction(this.interactionModify);
|
|
772
|
-
this.interactionSnap = new Snap({
|
|
773
|
-
source: this._editLayer.getSource()
|
|
774
|
-
});
|
|
775
|
-
this.map.addInteraction(this.interactionSnap);
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Layer to store temporary the elements to be edited
|
|
779
|
-
*
|
|
780
|
-
* @private
|
|
781
|
-
*/
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
_createEditLayer() {
|
|
785
|
-
this._editLayer = new Vector({
|
|
786
|
-
source: new Vector$1(),
|
|
787
|
-
zIndex: 5,
|
|
788
|
-
style: feature => this._styleFunction(feature)
|
|
789
|
-
});
|
|
790
|
-
this.map.addLayer(this._editLayer);
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* Add map handlers
|
|
794
|
-
*
|
|
795
|
-
* @private
|
|
796
|
-
*/
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
_addHandlers() {
|
|
352
|
+
*/
|
|
353
|
+
_getGeoserverLayersData(layers, geoServerUrl) {
|
|
354
|
+
const _super = Object.create(null, {
|
|
355
|
+
dispatchEvent: { get: () => super.dispatchEvent }
|
|
356
|
+
});
|
|
357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
358
|
+
/**
|
|
359
|
+
*
|
|
360
|
+
* @param layerName
|
|
361
|
+
* @fires describeFeatureType
|
|
362
|
+
* @fires allDescribeFeatureTypeLoaded
|
|
363
|
+
* @returns
|
|
364
|
+
* @private
|
|
365
|
+
*/
|
|
366
|
+
const getLayerData = (layerName) => __awaiter(this, void 0, void 0, function* () {
|
|
367
|
+
const params = new URLSearchParams({
|
|
368
|
+
service: 'wfs',
|
|
369
|
+
version: this._options.geoServerAdvanced
|
|
370
|
+
.describeFeatureTypeVersion,
|
|
371
|
+
request: 'DescribeFeatureType',
|
|
372
|
+
typeName: layerName,
|
|
373
|
+
outputFormat: 'application/json',
|
|
374
|
+
exceptions: 'application/json'
|
|
375
|
+
});
|
|
376
|
+
const url_fetch = geoServerUrl + '?' + params.toString();
|
|
377
|
+
const response = yield fetch(url_fetch, {
|
|
378
|
+
headers: this._options.headers
|
|
379
|
+
});
|
|
380
|
+
if (!response.ok) {
|
|
381
|
+
throw new Error('');
|
|
382
|
+
}
|
|
383
|
+
return yield response.json();
|
|
384
|
+
});
|
|
385
|
+
for (const layer of layers) {
|
|
386
|
+
const layerName = layer.name;
|
|
387
|
+
const layerLabel = layer.label || layerName;
|
|
388
|
+
try {
|
|
389
|
+
const data = yield getLayerData(layerName);
|
|
390
|
+
if (!data) {
|
|
391
|
+
throw new Error('');
|
|
392
|
+
}
|
|
393
|
+
_super.dispatchEvent.call(this, {
|
|
394
|
+
type: 'describeFeatureType',
|
|
395
|
+
// @ts-expect-error
|
|
396
|
+
layer: layerName,
|
|
397
|
+
data: data
|
|
398
|
+
});
|
|
399
|
+
const targetNamespace = data.targetNamespace;
|
|
400
|
+
const properties = data.featureTypes[0].properties;
|
|
401
|
+
// Find the geometry field
|
|
402
|
+
const geom = properties.find((el) => el.type.indexOf('gml:') >= 0);
|
|
403
|
+
this._geoServerData[layerName] = {
|
|
404
|
+
namespace: targetNamespace,
|
|
405
|
+
properties: properties,
|
|
406
|
+
geomType: geom.localType,
|
|
407
|
+
geomField: geom.name
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
throw new Error(`${this._i18n.errors.layer} "${layerLabel}"`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
_super.dispatchEvent.call(this, {
|
|
415
|
+
type: 'allDescribeFeatureTypeLoaded',
|
|
416
|
+
// @ts-expect-error
|
|
417
|
+
data: this._geoServerData
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
}
|
|
800
421
|
/**
|
|
422
|
+
* Create map layers in wfs o wms modes.
|
|
423
|
+
*
|
|
424
|
+
* @param layers
|
|
801
425
|
* @private
|
|
802
|
-
*/
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
426
|
+
*/
|
|
427
|
+
_createLayers(layers) {
|
|
428
|
+
let layerLoaded = 0;
|
|
429
|
+
let layersNumber = 0; // Only count visibles
|
|
430
|
+
/**
|
|
431
|
+
* When all the data is loaded, hide the loading
|
|
432
|
+
* @private
|
|
433
|
+
*/
|
|
434
|
+
const addLayerLoaded = () => {
|
|
435
|
+
layerLoaded++;
|
|
436
|
+
if (layerLoaded >= layersNumber) {
|
|
437
|
+
this._hideLoading();
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
*
|
|
442
|
+
* @param layerParams
|
|
443
|
+
* @private
|
|
444
|
+
*/
|
|
445
|
+
const newWmsLayer = (layerParams) => {
|
|
446
|
+
const layerName = layerParams.name;
|
|
447
|
+
const cqlFilter = layerParams.cqlFilter;
|
|
448
|
+
const buffer = layerParams.tilesBuffer;
|
|
449
|
+
const params = {
|
|
450
|
+
SERVICE: 'WMS',
|
|
451
|
+
LAYERS: layerName,
|
|
452
|
+
TILED: true
|
|
453
|
+
};
|
|
454
|
+
if (cqlFilter) {
|
|
455
|
+
params['CQL_FILTER'] = cqlFilter;
|
|
456
|
+
}
|
|
457
|
+
if (buffer) {
|
|
458
|
+
params['BUFFER'] = buffer;
|
|
459
|
+
}
|
|
460
|
+
const source = new TileWMS({
|
|
461
|
+
url: this._options.geoServerUrl,
|
|
462
|
+
params: params,
|
|
463
|
+
serverType: 'geoserver',
|
|
464
|
+
tileLoadFunction: (tile, src) => __awaiter(this, void 0, void 0, function* () {
|
|
465
|
+
try {
|
|
466
|
+
const response = yield fetch(src, {
|
|
467
|
+
headers: this._options.headers
|
|
468
|
+
});
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
throw new Error('');
|
|
471
|
+
}
|
|
472
|
+
const data = yield response.blob();
|
|
473
|
+
if (data !== undefined) {
|
|
474
|
+
tile.getImage().src = URL.createObjectURL(data);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
throw new Error('');
|
|
478
|
+
}
|
|
479
|
+
tile.setState(TileState.LOADED);
|
|
480
|
+
}
|
|
481
|
+
catch (err) {
|
|
482
|
+
tile.setState(TileState.ERROR);
|
|
483
|
+
}
|
|
484
|
+
})
|
|
485
|
+
});
|
|
486
|
+
let loading = 0;
|
|
487
|
+
let loaded = 0;
|
|
488
|
+
source.on('tileloadstart', () => {
|
|
489
|
+
loading++;
|
|
490
|
+
this._showLoading();
|
|
491
|
+
});
|
|
492
|
+
source.on(['tileloadend', 'tileloaderror'], () => {
|
|
493
|
+
loaded++;
|
|
494
|
+
setTimeout(() => {
|
|
495
|
+
if (loading === loaded)
|
|
496
|
+
addLayerLoaded();
|
|
497
|
+
}, 300);
|
|
498
|
+
});
|
|
499
|
+
const layer_options = Object.assign({ name: layerName, type: '_wms_', minZoom: this._options.minZoom, source: source, visible: true, zIndex: 1 }, layerParams);
|
|
500
|
+
const layer = new Tile(layer_options);
|
|
501
|
+
return layer;
|
|
502
|
+
};
|
|
503
|
+
/**
|
|
504
|
+
*
|
|
505
|
+
* @param layerParams
|
|
506
|
+
* @private
|
|
507
|
+
*/
|
|
508
|
+
const newWfsLayer = (layerParams) => {
|
|
509
|
+
const layerName = layerParams.name;
|
|
510
|
+
const cqlFilter = layerParams.cqlFilter;
|
|
511
|
+
const strategy = layerParams.wfsStrategy || 'bbox';
|
|
512
|
+
const source = new Vector$1({
|
|
513
|
+
format: new GeoJSON(),
|
|
514
|
+
strategy: strategy === 'bbox' ? bbox : all,
|
|
515
|
+
loader: (extent) => __awaiter(this, void 0, void 0, function* () {
|
|
516
|
+
try {
|
|
517
|
+
const params = new URLSearchParams({
|
|
518
|
+
service: 'wfs',
|
|
519
|
+
version: this._options.geoServerAdvanced
|
|
520
|
+
.getFeatureVersion,
|
|
521
|
+
request: 'GetFeature',
|
|
522
|
+
typename: layerName,
|
|
523
|
+
outputFormat: 'application/json',
|
|
524
|
+
exceptions: 'application/json',
|
|
525
|
+
srsName: this._options.geoServerAdvanced.projection.toString()
|
|
526
|
+
});
|
|
527
|
+
if (cqlFilter) {
|
|
528
|
+
params.append('cql_filter', cqlFilter);
|
|
529
|
+
}
|
|
530
|
+
// If bbox, add extent to the request
|
|
531
|
+
if (strategy === 'bbox') {
|
|
532
|
+
const extentGeoServer = transformExtent(extent, this._view.getProjection().getCode(), this._options.geoServerAdvanced.projection);
|
|
533
|
+
// https://docs.geoserver.org/stable/en/user/services/wfs/reference.html
|
|
534
|
+
// request features using a bounding box with CRS maybe different from featureTypes native CRS
|
|
535
|
+
params.append('bbox', extentGeoServer.toString() +
|
|
536
|
+
`,${this._options.geoServerAdvanced.projection}`);
|
|
537
|
+
}
|
|
538
|
+
const url_fetch = this._options.geoServerUrl +
|
|
539
|
+
'?' +
|
|
540
|
+
params.toString();
|
|
541
|
+
const response = yield fetch(url_fetch, {
|
|
542
|
+
headers: this._options.headers
|
|
543
|
+
});
|
|
544
|
+
if (!response.ok) {
|
|
545
|
+
throw new Error('');
|
|
546
|
+
}
|
|
547
|
+
const data = yield response.json();
|
|
548
|
+
this.dispatchEvent({
|
|
549
|
+
type: 'getFeature',
|
|
550
|
+
// @ts-expect-error
|
|
551
|
+
layer: layerName,
|
|
552
|
+
data: data
|
|
553
|
+
});
|
|
554
|
+
const features = source.getFormat().readFeatures(data, {
|
|
555
|
+
featureProjection: this._view
|
|
556
|
+
.getProjection()
|
|
557
|
+
.getCode(),
|
|
558
|
+
dataProjection: this._options.geoServerAdvanced
|
|
559
|
+
.projection
|
|
560
|
+
});
|
|
561
|
+
features.forEach((feature) => {
|
|
562
|
+
feature.set('_layerName_', layerName,
|
|
563
|
+
/* silent = */ true);
|
|
564
|
+
});
|
|
565
|
+
source.addFeatures(features);
|
|
566
|
+
source.dispatchEvent('featuresloadend');
|
|
567
|
+
}
|
|
568
|
+
catch (err) {
|
|
569
|
+
source.dispatchEvent('featuresloaderror');
|
|
570
|
+
this._showError(this._i18n.errors.geoserver, err);
|
|
571
|
+
source.removeLoadedExtent(extent);
|
|
572
|
+
}
|
|
573
|
+
})
|
|
574
|
+
});
|
|
575
|
+
let loading = 0;
|
|
576
|
+
let loaded = 0;
|
|
577
|
+
source.on('featuresloadstart', () => {
|
|
578
|
+
loading++;
|
|
579
|
+
this._showLoading();
|
|
580
|
+
});
|
|
581
|
+
source.on(['featuresloadend', 'featuresloaderror'], () => {
|
|
582
|
+
loaded++;
|
|
583
|
+
setTimeout(() => {
|
|
584
|
+
if (loading === loaded)
|
|
585
|
+
addLayerLoaded();
|
|
586
|
+
}, 300);
|
|
587
|
+
});
|
|
588
|
+
const layer_options = Object.assign({ name: layerName, type: '_wfs_', minZoom: this._options.minZoom, source: source, visible: true, zIndex: 2 }, layerParams);
|
|
589
|
+
const layer = new Vector(layer_options);
|
|
590
|
+
return layer;
|
|
591
|
+
};
|
|
592
|
+
for (const layerParams of layers) {
|
|
593
|
+
const layerName = layerParams.name;
|
|
594
|
+
// Only create the layer if we can get the GeoserverData
|
|
595
|
+
if (this._geoServerData[layerName]) {
|
|
596
|
+
let layer;
|
|
597
|
+
const layerParams = this._options.layers.find((e) => e.name === layerName);
|
|
598
|
+
const mode = layerParams.mode;
|
|
599
|
+
// If mode is undefined, by default use wfs
|
|
600
|
+
if (!mode) {
|
|
601
|
+
layerParams.mode = 'wfs';
|
|
602
|
+
}
|
|
603
|
+
if (layerParams.mode === 'wfs') {
|
|
604
|
+
layer = newWfsLayer(layerParams);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
layer = newWmsLayer(layerParams);
|
|
608
|
+
}
|
|
609
|
+
if (layer.getVisible())
|
|
610
|
+
layersNumber++;
|
|
611
|
+
this._map.addLayer(layer);
|
|
612
|
+
this._mapLayers[layerName] = layer;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
836
616
|
/**
|
|
617
|
+
* Create the edit layer to allow modify elements, add interactions,
|
|
618
|
+
* map controls and keyboard handlers.
|
|
619
|
+
*
|
|
620
|
+
* @param showControl
|
|
621
|
+
* @param active
|
|
837
622
|
* @private
|
|
838
|
-
*/
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
* @private
|
|
1356
|
-
*/
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
_isFeatureEdited(feature) {
|
|
1360
|
-
return this._editedFeatures.has(String(feature.getId()));
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
*
|
|
1364
|
-
* @param feature
|
|
1365
|
-
* @private
|
|
1366
|
-
*/
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
_deselectEditFeature(feature) {
|
|
1370
|
-
this._removeOverlayHelper(feature);
|
|
1371
|
-
}
|
|
1372
|
-
/**
|
|
1373
|
-
*
|
|
1374
|
-
* @param feature
|
|
1375
|
-
* @param layerName
|
|
1376
|
-
* @private
|
|
1377
|
-
*/
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
_restoreFeatureToLayer(feature, layerName) {
|
|
1381
|
-
layerName = layerName || feature.get('_layerName_');
|
|
1382
|
-
var layer = this._mapLayers[layerName];
|
|
1383
|
-
layer.getSource().addFeature(feature);
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
_removeFeatureFromTmpLayer(feature) {
|
|
1387
|
-
// Remove element from the Layer
|
|
1388
|
-
this._editLayer.getSource().removeFeature(feature);
|
|
1389
|
-
}
|
|
1390
|
-
/**
|
|
1391
|
-
* Trigger on deselecting a feature from in the Edit layer
|
|
1392
|
-
*
|
|
1393
|
-
* @private
|
|
1394
|
-
*/
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
_onDeselectFeatureEvent() {
|
|
1398
|
-
var checkIfFeatureIsChanged = feature => {
|
|
1399
|
-
var layerName = feature.get('_layerName_');
|
|
1400
|
-
var {
|
|
1401
|
-
mode
|
|
1402
|
-
} = this.options.layers.find(layer => layer.name === layerName);
|
|
1403
|
-
|
|
1404
|
-
if (mode === 'wfs') {
|
|
1405
|
-
this.interactionWfsSelect.getFeatures().remove(feature);
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
if (this._isFeatureEdited(feature)) {
|
|
1409
|
-
this._transactWFS('update', feature, layerName);
|
|
1410
|
-
} else {
|
|
1411
|
-
// Si es wfs y el elemento no tuvo cambios, lo devolvemos a la layer original
|
|
1412
|
-
if (mode === 'wfs') {
|
|
1413
|
-
this._restoreFeatureToLayer(feature, layerName);
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
this._removeFeatureFromTmpLayer(feature);
|
|
1417
|
-
}
|
|
1418
|
-
}; // This is fired when a feature is deselected and fires the transaction process
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
this._keySelect = this.interactionSelectModify.getFeatures().on('remove', evt => {
|
|
1422
|
-
var feature = evt.element;
|
|
1423
|
-
|
|
1424
|
-
this._deselectEditFeature(feature);
|
|
1425
|
-
|
|
1426
|
-
checkIfFeatureIsChanged(feature);
|
|
1427
|
-
|
|
1428
|
-
this._editModeOff();
|
|
1429
|
-
});
|
|
1430
|
-
}
|
|
1431
|
-
/**
|
|
1432
|
-
* Trigger on removing a feature from the Edit layer
|
|
1433
|
-
*
|
|
1434
|
-
* @private
|
|
1435
|
-
*/
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
_onRemoveFeatureEvent() {
|
|
1439
|
-
// If a feature is removed from the edit layer
|
|
1440
|
-
this._keyRemove = this._editLayer.getSource().on('removefeature', evt => {
|
|
1441
|
-
var feature = evt.feature;
|
|
1442
|
-
|
|
1443
|
-
if (!feature.get('_delete_')) {
|
|
1444
|
-
return;
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
if (this._keySelect) {
|
|
1448
|
-
unByKey(this._keySelect);
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
var layerName = feature.get('_layerName_');
|
|
1452
|
-
|
|
1453
|
-
this._transactWFS('delete', feature, layerName);
|
|
1454
|
-
|
|
1455
|
-
this._deselectEditFeature(feature);
|
|
1456
|
-
|
|
1457
|
-
this._editModeOff();
|
|
1458
|
-
|
|
1459
|
-
if (this._keySelect) {
|
|
1460
|
-
setTimeout(() => {
|
|
1461
|
-
this._onDeselectFeatureEvent();
|
|
1462
|
-
}, 150);
|
|
1463
|
-
}
|
|
1464
|
-
});
|
|
1465
|
-
}
|
|
1466
|
-
/**
|
|
1467
|
-
* Master style that handles two modes on the Edit Layer:
|
|
1468
|
-
* - one is the basic, showing only the vertices
|
|
1469
|
-
* - and the other when modify is active, showing bigger vertices
|
|
1470
|
-
*
|
|
1471
|
-
* @param feature
|
|
1472
|
-
* @private
|
|
1473
|
-
*/
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
_styleFunction(feature) {
|
|
1477
|
-
var getVertexs = feature => {
|
|
1478
|
-
var geometry = feature.getGeometry();
|
|
1479
|
-
var type = geometry.getType();
|
|
1480
|
-
|
|
1481
|
-
if (type === GeometryType.GEOMETRY_COLLECTION) {
|
|
1482
|
-
geometry = geometry.getGeometries()[0];
|
|
1483
|
-
type = geometry.getType();
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
var coordinates = geometry.getCoordinates();
|
|
1487
|
-
var flatCoordinates = null;
|
|
1488
|
-
|
|
1489
|
-
if (type === GeometryType.POLYGON || type === GeometryType.MULTI_LINE_STRING) {
|
|
1490
|
-
flatCoordinates = coordinates.flat(1);
|
|
1491
|
-
} else if (type === GeometryType.MULTI_POLYGON) {
|
|
1492
|
-
flatCoordinates = coordinates.flat(2);
|
|
1493
|
-
} else {
|
|
1494
|
-
flatCoordinates = coordinates;
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
if (!flatCoordinates || !flatCoordinates.length) {
|
|
1498
|
-
return;
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
return new MultiPoint(flatCoordinates);
|
|
1502
|
-
};
|
|
1503
|
-
|
|
1504
|
-
var geometry = feature.getGeometry();
|
|
1505
|
-
var type = geometry.getType();
|
|
1506
|
-
|
|
1507
|
-
if (type === GeometryType.GEOMETRY_COLLECTION) {
|
|
1508
|
-
geometry = geometry.getGeometries()[0];
|
|
1509
|
-
type = geometry.getType();
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
switch (type) {
|
|
1513
|
-
case 'Point':
|
|
1514
|
-
case 'MultiPoint':
|
|
1515
|
-
if (this._isEditModeOn) {
|
|
1516
|
-
return [new Style({
|
|
1517
|
-
image: new Circle({
|
|
1518
|
-
radius: 6,
|
|
1519
|
-
fill: new Fill({
|
|
1520
|
-
color: '#000000'
|
|
1521
|
-
})
|
|
1522
|
-
})
|
|
1523
|
-
}), new Style({
|
|
1524
|
-
image: new Circle({
|
|
1525
|
-
radius: 4,
|
|
1526
|
-
fill: new Fill({
|
|
1527
|
-
color: '#ff0000'
|
|
1528
|
-
})
|
|
1529
|
-
})
|
|
1530
|
-
})];
|
|
1531
|
-
} else {
|
|
1532
|
-
return [new Style({
|
|
1533
|
-
image: new Circle({
|
|
1534
|
-
radius: 5,
|
|
1535
|
-
fill: new Fill({
|
|
1536
|
-
color: '#ff0000'
|
|
1537
|
-
})
|
|
1538
|
-
})
|
|
1539
|
-
}), new Style({
|
|
1540
|
-
image: new Circle({
|
|
1541
|
-
radius: 2,
|
|
1542
|
-
fill: new Fill({
|
|
1543
|
-
color: '#000000'
|
|
1544
|
-
})
|
|
1545
|
-
})
|
|
1546
|
-
})];
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
default:
|
|
1550
|
-
// If editing mode is active, show bigger vertex
|
|
1551
|
-
if (this._isEditModeOn || this._isDrawModeOn) {
|
|
1552
|
-
return [new Style({
|
|
1553
|
-
stroke: new Stroke({
|
|
1554
|
-
color: 'rgba( 255, 0, 0, 1)',
|
|
1555
|
-
width: 4
|
|
1556
|
-
}),
|
|
1557
|
-
fill: new Fill({
|
|
1558
|
-
color: 'rgba(255, 0, 0, 0.7)'
|
|
1559
|
-
})
|
|
1560
|
-
}), new Style({
|
|
1561
|
-
image: new Circle({
|
|
1562
|
-
radius: 4,
|
|
1563
|
-
fill: new Fill({
|
|
1564
|
-
color: '#ff0000'
|
|
1565
|
-
}),
|
|
1566
|
-
stroke: new Stroke({
|
|
1567
|
-
width: 2,
|
|
1568
|
-
color: 'rgba(5, 5, 5, 0.9)'
|
|
1569
|
-
})
|
|
1570
|
-
}),
|
|
1571
|
-
geometry: feature => getVertexs(feature)
|
|
1572
|
-
}), new Style({
|
|
1573
|
-
stroke: new Stroke({
|
|
1574
|
-
color: 'rgba(255, 255, 255, 0.7)',
|
|
1575
|
-
width: 2
|
|
1576
|
-
})
|
|
1577
|
-
})];
|
|
1578
|
-
} else {
|
|
1579
|
-
return [new Style({
|
|
1580
|
-
image: new Circle({
|
|
1581
|
-
radius: 2,
|
|
1582
|
-
fill: new Fill({
|
|
1583
|
-
color: '#000000'
|
|
1584
|
-
})
|
|
1585
|
-
}),
|
|
1586
|
-
geometry: feature => getVertexs(feature)
|
|
1587
|
-
}), new Style({
|
|
1588
|
-
stroke: new Stroke({
|
|
1589
|
-
color: '#ff0000',
|
|
1590
|
-
width: 4
|
|
1591
|
-
}),
|
|
1592
|
-
fill: new Fill({
|
|
1593
|
-
color: 'rgba(255, 0, 0, 0.7)'
|
|
1594
|
-
})
|
|
1595
|
-
})];
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
/**
|
|
1601
|
-
*
|
|
1602
|
-
* @param feature
|
|
1603
|
-
* @private
|
|
1604
|
-
*/
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
_editModeOn(feature) {
|
|
1608
|
-
this._editFeatureOriginal = feature.clone();
|
|
1609
|
-
this._isEditModeOn = true; // To refresh the style
|
|
1610
|
-
|
|
1611
|
-
this._editLayer.getSource().changed();
|
|
1612
|
-
|
|
1613
|
-
this._removeOverlayHelper(feature);
|
|
1614
|
-
|
|
1615
|
-
var controlDiv = document.createElement('div');
|
|
1616
|
-
controlDiv.className = 'ol-wfst--changes-control';
|
|
1617
|
-
var elements = document.createElement('div');
|
|
1618
|
-
elements.className = 'ol-wfst--changes-control-el';
|
|
1619
|
-
var elementId = document.createElement('div');
|
|
1620
|
-
elementId.className = 'ol-wfst--changes-control-id';
|
|
1621
|
-
elementId.innerHTML = "<b>".concat(this._i18n.labels.editMode, "</b> - <i>").concat(String(feature.getId()), "</i>");
|
|
1622
|
-
var acceptButton = document.createElement('button');
|
|
1623
|
-
acceptButton.type = 'button';
|
|
1624
|
-
acceptButton.textContent = this._i18n.labels.apply;
|
|
1625
|
-
acceptButton.className = 'btn btn-primary';
|
|
1626
|
-
|
|
1627
|
-
acceptButton.onclick = () => {
|
|
1628
|
-
this._showLoading();
|
|
1629
|
-
|
|
1630
|
-
this.interactionSelectModify.getFeatures().remove(feature);
|
|
1631
|
-
};
|
|
1632
|
-
|
|
1633
|
-
var cancelButton = document.createElement('button');
|
|
1634
|
-
cancelButton.type = 'button';
|
|
1635
|
-
cancelButton.textContent = this._i18n.labels.cancel;
|
|
1636
|
-
cancelButton.className = 'btn btn-secondary';
|
|
1637
|
-
|
|
1638
|
-
cancelButton.onclick = () => {
|
|
1639
|
-
feature.setGeometry(this._editFeatureOriginal.getGeometry());
|
|
1640
|
-
|
|
1641
|
-
this._removeFeatureFromEditList(feature);
|
|
1642
|
-
|
|
1643
|
-
this.interactionSelectModify.getFeatures().remove(feature);
|
|
1644
|
-
};
|
|
1645
|
-
|
|
1646
|
-
elements.append(elementId);
|
|
1647
|
-
elements.append(cancelButton);
|
|
1648
|
-
elements.append(acceptButton);
|
|
1649
|
-
controlDiv.append(elements);
|
|
1650
|
-
this._controlApplyDiscardChanges = new Control({
|
|
1651
|
-
element: controlDiv
|
|
1652
|
-
});
|
|
1653
|
-
this.map.addControl(this._controlApplyDiscardChanges);
|
|
1654
|
-
}
|
|
1655
|
-
/**
|
|
1656
|
-
* @private
|
|
1657
|
-
*/
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
_editModeOff() {
|
|
1661
|
-
this._isEditModeOn = false;
|
|
1662
|
-
this.map.removeControl(this._controlApplyDiscardChanges);
|
|
1663
|
-
}
|
|
1664
|
-
/**
|
|
1665
|
-
* Remove a feature from the edit Layer and from the Geoserver
|
|
1666
|
-
*
|
|
1667
|
-
* @param feature
|
|
1668
|
-
* @private
|
|
1669
|
-
*/
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
_deleteFeature(feature, confirm) {
|
|
1673
|
-
var deleteEl = () => {
|
|
1674
|
-
var features = Array.isArray(feature) ? feature : [feature];
|
|
1675
|
-
features.forEach(feature => {
|
|
1676
|
-
feature.set('_delete_', true, true);
|
|
1677
|
-
|
|
1678
|
-
this._editLayer.getSource().removeFeature(feature);
|
|
1679
|
-
});
|
|
1680
|
-
this.interactionSelectModify.getFeatures().clear();
|
|
1681
|
-
var layerName = feature.get('_layerName_');
|
|
1682
|
-
var {
|
|
1683
|
-
mode
|
|
1684
|
-
} = this.options.layers.find(layer => layer.name === layerName);
|
|
1685
|
-
|
|
1686
|
-
if (mode === 'wfs') {
|
|
1687
|
-
this.interactionWfsSelect.getFeatures().remove(feature);
|
|
1688
|
-
}
|
|
1689
|
-
};
|
|
1690
|
-
|
|
1691
|
-
if (confirm) {
|
|
1692
|
-
var confirmModal = Modal.confirm(this._i18n.labels.confirmDelete, {
|
|
1693
|
-
animateInClass: 'in'
|
|
1694
|
-
});
|
|
1695
|
-
confirmModal.show().once('dismiss', function (modal, ev, button) {
|
|
1696
|
-
if (button && button.value) {
|
|
1697
|
-
deleteEl();
|
|
1698
|
-
}
|
|
1699
|
-
});
|
|
1700
|
-
} else {
|
|
1701
|
-
deleteEl();
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
/**
|
|
1705
|
-
* Add a feature to the Edit Layer to allow editing, and creates an Overlay Helper to show options
|
|
1706
|
-
*
|
|
1707
|
-
* @param feature
|
|
1708
|
-
* @param coordinate
|
|
1709
|
-
* @param layerName
|
|
1710
|
-
* @private
|
|
1711
|
-
*/
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
_addFeatureToEdit(feature) {
|
|
1715
|
-
var coordinate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
1716
|
-
var layerName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
1717
|
-
|
|
1718
|
-
var prepareOverlay = () => {
|
|
1719
|
-
var svgFields = "<img src=\"".concat(img$1, "\"/>");
|
|
1720
|
-
var editFieldsEl = document.createElement('div');
|
|
1721
|
-
editFieldsEl.className = 'ol-wfst--edit-button-cnt';
|
|
1722
|
-
editFieldsEl.innerHTML = "<button class=\"ol-wfst--edit-button\" type=\"button\" title=\"".concat(this._i18n.labels.editFields, "\">").concat(svgFields, "</button>");
|
|
1723
|
-
|
|
1724
|
-
editFieldsEl.onclick = () => {
|
|
1725
|
-
this._initEditFieldsModal(feature);
|
|
1726
|
-
};
|
|
1727
|
-
|
|
1728
|
-
var buttons = document.createElement('div');
|
|
1729
|
-
buttons.append(editFieldsEl);
|
|
1730
|
-
var svgGeom = "<img src=\"".concat(img$2, "\"/>");
|
|
1731
|
-
var editGeomEl = document.createElement('div');
|
|
1732
|
-
editGeomEl.className = 'ol-wfst--edit-button-cnt';
|
|
1733
|
-
editGeomEl.innerHTML = "<button class=\"ol-wfst--edit-button\" type=\"button\" title=\"".concat(this._i18n.labels.editGeom, "\">").concat(svgGeom, "</button>");
|
|
1734
|
-
|
|
1735
|
-
editGeomEl.onclick = () => {
|
|
1736
|
-
this._editModeOn(feature);
|
|
1737
|
-
};
|
|
1738
|
-
|
|
1739
|
-
buttons.append(editGeomEl);
|
|
1740
|
-
var position = coordinate || getCenter(feature.getGeometry().getExtent());
|
|
1741
|
-
var buttonsOverlay = new Overlay({
|
|
1742
|
-
id: feature.getId(),
|
|
1743
|
-
position: position,
|
|
1744
|
-
positioning: OverlayPositioning.CENTER_CENTER,
|
|
1745
|
-
element: buttons,
|
|
1746
|
-
offset: [0, -40],
|
|
1747
|
-
stopEvent: true
|
|
1748
|
-
});
|
|
1749
|
-
this.map.addOverlay(buttonsOverlay);
|
|
1750
|
-
};
|
|
1751
|
-
|
|
1752
|
-
if (layerName) {
|
|
1753
|
-
// Guardamos el nombre de la capa de donde sale la feature
|
|
1754
|
-
feature.set('_layerName_', layerName);
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
var props = feature ? feature.getProperties() : '';
|
|
1758
|
-
|
|
1759
|
-
if (props) {
|
|
1760
|
-
if (feature.getGeometry()) {
|
|
1761
|
-
this._editLayer.getSource().addFeature(feature);
|
|
1762
|
-
|
|
1763
|
-
this.interactionSelectModify.getFeatures().push(feature);
|
|
1764
|
-
prepareOverlay();
|
|
1765
|
-
|
|
1766
|
-
if (this._useLockFeature && this._hasLockFeature) {
|
|
1767
|
-
this._lockFeature(feature.getId(), feature.get('_layerName_'));
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
/**
|
|
1773
|
-
* Removes in the DOM the class of the tools
|
|
1774
|
-
* @private
|
|
1775
|
-
*/
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
_resetStateButtons() {
|
|
1779
|
-
var activeBtn = document.querySelector('.ol-wfst--tools-control-btn.wfst--active');
|
|
1780
|
-
|
|
1781
|
-
if (activeBtn) {
|
|
1782
|
-
activeBtn.classList.remove('wfst--active');
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
/**
|
|
1786
|
-
* Confirm modal before transact to the GeoServer the features in the file
|
|
1787
|
-
*
|
|
1788
|
-
* @param content
|
|
1789
|
-
* @param featureToInsert
|
|
1790
|
-
* @private
|
|
1791
|
-
*/
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
_initUploadFileModal(content, featuresToInsert) {
|
|
1795
|
-
var footer = "\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">\n ".concat(this._i18n.labels.cancel, "\n </button>\n <button type=\"button\" class=\"btn btn-primary\" data-action=\"save\" data-dismiss=\"modal\">\n ").concat(this._i18n.labels.upload, "\n </button>\n ");
|
|
1796
|
-
var modal = new Modal({
|
|
1797
|
-
header: true,
|
|
1798
|
-
headerClose: false,
|
|
1799
|
-
title: this._i18n.labels.uploadFeatures + ' ' + this._layerToInsertElements,
|
|
1800
|
-
content: content,
|
|
1801
|
-
backdrop: 'static',
|
|
1802
|
-
footer: footer,
|
|
1803
|
-
animateInClass: 'in'
|
|
1804
|
-
}).show();
|
|
1805
|
-
modal.on('dismiss', (modal, event) => {
|
|
1806
|
-
// On saving changes
|
|
1807
|
-
if (event.target.dataset.action === 'save') {
|
|
1808
|
-
this._transactWFS('insert', featuresToInsert, this._layerToInsertElements);
|
|
1809
|
-
} else {
|
|
1810
|
-
// On cancel button
|
|
1811
|
-
this._editLayer.getSource().clear();
|
|
1812
|
-
}
|
|
1813
|
-
});
|
|
1814
|
-
}
|
|
1815
|
-
/**
|
|
1816
|
-
* Parse and check geometry of uploaded files
|
|
1817
|
-
*
|
|
1818
|
-
* @param evt
|
|
1819
|
-
* @private
|
|
1820
|
-
*/
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
_processUploadFile(evt) {
|
|
1824
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1825
|
-
/**
|
|
1826
|
-
* Read data file
|
|
1827
|
-
* @param file
|
|
1828
|
-
* @private
|
|
1829
|
-
*/
|
|
1830
|
-
var fileReader = file => {
|
|
1831
|
-
return new Promise((resolve, reject) => {
|
|
1832
|
-
var reader = new FileReader();
|
|
1833
|
-
reader.addEventListener('load', e => __awaiter(this, void 0, void 0, function* () {
|
|
1834
|
-
var fileData = e.target.result;
|
|
1835
|
-
resolve(fileData);
|
|
1836
|
-
}));
|
|
1837
|
-
reader.addEventListener('error', err => {
|
|
1838
|
-
console.error('Error' + err);
|
|
1839
|
-
reject();
|
|
1840
|
-
});
|
|
1841
|
-
reader.readAsText(file);
|
|
1842
|
-
});
|
|
1843
|
-
};
|
|
1844
|
-
/**
|
|
1845
|
-
* Attemp to change the geometry feature to the layer
|
|
1846
|
-
* @param feature
|
|
1847
|
-
* @private
|
|
1848
|
-
*/
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
var fixGeometry = feature => {
|
|
1852
|
-
// Geometry of the layer
|
|
1853
|
-
var geomTypeLayer = this._geoServerData[this._layerToInsertElements].geomType;
|
|
1854
|
-
var geomTypeFeature = feature.getGeometry().getType();
|
|
1855
|
-
var geom;
|
|
1856
|
-
|
|
1857
|
-
switch (geomTypeFeature) {
|
|
1858
|
-
case 'Point':
|
|
1859
|
-
{
|
|
1860
|
-
if (geomTypeLayer === 'MultiPoint') {
|
|
1861
|
-
var coords = feature.getGeometry().getCoordinates();
|
|
1862
|
-
geom = new MultiPoint([coords]);
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
|
-
break;
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
case 'LineString':
|
|
1869
|
-
if (geomTypeLayer === 'MultiLineString') {
|
|
1870
|
-
var _coords = feature.getGeometry().getCoordinates();
|
|
1871
|
-
|
|
1872
|
-
geom = new MultiLineString([_coords]);
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
|
-
break;
|
|
1876
|
-
|
|
1877
|
-
case 'Polygon':
|
|
1878
|
-
if (geomTypeLayer === 'MultiPolygon') {
|
|
1879
|
-
var _coords2 = feature.getGeometry().getCoordinates();
|
|
1880
|
-
|
|
1881
|
-
geom = new MultiPolygon([_coords2]);
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
break;
|
|
1885
|
-
|
|
1886
|
-
default:
|
|
1887
|
-
geom = null;
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
if (!geom) {
|
|
1891
|
-
return null;
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
feature.setGeometry(geom);
|
|
1895
|
-
return feature;
|
|
1896
|
-
};
|
|
1897
|
-
/**
|
|
1898
|
-
* Check if the feature has the same geometry as the target layer
|
|
1899
|
-
* @param feature
|
|
1900
|
-
* @private
|
|
1901
|
-
*/
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
var checkGeometry = feature => {
|
|
1905
|
-
// Geometry of the layer
|
|
1906
|
-
var geomTypeLayer = this._geoServerData[this._layerToInsertElements].geomType;
|
|
1907
|
-
var geomTypeFeature = feature.getGeometry().getType(); // This geom accepts every type of geometry
|
|
1908
|
-
|
|
1909
|
-
if (geomTypeLayer === GeometryType.GEOMETRY_COLLECTION) {
|
|
1910
|
-
return true;
|
|
1911
|
-
}
|
|
1912
|
-
|
|
1913
|
-
return geomTypeFeature === geomTypeLayer;
|
|
1914
|
-
};
|
|
1915
|
-
|
|
1916
|
-
var file = evt.target.files[0];
|
|
1917
|
-
var features;
|
|
1918
|
-
|
|
1919
|
-
if (!file) {
|
|
1920
|
-
return;
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
var extension = file.name.split('.').pop().toLowerCase();
|
|
1924
|
-
|
|
1925
|
-
try {
|
|
1926
|
-
// If the user uses a custom fucntion...
|
|
1927
|
-
if (this.options.processUpload) {
|
|
1928
|
-
features = this.options.processUpload(file);
|
|
1929
|
-
} // If the user functions return features, we dont process anything more
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
if (!features) {
|
|
1933
|
-
var string = yield fileReader(file);
|
|
1934
|
-
|
|
1935
|
-
if (extension === 'geojson' || extension === 'json') {
|
|
1936
|
-
features = this._formatGeoJSON.readFeatures(string, {
|
|
1937
|
-
featureProjection: this.view.getProjection().getCode()
|
|
1938
|
-
});
|
|
1939
|
-
} else if (extension === 'kml') {
|
|
1940
|
-
features = this._formatKml.readFeatures(string, {
|
|
1941
|
-
featureProjection: this.view.getProjection().getCode()
|
|
1942
|
-
});
|
|
1943
|
-
} else {
|
|
1944
|
-
this._showError(this._i18n.errors.badFormat);
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
} catch (err) {
|
|
1948
|
-
this._showError(this._i18n.errors.badFile);
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
var invalidFeaturesCount = 0;
|
|
1952
|
-
var validFeaturesCount = 0;
|
|
1953
|
-
var featuresToInsert = [];
|
|
1954
|
-
|
|
1955
|
-
for (var feature of features) {
|
|
1956
|
-
// If the geometry doesn't correspond to the layer, try to fixit.
|
|
1957
|
-
// If we can't, don't use it
|
|
1958
|
-
if (!checkGeometry(feature)) {
|
|
1959
|
-
feature = fixGeometry(feature);
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
if (feature) {
|
|
1963
|
-
featuresToInsert.push(feature);
|
|
1964
|
-
validFeaturesCount++;
|
|
1965
|
-
} else {
|
|
1966
|
-
invalidFeaturesCount++;
|
|
1967
|
-
continue;
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
|
-
if (!validFeaturesCount) {
|
|
1972
|
-
this._showError(this._i18n.errors.noValidGeometry);
|
|
1973
|
-
} else {
|
|
1974
|
-
this._resetStateButtons();
|
|
1975
|
-
|
|
1976
|
-
this.activateEditMode();
|
|
1977
|
-
var content = "\n ".concat(this._i18n.labels.validFeatures, ": ").concat(validFeaturesCount, "<br>\n ").concat(invalidFeaturesCount ? "".concat(this._i18n.labels.invalidFeatures, ": ").concat(invalidFeaturesCount) : '', "\n ");
|
|
1978
|
-
|
|
1979
|
-
this._initUploadFileModal(content, featuresToInsert);
|
|
1980
|
-
|
|
1981
|
-
this._editLayer.getSource().addFeatures(featuresToInsert);
|
|
1982
|
-
|
|
1983
|
-
this.view.fit(this._editLayer.getSource().getExtent(), {
|
|
1984
|
-
size: this.map.getSize(),
|
|
1985
|
-
maxZoom: 21,
|
|
1986
|
-
padding: [100, 100, 100, 100]
|
|
1987
|
-
});
|
|
1988
|
-
} // Reset the input to allow another onChange trigger
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
evt.target.value = null;
|
|
1992
|
-
});
|
|
1993
|
-
}
|
|
1994
|
-
/**
|
|
1995
|
-
* Update geom Types availibles to select for this layer
|
|
1996
|
-
*
|
|
1997
|
-
* @param layerName
|
|
1998
|
-
* @param geomDrawTypeSelected
|
|
1999
|
-
*/
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
_changeStateSelect(layerName) {
|
|
2003
|
-
var geomDrawTypeSelected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
2004
|
-
|
|
623
|
+
*/
|
|
624
|
+
_initMapElements(showControl, active) {
|
|
625
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
626
|
+
// VectorLayer to store features on editing and inserting
|
|
627
|
+
this._createEditLayer();
|
|
628
|
+
this._addInteractions();
|
|
629
|
+
this._addHandlers();
|
|
630
|
+
if (showControl) {
|
|
631
|
+
this._addMapControl();
|
|
632
|
+
}
|
|
633
|
+
// By default, init in edit mode
|
|
634
|
+
this.activateEditMode(active);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* @private
|
|
639
|
+
*/
|
|
640
|
+
_addInteractions() {
|
|
641
|
+
/**
|
|
642
|
+
* Select the wfs feature already downloaded
|
|
643
|
+
* @private
|
|
644
|
+
*/
|
|
645
|
+
const prepareWfsInteraction = () => {
|
|
646
|
+
this._collectionModify = new Collection();
|
|
647
|
+
// Interaction to select wfs layer elements
|
|
648
|
+
this.interactionWfsSelect = new Select({
|
|
649
|
+
hitTolerance: 10,
|
|
650
|
+
style: (feature) => this._styleFunction(feature),
|
|
651
|
+
toggleCondition: never,
|
|
652
|
+
filter: (feature, layer) => {
|
|
653
|
+
return (!this._isEditModeOn &&
|
|
654
|
+
layer &&
|
|
655
|
+
layer.get('type') === '_wfs_');
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
this._map.addInteraction(this.interactionWfsSelect);
|
|
659
|
+
this.interactionWfsSelect.on('select', ({ selected, deselected, mapBrowserEvent }) => {
|
|
660
|
+
const coordinate = mapBrowserEvent.coordinate;
|
|
661
|
+
if (selected.length) {
|
|
662
|
+
selected.forEach((feature) => {
|
|
663
|
+
if (!this._editedFeatures.has(String(feature.getId()))) {
|
|
664
|
+
// Remove the feature from the original layer
|
|
665
|
+
const layer = this.interactionWfsSelect.getLayer(feature);
|
|
666
|
+
layer.getSource().removeFeature(feature);
|
|
667
|
+
this._addFeatureToEdit(feature, coordinate);
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
if (deselected.length) {
|
|
672
|
+
if (!this._isEditModeOn) {
|
|
673
|
+
deselected.forEach((feature) => {
|
|
674
|
+
// Trigger deselect
|
|
675
|
+
// This is necessary for those times where two features overlap.
|
|
676
|
+
this._collectionModify.remove(feature);
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
};
|
|
682
|
+
/**
|
|
683
|
+
* Call the geoserver to get the clicked feature
|
|
684
|
+
* @private
|
|
685
|
+
*/
|
|
686
|
+
const prepareWmsInteraction = () => {
|
|
687
|
+
// Interaction to allow select features in the edit layer
|
|
688
|
+
this.interactionSelectModify = new Select({
|
|
689
|
+
style: (feature) => this._styleFunction(feature),
|
|
690
|
+
layers: [this._editLayer],
|
|
691
|
+
toggleCondition: never,
|
|
692
|
+
removeCondition: () => (this._isEditModeOn ? true : false) // Prevent deselect on clicking outside the feature
|
|
693
|
+
});
|
|
694
|
+
this._map.addInteraction(this.interactionSelectModify);
|
|
695
|
+
this._collectionModify = this.interactionSelectModify.getFeatures();
|
|
696
|
+
const getFeatures = (evt) => __awaiter(this, void 0, void 0, function* () {
|
|
697
|
+
for (const layerName in this._mapLayers) {
|
|
698
|
+
const layer = this._mapLayers[layerName];
|
|
699
|
+
// If layer is hidden or is not a wms, skip
|
|
700
|
+
if (!layer.getVisible() ||
|
|
701
|
+
!(layer.get('type') === '_wms_')) {
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const coordinate = evt.coordinate;
|
|
705
|
+
// Si la vista es lejana, disminumos el buffer
|
|
706
|
+
// Si es cercana, lo aumentamos, por ejemplo, para podeer clickear los vectores
|
|
707
|
+
// y mejorar la sensibilidad en IOS
|
|
708
|
+
const buffer = this._view.getZoom() > 10 ? 10 : 5;
|
|
709
|
+
const source = layer.getSource();
|
|
710
|
+
// Fallback to support a bad name
|
|
711
|
+
// https://openlayers.org/en/v5.3.0/apidoc/module-ol_source_ImageWMS-ImageWMS.html#getGetFeatureInfoUrl
|
|
712
|
+
const fallbackOl5 = 'getFeatureInfoUrl' in source
|
|
713
|
+
? 'getFeatureInfoUrl'
|
|
714
|
+
: 'getGetFeatureInfoUrl';
|
|
715
|
+
const url = source[fallbackOl5](coordinate, this._view.getResolution(), this._view.getProjection().getCode(), {
|
|
716
|
+
INFO_FORMAT: 'application/json',
|
|
717
|
+
BUFFER: buffer,
|
|
718
|
+
FEATURE_COUNT: 1,
|
|
719
|
+
EXCEPTIONS: 'application/json'
|
|
720
|
+
});
|
|
721
|
+
try {
|
|
722
|
+
const response = yield fetch(url, {
|
|
723
|
+
headers: this._options.headers
|
|
724
|
+
});
|
|
725
|
+
if (!response.ok) {
|
|
726
|
+
throw new Error(this._i18n.errors.getFeatures +
|
|
727
|
+
' ' +
|
|
728
|
+
response.status);
|
|
729
|
+
}
|
|
730
|
+
const data = yield response.json();
|
|
731
|
+
const features = this._formatGeoJSON.readFeatures(data);
|
|
732
|
+
if (!features.length) {
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
features.forEach((feature) => this._addFeatureToEdit(feature, coordinate, layerName));
|
|
736
|
+
}
|
|
737
|
+
catch (err) {
|
|
738
|
+
this._showError(err.message, err);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
this._keyClickWms = this._map.on(this._options.evtType, (evt) => __awaiter(this, void 0, void 0, function* () {
|
|
743
|
+
if (this._map.hasFeatureAtPixel(evt.pixel)) {
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
if (!this._isVisible) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
// Only get other features if editmode is disabled
|
|
750
|
+
if (!this._isEditModeOn) {
|
|
751
|
+
yield getFeatures(evt);
|
|
752
|
+
}
|
|
753
|
+
}));
|
|
754
|
+
};
|
|
755
|
+
if (this._options.layers.find((layer) => layer.mode === 'wfs')) {
|
|
756
|
+
prepareWfsInteraction();
|
|
757
|
+
}
|
|
758
|
+
if (this._options.layers.find((layer) => layer.mode === 'wms')) {
|
|
759
|
+
prepareWmsInteraction();
|
|
760
|
+
}
|
|
761
|
+
this.interactionModify = new Modify({
|
|
762
|
+
style: () => {
|
|
763
|
+
if (this._isEditModeOn) {
|
|
764
|
+
return new Style({
|
|
765
|
+
image: new Circle({
|
|
766
|
+
radius: 6,
|
|
767
|
+
fill: new Fill({
|
|
768
|
+
color: '#ff0000'
|
|
769
|
+
}),
|
|
770
|
+
stroke: new Stroke({
|
|
771
|
+
width: 2,
|
|
772
|
+
color: 'rgba(5, 5, 5, 0.9)'
|
|
773
|
+
})
|
|
774
|
+
})
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
},
|
|
781
|
+
features: this._collectionModify,
|
|
782
|
+
condition: (evt) => {
|
|
783
|
+
return primaryAction(evt) && this._isEditModeOn;
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
this._map.addInteraction(this.interactionModify);
|
|
787
|
+
this.interactionSnap = new Snap({
|
|
788
|
+
source: this._editLayer.getSource()
|
|
789
|
+
});
|
|
790
|
+
this._map.addInteraction(this.interactionSnap);
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Layer to store temporary the elements to be edited
|
|
794
|
+
* @private
|
|
795
|
+
*/
|
|
796
|
+
_createEditLayer() {
|
|
797
|
+
this._editLayer = new Vector({
|
|
798
|
+
source: new Vector$1(),
|
|
799
|
+
zIndex: 100
|
|
800
|
+
});
|
|
801
|
+
this._map.addLayer(this._editLayer);
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Add map handlers
|
|
805
|
+
* @private
|
|
806
|
+
*/
|
|
807
|
+
_addHandlers() {
|
|
808
|
+
/**
|
|
809
|
+
* @private
|
|
810
|
+
*/
|
|
811
|
+
const keyboardEvents = () => {
|
|
812
|
+
document.addEventListener('keydown', ({ key }) => {
|
|
813
|
+
const inputFocus = document.querySelector('input:focus');
|
|
814
|
+
if (inputFocus) {
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (key === 'Delete') {
|
|
818
|
+
const selectedFeatures = this._collectionModify;
|
|
819
|
+
if (selectedFeatures) {
|
|
820
|
+
selectedFeatures.forEach((feature) => {
|
|
821
|
+
this._deleteFeature(feature, true);
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
};
|
|
827
|
+
// When a feature is modified, add this to a list.
|
|
828
|
+
// This prevent events fired on select and deselect features that has no changes and should
|
|
829
|
+
// not be updated in the geoserver
|
|
830
|
+
this.interactionModify.on('modifyend', (evt) => {
|
|
831
|
+
const feature = evt.features.item(0);
|
|
832
|
+
this._addFeatureToEditedList(feature);
|
|
833
|
+
super.dispatchEvent(evt);
|
|
834
|
+
});
|
|
835
|
+
this.interactionModify.on('modifystart', (evt) => {
|
|
836
|
+
super.dispatchEvent(evt);
|
|
837
|
+
});
|
|
838
|
+
this._onDeselectFeatureEvent();
|
|
839
|
+
this._onRemoveFeatureEvent();
|
|
840
|
+
/**
|
|
841
|
+
* @private
|
|
842
|
+
*/
|
|
843
|
+
const handleZoomEnd = () => {
|
|
844
|
+
if (this._currentZoom > this._options.minZoom) {
|
|
845
|
+
// Show the layers
|
|
846
|
+
if (!this._isVisible) {
|
|
847
|
+
this._isVisible = true;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
// Hide the layer
|
|
852
|
+
if (this._isVisible) {
|
|
853
|
+
this._isVisible = false;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
this._map.on('moveend', () => {
|
|
858
|
+
this._currentZoom = this._view.getZoom();
|
|
859
|
+
if (this._currentZoom !== this._lastZoom) {
|
|
860
|
+
handleZoomEnd();
|
|
861
|
+
}
|
|
862
|
+
this._lastZoom = this._currentZoom;
|
|
863
|
+
});
|
|
864
|
+
keyboardEvents();
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Add the widget on the map to allow change the tools and select active layers
|
|
868
|
+
* @private
|
|
869
|
+
*/
|
|
870
|
+
_addMapControl() {
|
|
871
|
+
/**
|
|
872
|
+
* @private
|
|
873
|
+
* @returns
|
|
874
|
+
*/
|
|
875
|
+
const createLayersControl = () => {
|
|
876
|
+
/**
|
|
877
|
+
*
|
|
878
|
+
* @param layerParams
|
|
879
|
+
* @private
|
|
880
|
+
* @returns
|
|
881
|
+
*/
|
|
882
|
+
const createLayerElements = (layerParams) => {
|
|
883
|
+
const layerName = layerParams.name;
|
|
884
|
+
const layerLabel = `<span title="${this._geoServerData[layerName].geomType}">${layerParams.label || layerName}</span>`;
|
|
885
|
+
const visible = 'visible' in layerParams ? layerParams.visible : true;
|
|
886
|
+
return `
|
|
887
|
+
<div class="wfst--layer-control
|
|
888
|
+
${visible ? 'ol-wfst--visible-on' : ''}
|
|
889
|
+
${layerName === this._layerToInsertElements
|
|
890
|
+
? 'ol-wfst--selected-on'
|
|
891
|
+
: ''}
|
|
892
|
+
" data-layer="${layerName}">
|
|
893
|
+
<div class="ol-wfst--tools-control-visible">
|
|
894
|
+
<span class="ol-wfst--tools-control-visible-btn ol-wfst--visible-btn-on" title="${this._i18n.labels.toggleVisibility}">
|
|
895
|
+
<img src="${img$4}"/>
|
|
896
|
+
</span>
|
|
897
|
+
<span class="ol-wfst--tools-control-visible-btn ol-wfst--visible-btn-off" title="${this._i18n.labels.toggleVisibility}">
|
|
898
|
+
<img src="${img$5}"/>
|
|
899
|
+
</span>
|
|
900
|
+
</div>
|
|
901
|
+
<label for="wfst--${layerName}">
|
|
902
|
+
<input value="${layerName}" id="wfst--${layerName}" type="radio" class="ol-wfst--tools-control-input" name="wfst--select-layer" ${layerName === this._layerToInsertElements
|
|
903
|
+
? 'checked="checked"'
|
|
904
|
+
: ''}>
|
|
905
|
+
${layerLabel}
|
|
906
|
+
</label>
|
|
907
|
+
</div>`;
|
|
908
|
+
};
|
|
909
|
+
let htmlLayers = '';
|
|
910
|
+
Object.keys(this._mapLayers).map((key) => (htmlLayers += createLayerElements(this._options.layers.find((el) => el.name === key))));
|
|
911
|
+
const selectLayers = document.createElement('div');
|
|
912
|
+
selectLayers.className = 'wfst--tools-control--select-layers';
|
|
913
|
+
selectLayers.innerHTML = htmlLayers;
|
|
914
|
+
// Layer Selector
|
|
915
|
+
const radioInputs = selectLayers.querySelectorAll('input');
|
|
916
|
+
radioInputs.forEach((radioInput) => {
|
|
917
|
+
const parentDiv = radioInput.closest('.wfst--layer-control');
|
|
918
|
+
radioInput.onchange = () => {
|
|
919
|
+
// Deselect DOM previous layer
|
|
920
|
+
const selected = selectLayers.querySelector('.ol-wfst--selected-on');
|
|
921
|
+
if (selected)
|
|
922
|
+
selected.classList.remove('ol-wfst--selected-on');
|
|
923
|
+
// Select this layer
|
|
924
|
+
parentDiv.classList.add('ol-wfst--selected-on');
|
|
925
|
+
this._layerToInsertElements = radioInput.value;
|
|
926
|
+
this._changeStateSelect(this._layerToInsertElements);
|
|
927
|
+
};
|
|
928
|
+
});
|
|
929
|
+
// Visibility toggler
|
|
930
|
+
const visibilityBtn = selectLayers.querySelectorAll('.ol-wfst--tools-control-visible-btn');
|
|
931
|
+
visibilityBtn.forEach((btn) => {
|
|
932
|
+
const parentDiv = btn.closest('.wfst--layer-control');
|
|
933
|
+
const layerName = parentDiv.dataset['layer'];
|
|
934
|
+
btn.onclick = () => {
|
|
935
|
+
parentDiv.classList.toggle('ol-wfst--visible-on');
|
|
936
|
+
const layer = this._mapLayers[layerName];
|
|
937
|
+
if (parentDiv.classList.contains('ol-wfst--visible-on')) {
|
|
938
|
+
layer.setVisible(true);
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
layer.setVisible(false);
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
});
|
|
945
|
+
return selectLayers;
|
|
946
|
+
};
|
|
947
|
+
/**
|
|
948
|
+
* @private
|
|
949
|
+
* @returns
|
|
950
|
+
*/
|
|
951
|
+
const createHeadControl = () => {
|
|
952
|
+
/**
|
|
953
|
+
* @private
|
|
954
|
+
*/
|
|
955
|
+
const createUploadElements = () => {
|
|
956
|
+
const container = document.createElement('div');
|
|
957
|
+
// Upload button Tool
|
|
958
|
+
const uploadButton = document.createElement('label');
|
|
959
|
+
uploadButton.className =
|
|
960
|
+
'ol-wfst--tools-control-btn ol-wfst--tools-control-btn-upload';
|
|
961
|
+
uploadButton.htmlFor = 'ol-wfst--upload';
|
|
962
|
+
uploadButton.innerHTML = `<img src="${img$3}"/> `;
|
|
963
|
+
uploadButton.title = this._i18n.labels.uploadToLayer;
|
|
964
|
+
// Hidden Input form
|
|
965
|
+
const uploadInput = document.createElement('input');
|
|
966
|
+
uploadInput.id = 'ol-wfst--upload';
|
|
967
|
+
uploadInput.type = 'file';
|
|
968
|
+
uploadInput.accept = this._options.uploadFormats;
|
|
969
|
+
uploadInput.onchange = (evt) => this._processUploadFile(evt);
|
|
970
|
+
container.append(uploadInput);
|
|
971
|
+
container.append(uploadButton);
|
|
972
|
+
return container;
|
|
973
|
+
};
|
|
974
|
+
/**
|
|
975
|
+
* @private
|
|
976
|
+
* @returns
|
|
977
|
+
*/
|
|
978
|
+
const createDrawContainer = () => {
|
|
979
|
+
const drawContainer = document.createElement('div');
|
|
980
|
+
drawContainer.className = 'ol-wfst--tools-control-draw-cnt';
|
|
981
|
+
// Draw Tool
|
|
982
|
+
const drawButton = document.createElement('button');
|
|
983
|
+
drawButton.className =
|
|
984
|
+
'ol-wfst--tools-control-btn ol-wfst--tools-control-btn-draw';
|
|
985
|
+
drawButton.type = 'button';
|
|
986
|
+
drawButton.innerHTML = `<img src="${img}"/>`;
|
|
987
|
+
drawButton.title = this._i18n.labels.addElement;
|
|
988
|
+
drawButton.onclick = () => {
|
|
989
|
+
if (this._isDrawModeOn) {
|
|
990
|
+
this._resetStateButtons();
|
|
991
|
+
this.activateEditMode();
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
this.activateDrawMode(this._layerToInsertElements);
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
// Select geom type
|
|
998
|
+
const select = document.createElement('select');
|
|
999
|
+
select.title = this._i18n.labels.selectDrawType;
|
|
1000
|
+
select.className = 'wfst--tools-control--select-draw';
|
|
1001
|
+
select.onchange = () => {
|
|
1002
|
+
const selectedValue = select.value;
|
|
1003
|
+
this._changeStateSelect(this._layerToInsertElements, selectedValue);
|
|
1004
|
+
if (this._isDrawModeOn) {
|
|
1005
|
+
this.activateDrawMode(this._layerToInsertElements);
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
const types = [
|
|
1009
|
+
GeometryType.Point,
|
|
1010
|
+
GeometryType.MultiPoint,
|
|
1011
|
+
GeometryType.LineString,
|
|
1012
|
+
GeometryType.MultiLineString,
|
|
1013
|
+
GeometryType.Polygon,
|
|
1014
|
+
GeometryType.MultiPolygon,
|
|
1015
|
+
GeometryType.Circle
|
|
1016
|
+
];
|
|
1017
|
+
for (const type of types) {
|
|
1018
|
+
const option = document.createElement('option');
|
|
1019
|
+
option.value = type;
|
|
1020
|
+
option.text = type;
|
|
1021
|
+
option.selected =
|
|
1022
|
+
this._geoServerData[this._layerToInsertElements]
|
|
1023
|
+
.geomType === type || false;
|
|
1024
|
+
select.appendChild(option);
|
|
1025
|
+
}
|
|
1026
|
+
drawContainer.append(drawButton);
|
|
1027
|
+
drawContainer.append(select);
|
|
1028
|
+
this._selectDraw = select;
|
|
1029
|
+
return drawContainer;
|
|
1030
|
+
};
|
|
1031
|
+
const subControl = document.createElement('div');
|
|
1032
|
+
subControl.className = 'wfst--tools-control--head';
|
|
1033
|
+
// Upload section
|
|
1034
|
+
if (this._options.showUpload) {
|
|
1035
|
+
const uploadSection = createUploadElements();
|
|
1036
|
+
subControl.append(uploadSection);
|
|
1037
|
+
}
|
|
1038
|
+
const drawContainer = createDrawContainer();
|
|
1039
|
+
subControl.append(drawContainer);
|
|
1040
|
+
return subControl;
|
|
1041
|
+
};
|
|
1042
|
+
const headControl = createHeadControl();
|
|
1043
|
+
this._controlWidgetToolsDiv.append(headControl);
|
|
1044
|
+
const htmlLayers = createLayersControl();
|
|
1045
|
+
this._controlWidgetToolsDiv.append(htmlLayers);
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Show Loading
|
|
1049
|
+
* @private
|
|
1050
|
+
*/
|
|
1051
|
+
_showLoading() {
|
|
1052
|
+
if (!this._modalLoading) {
|
|
1053
|
+
this._modalLoading = document.createElement('div');
|
|
1054
|
+
this._modalLoading.className = 'ol-wfst--tools-control--loading';
|
|
1055
|
+
this._modalLoading.innerHTML = this._i18n.labels.loading;
|
|
1056
|
+
this._controlWidgetToolsDiv.append(this._modalLoading);
|
|
1057
|
+
}
|
|
1058
|
+
this._modalLoading.classList.add('ol-wfst--tools-control--loading-show');
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Hide loading
|
|
1062
|
+
* @private
|
|
1063
|
+
*/
|
|
1064
|
+
_hideLoading() {
|
|
1065
|
+
this._modalLoading.classList.remove('ol-wfst--tools-control--loading-show');
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Lock a feature in the geoserver before edit
|
|
1069
|
+
*
|
|
1070
|
+
* @param featureId
|
|
1071
|
+
* @param layerName
|
|
1072
|
+
* @param retry
|
|
1073
|
+
* @private
|
|
1074
|
+
*/
|
|
1075
|
+
_lockFeature(featureId, layerName, retry = 0) {
|
|
1076
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1077
|
+
const params = new URLSearchParams({
|
|
1078
|
+
service: 'wfs',
|
|
1079
|
+
version: this._options.geoServerAdvanced.lockFeatureVersion,
|
|
1080
|
+
request: 'LockFeature',
|
|
1081
|
+
expiry: String(5),
|
|
1082
|
+
LockId: 'GeoServer',
|
|
1083
|
+
typeName: layerName,
|
|
1084
|
+
releaseAction: 'SOME',
|
|
1085
|
+
exceptions: 'application/json',
|
|
1086
|
+
featureid: `${featureId}`
|
|
1087
|
+
});
|
|
1088
|
+
const url_fetch = this._options.geoServerUrl + '?' + params.toString();
|
|
1089
|
+
try {
|
|
1090
|
+
const response = yield fetch(url_fetch, {
|
|
1091
|
+
headers: this._options.headers
|
|
1092
|
+
});
|
|
1093
|
+
if (!response.ok) {
|
|
1094
|
+
throw new Error(this._i18n.errors.lockFeature);
|
|
1095
|
+
}
|
|
1096
|
+
const data = yield response.text();
|
|
1097
|
+
try {
|
|
1098
|
+
// First, check if is a JSON (with errors)
|
|
1099
|
+
const dataParsed = JSON.parse(data);
|
|
1100
|
+
if ('exceptions' in dataParsed) {
|
|
1101
|
+
const exceptions = dataParsed.exceptions;
|
|
1102
|
+
if (exceptions[0].code === 'CannotLockAllFeatures') {
|
|
1103
|
+
// Maybe the Feature is already blocked, ant thats trigger error, so, we try one locking more time again
|
|
1104
|
+
if (!retry) {
|
|
1105
|
+
this._lockFeature(featureId, layerName, 1);
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
this._showError(this._i18n.errors.lockFeature, exceptions);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
this._showError(exceptions[0].text, exceptions);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
catch (err) {
|
|
1117
|
+
/*
|
|
1118
|
+
|
|
1119
|
+
let dataDoc = (new window.DOMParser()).parseFromString(data, 'text/xml');
|
|
1120
|
+
|
|
1121
|
+
let lockId = dataDoc.getElementsByTagName('wfs:LockId');
|
|
1122
|
+
|
|
1123
|
+
let featuresLocked: HTMLCollectionOf<Element> = dataDoc.getElementsByTagName('ogc:FeatureId');
|
|
1124
|
+
|
|
1125
|
+
for (let featureLocked of featuresLocked as any) {
|
|
1126
|
+
|
|
1127
|
+
console.log(featureLocked.getAttribute('fid'));
|
|
1128
|
+
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
*/
|
|
1132
|
+
}
|
|
1133
|
+
return data;
|
|
1134
|
+
}
|
|
1135
|
+
catch (err) {
|
|
1136
|
+
this._showError(err.message, err);
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
2005
1140
|
/**
|
|
2006
|
-
*
|
|
2007
|
-
* the layer in the geoserver and disable what does not correspond.
|
|
1141
|
+
* Show modal with errors
|
|
2008
1142
|
*
|
|
2009
|
-
* @param
|
|
2010
|
-
* @param options
|
|
1143
|
+
* @param msg
|
|
2011
1144
|
* @private
|
|
2012
|
-
*/
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
});
|
|
2019
|
-
};
|
|
2020
|
-
|
|
2021
|
-
var drawType;
|
|
2022
|
-
|
|
2023
|
-
if (this._selectDraw) {
|
|
2024
|
-
var geomLayer = this._geoServerData[layerName].geomType;
|
|
2025
|
-
|
|
2026
|
-
if (geomDrawTypeSelected) {
|
|
2027
|
-
drawType = this._selectDraw.value;
|
|
2028
|
-
} else {
|
|
2029
|
-
if (geomLayer === GeometryType.GEOMETRY_COLLECTION) {
|
|
2030
|
-
drawType = GeometryType.LINE_STRING; // Default drawing type for GeometryCollection
|
|
2031
|
-
|
|
2032
|
-
setSelectState(drawType, 'all');
|
|
2033
|
-
} else if (geomLayer === GeometryType.LINEAR_RING) {
|
|
2034
|
-
drawType = GeometryType.LINE_STRING; // Default drawing type for GeometryCollection
|
|
2035
|
-
|
|
2036
|
-
setSelectState(drawType, [GeometryType.CIRCLE, GeometryType.LINEAR_RING, GeometryType.POLYGON]);
|
|
2037
|
-
this._selectDraw.value = drawType;
|
|
2038
|
-
} else {
|
|
2039
|
-
drawType = geomLayer;
|
|
2040
|
-
setSelectState(drawType, [geomLayer]);
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
|
-
return drawType;
|
|
2046
|
-
}
|
|
2047
|
-
/**
|
|
2048
|
-
* Activate/deactivate the draw mode
|
|
2049
|
-
*
|
|
2050
|
-
* @param layerName
|
|
2051
|
-
* @public
|
|
2052
|
-
*/
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
activateDrawMode(layerName) {
|
|
1145
|
+
*/
|
|
1146
|
+
_showError(msg, originalError = null) {
|
|
1147
|
+
Modal.alert('Error: ' + msg, Object.assign({}, this._options.modal)).show();
|
|
1148
|
+
if (originalError)
|
|
1149
|
+
console.error(originalError);
|
|
1150
|
+
}
|
|
2056
1151
|
/**
|
|
1152
|
+
* Make the WFS Transactions
|
|
2057
1153
|
*
|
|
1154
|
+
* @param action
|
|
1155
|
+
* @param features
|
|
2058
1156
|
* @param layerName
|
|
2059
1157
|
* @private
|
|
2060
|
-
*/
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
1158
|
+
*/
|
|
1159
|
+
_transactWFS(action, features, layerName) {
|
|
1160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1161
|
+
const transformCircleToPolygon = (feature, geom) => {
|
|
1162
|
+
const geomConverted = fromCircle(geom);
|
|
1163
|
+
feature.setGeometry(geomConverted);
|
|
1164
|
+
};
|
|
1165
|
+
const transformGeoemtryCollectionToGeometries = (feature, geom) => {
|
|
1166
|
+
let geomConverted = geom.getGeometries()[0];
|
|
1167
|
+
if (geomConverted instanceof Circle$1) {
|
|
1168
|
+
geomConverted = fromCircle(geomConverted);
|
|
1169
|
+
}
|
|
1170
|
+
feature.setGeometry(geomConverted);
|
|
1171
|
+
};
|
|
1172
|
+
features = Array.isArray(features) ? features : [features];
|
|
1173
|
+
const cloneFeature = (feature) => {
|
|
1174
|
+
this._removeFeatureFromEditList(feature);
|
|
1175
|
+
const featureProperties = feature.getProperties();
|
|
1176
|
+
delete featureProperties.boundedBy;
|
|
1177
|
+
delete featureProperties._layerName_;
|
|
1178
|
+
const clone = new Feature(featureProperties);
|
|
1179
|
+
clone.setId(feature.getId());
|
|
1180
|
+
return clone;
|
|
1181
|
+
};
|
|
1182
|
+
const refreshWmsLayer = (layer) => {
|
|
1183
|
+
const source = layer.getSource();
|
|
1184
|
+
// Refrescamos el wms
|
|
1185
|
+
source.refresh();
|
|
1186
|
+
// Force refresh the tiles
|
|
1187
|
+
const params = source.getParams();
|
|
1188
|
+
params.t = new Date().getMilliseconds();
|
|
1189
|
+
source.updateParams(params);
|
|
1190
|
+
};
|
|
1191
|
+
const refreshWfsLayer = (layer) => {
|
|
1192
|
+
const source = layer.getSource();
|
|
1193
|
+
// Refrescamos el wms
|
|
1194
|
+
source.refresh();
|
|
1195
|
+
};
|
|
1196
|
+
const clonedFeatures = [];
|
|
1197
|
+
for (const feature of features) {
|
|
1198
|
+
let clone = cloneFeature(feature);
|
|
1199
|
+
const cloneGeom = clone.getGeometry();
|
|
1200
|
+
// Ugly fix to support GeometryCollection on GML
|
|
1201
|
+
// See https://github.com/openlayers/openlayers/issues/4220
|
|
1202
|
+
if (cloneGeom instanceof GeometryCollection) {
|
|
1203
|
+
transformGeoemtryCollectionToGeometries(clone, cloneGeom);
|
|
1204
|
+
}
|
|
1205
|
+
else if (cloneGeom instanceof Circle$1) {
|
|
1206
|
+
// Geoserver has no Support to Circles
|
|
1207
|
+
transformCircleToPolygon(clone, cloneGeom);
|
|
1208
|
+
}
|
|
1209
|
+
if (action === 'insert') {
|
|
1210
|
+
// Filters
|
|
1211
|
+
if (this._options.beforeInsertFeature) {
|
|
1212
|
+
clone = this._options.beforeInsertFeature(clone);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
if (clone) {
|
|
1216
|
+
clonedFeatures.push(clone);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
if (!clonedFeatures.length) {
|
|
1220
|
+
return this._showError(this._i18n.errors.noValidGeometry);
|
|
1221
|
+
}
|
|
1222
|
+
switch (action) {
|
|
1223
|
+
case 'insert':
|
|
1224
|
+
this._insertFeatures = [
|
|
1225
|
+
...this._insertFeatures,
|
|
1226
|
+
...clonedFeatures
|
|
1227
|
+
];
|
|
1228
|
+
break;
|
|
1229
|
+
case 'update':
|
|
1230
|
+
this._updateFeatures = [
|
|
1231
|
+
...this._updateFeatures,
|
|
1232
|
+
...clonedFeatures
|
|
1233
|
+
];
|
|
1234
|
+
break;
|
|
1235
|
+
case 'delete':
|
|
1236
|
+
this._deleteFeatures = [
|
|
1237
|
+
...this._deleteFeatures,
|
|
1238
|
+
...clonedFeatures
|
|
1239
|
+
];
|
|
1240
|
+
break;
|
|
1241
|
+
}
|
|
1242
|
+
this._countRequests++;
|
|
1243
|
+
const numberRequest = this._countRequests;
|
|
1244
|
+
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
1245
|
+
try {
|
|
1246
|
+
// Prevent fire multiples times
|
|
1247
|
+
if (numberRequest !== this._countRequests) {
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
let srs = this._view.getProjection().getCode();
|
|
1251
|
+
// Force latitude/longitude order on transactions
|
|
1252
|
+
// EPSG:4326 is longitude/latitude (assumption) and is not managed correctly by GML3
|
|
1253
|
+
srs = srs === 'EPSG:4326' ? 'urn:x-ogc:def:crs:EPSG:4326' : srs;
|
|
1254
|
+
const options = {
|
|
1255
|
+
featureNS: this._geoServerData[layerName].namespace,
|
|
1256
|
+
featureType: layerName,
|
|
1257
|
+
srsName: srs,
|
|
1258
|
+
featurePrefix: null,
|
|
1259
|
+
nativeElements: null,
|
|
1260
|
+
version: this._options.geoServerAdvanced
|
|
1261
|
+
.wfsTransactionVersion
|
|
1262
|
+
};
|
|
1263
|
+
const transaction = this._formatWFS.writeTransaction(this._insertFeatures, this._updateFeatures, this._deleteFeatures, options);
|
|
1264
|
+
let payload = this._xs.serializeToString(transaction);
|
|
1265
|
+
const geomType = this._geoServerData[layerName].geomType;
|
|
1266
|
+
const geomField = this._geoServerData[layerName].geomField;
|
|
1267
|
+
// Ugly fix to support GeometryCollection on GML
|
|
1268
|
+
// See https://github.com/openlayers/openlayers/issues/4220
|
|
1269
|
+
if (geomType === GeometryType.GeometryCollection) {
|
|
1270
|
+
if (action === 'insert') {
|
|
1271
|
+
payload = payload.replace(/<geometry>/g, `<geometry><MultiGeometry xmlns="http://www.opengis.net/gml" srsName="${srs}"><geometryMember>`);
|
|
1272
|
+
payload = payload.replace(/<\/geometry>/g, `</geometryMember></MultiGeometry></geometry>`);
|
|
1273
|
+
}
|
|
1274
|
+
else if (action === 'update') {
|
|
1275
|
+
const gmemberIn = `<MultiGeometry xmlns="http://www.opengis.net/gml" srsName="${srs}"><geometryMember>`;
|
|
1276
|
+
const gmemberOut = `</geometryMember></MultiGeometry>`;
|
|
1277
|
+
payload = payload.replace(/(.*)(<Name>geometry<\/Name><Value>)(.*?)(<\/Value>)(.*)/g, `$1$2${gmemberIn}$3${gmemberOut}$4$5`);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
// Fixes geometry name, weird bug with GML:
|
|
1281
|
+
// The property for the geometry column is always named "geometry"
|
|
1282
|
+
if (action === 'insert') {
|
|
1283
|
+
payload = payload.replace(/<(\/?)\bgeometry\b>/g, `<$1${geomField}>`);
|
|
1284
|
+
}
|
|
1285
|
+
else {
|
|
1286
|
+
payload = payload.replace(/<Name>geometry<\/Name>/g, `<Name>${geomField}</Name>`);
|
|
1287
|
+
}
|
|
1288
|
+
// Add default LockId value
|
|
1289
|
+
if (this._hasLockFeature &&
|
|
1290
|
+
this._useLockFeature &&
|
|
1291
|
+
action !== 'insert') {
|
|
1292
|
+
payload = payload.replace(`</Transaction>`, `<LockId>GeoServer</LockId></Transaction>`);
|
|
1293
|
+
}
|
|
1294
|
+
const headers = Object.assign({ 'Content-Type': 'text/xml' }, this._options.headers);
|
|
1295
|
+
const response = yield fetch(this._options.geoServerUrl, {
|
|
1296
|
+
method: 'POST',
|
|
1297
|
+
body: payload,
|
|
1298
|
+
headers: headers
|
|
1299
|
+
});
|
|
1300
|
+
if (!response.ok) {
|
|
1301
|
+
throw new Error(this._i18n.errors.transaction + ' ' + response.status);
|
|
1302
|
+
}
|
|
1303
|
+
const parseResponse = this._formatWFS.readTransactionResponse(response);
|
|
1304
|
+
if (!Object.keys(parseResponse).length) {
|
|
1305
|
+
const responseStr = yield response.text();
|
|
1306
|
+
const findError = String(responseStr).match(/<ows:ExceptionText>([\s\S]*?)<\/ows:ExceptionText>/);
|
|
1307
|
+
if (findError) {
|
|
1308
|
+
this._showError(findError[1]);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
if (action !== 'delete') {
|
|
1312
|
+
for (const feature of features) {
|
|
1313
|
+
this._editLayer.getSource().removeFeature(feature);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
const { mode } = this._options.layers.find((layer) => layer.name === layerName);
|
|
1317
|
+
if (mode === 'wfs') {
|
|
1318
|
+
refreshWfsLayer(this._mapLayers[layerName]);
|
|
1319
|
+
}
|
|
1320
|
+
else if (mode === 'wms') {
|
|
1321
|
+
refreshWmsLayer(this._mapLayers[layerName]);
|
|
1322
|
+
}
|
|
1323
|
+
this._hideLoading();
|
|
1324
|
+
}
|
|
1325
|
+
catch (err) {
|
|
1326
|
+
this._showError(err.message, err);
|
|
1327
|
+
}
|
|
1328
|
+
this._insertFeatures = [];
|
|
1329
|
+
this._updateFeatures = [];
|
|
1330
|
+
this._deleteFeatures = [];
|
|
1331
|
+
this._countRequests = 0;
|
|
1332
|
+
}), 0);
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
*
|
|
1337
|
+
* @param feature
|
|
1338
|
+
* @private
|
|
1339
|
+
*/
|
|
1340
|
+
_addFeatureToEditedList(feature) {
|
|
1341
|
+
this._editedFeatures.add(String(feature.getId()));
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
*
|
|
1345
|
+
* @param feature
|
|
1346
|
+
* @private
|
|
1347
|
+
*/
|
|
1348
|
+
_removeFeatureFromEditList(feature) {
|
|
1349
|
+
this._editedFeatures.delete(String(feature.getId()));
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
*
|
|
1353
|
+
* @param feature
|
|
1354
|
+
* @private
|
|
1355
|
+
*/
|
|
1356
|
+
_isFeatureEdited(feature) {
|
|
1357
|
+
return this._editedFeatures.has(String(feature.getId()));
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
*
|
|
1361
|
+
* @param feature
|
|
1362
|
+
* @private
|
|
1363
|
+
*/
|
|
1364
|
+
_deselectEditFeature(feature) {
|
|
1365
|
+
this._removeOverlayHelper(feature);
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
*
|
|
1369
|
+
* @param feature
|
|
1370
|
+
* @param layerName
|
|
1371
|
+
* @private
|
|
1372
|
+
*/
|
|
1373
|
+
_restoreFeatureToLayer(feature, layerName) {
|
|
1374
|
+
layerName = layerName || feature.get('_layerName_');
|
|
1375
|
+
const layer = this._mapLayers[layerName];
|
|
1376
|
+
layer.getSource().addFeature(feature);
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* @private
|
|
1380
|
+
* @param feature
|
|
1381
|
+
*/
|
|
1382
|
+
_removeFeatureFromTmpLayer(feature) {
|
|
1383
|
+
// Remove element from the Layer
|
|
1384
|
+
this._editLayer.getSource().removeFeature(feature);
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Trigger on deselecting a feature from in the Edit layer
|
|
1388
|
+
*
|
|
1389
|
+
* @private
|
|
1390
|
+
*/
|
|
1391
|
+
_onDeselectFeatureEvent() {
|
|
1392
|
+
const checkIfFeatureIsChanged = (feature) => {
|
|
1393
|
+
const layerName = feature.get('_layerName_');
|
|
1394
|
+
const { mode } = this._options.layers.find((layer) => layer.name === layerName);
|
|
1395
|
+
if (mode === 'wfs') {
|
|
1396
|
+
this.interactionWfsSelect.getFeatures().remove(feature);
|
|
1397
|
+
}
|
|
1398
|
+
if (this._isFeatureEdited(feature)) {
|
|
1399
|
+
this._transactWFS('update', feature, layerName);
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
// Si es wfs y el elemento no tuvo cambios, lo devolvemos a la layer original
|
|
1403
|
+
if (mode === 'wfs') {
|
|
1404
|
+
this._restoreFeatureToLayer(feature, layerName);
|
|
1405
|
+
}
|
|
1406
|
+
this._removeFeatureFromTmpLayer(feature);
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
// This is fired when a feature is deselected and fires the transaction process
|
|
1410
|
+
this._keySelect = this._collectionModify.on('remove', (evt) => {
|
|
1411
|
+
const feature = evt.element;
|
|
1412
|
+
this._deselectEditFeature(feature);
|
|
1413
|
+
checkIfFeatureIsChanged(feature);
|
|
1414
|
+
this._editModeOff();
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Trigger on removing a feature from the Edit layer
|
|
1419
|
+
*
|
|
1420
|
+
* @private
|
|
1421
|
+
*/
|
|
1422
|
+
_onRemoveFeatureEvent() {
|
|
1423
|
+
// If a feature is removed from the edit layer
|
|
1424
|
+
this._keyRemove = this._editLayer
|
|
1425
|
+
.getSource()
|
|
1426
|
+
.on('removefeature', (evt) => {
|
|
1427
|
+
const feature = evt.feature;
|
|
1428
|
+
if (!feature.get('_delete_')) {
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
if (this._keySelect) {
|
|
1432
|
+
unByKey(this._keySelect);
|
|
1433
|
+
}
|
|
1434
|
+
const layerName = feature.get('_layerName_');
|
|
1435
|
+
this._transactWFS('delete', feature, layerName);
|
|
1436
|
+
this._deselectEditFeature(feature);
|
|
1437
|
+
this._editModeOff();
|
|
1438
|
+
if (this._keySelect) {
|
|
1439
|
+
setTimeout(() => {
|
|
1440
|
+
this._onDeselectFeatureEvent();
|
|
1441
|
+
}, 150);
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* Master style that handles two modes on the Edit Layer:
|
|
1447
|
+
* - one is the basic, showing only the vertices
|
|
1448
|
+
* - and the other when modify is active, showing bigger vertices
|
|
1449
|
+
*
|
|
1450
|
+
* @param feature
|
|
1451
|
+
* @private
|
|
1452
|
+
*/
|
|
1453
|
+
_styleFunction(feature) {
|
|
1454
|
+
const getVertexs = (feature) => {
|
|
1455
|
+
let geometry = feature.getGeometry();
|
|
1456
|
+
if (geometry instanceof GeometryCollection) {
|
|
1457
|
+
geometry = geometry.getGeometries()[0];
|
|
1458
|
+
}
|
|
1459
|
+
const coordinates = geometry.getCoordinates();
|
|
1460
|
+
let flatCoordinates = null;
|
|
1461
|
+
if (geometry instanceof Polygon ||
|
|
1462
|
+
geometry instanceof MultiLineString) {
|
|
1463
|
+
flatCoordinates = coordinates.flat(1);
|
|
1464
|
+
}
|
|
1465
|
+
else if (geometry instanceof MultiPolygon) {
|
|
1466
|
+
flatCoordinates = coordinates.flat(2);
|
|
1467
|
+
}
|
|
1468
|
+
else {
|
|
1469
|
+
flatCoordinates = coordinates;
|
|
1470
|
+
}
|
|
1471
|
+
if (!flatCoordinates || !flatCoordinates.length) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
return new MultiPoint(flatCoordinates);
|
|
1475
|
+
};
|
|
1476
|
+
let geometry = feature.getGeometry();
|
|
1477
|
+
let type = geometry.getType();
|
|
1478
|
+
if (geometry instanceof GeometryCollection) {
|
|
1479
|
+
geometry = geometry.getGeometries()[0];
|
|
1480
|
+
type = geometry.getType();
|
|
1481
|
+
}
|
|
1482
|
+
switch (type) {
|
|
1483
|
+
case GeometryType.Point:
|
|
1484
|
+
case GeometryType.MultiPoint:
|
|
1485
|
+
if (this._isEditModeOn) {
|
|
1486
|
+
return [
|
|
1487
|
+
new Style({
|
|
1488
|
+
image: new Circle({
|
|
1489
|
+
radius: 6,
|
|
1490
|
+
fill: new Fill({
|
|
1491
|
+
color: '#000000'
|
|
1492
|
+
})
|
|
1493
|
+
})
|
|
1494
|
+
}),
|
|
1495
|
+
new Style({
|
|
1496
|
+
image: new Circle({
|
|
1497
|
+
radius: 4,
|
|
1498
|
+
fill: new Fill({
|
|
1499
|
+
color: '#ff0000'
|
|
1500
|
+
})
|
|
1501
|
+
})
|
|
1502
|
+
})
|
|
1503
|
+
];
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
return [
|
|
1507
|
+
new Style({
|
|
1508
|
+
image: new Circle({
|
|
1509
|
+
radius: 5,
|
|
1510
|
+
fill: new Fill({
|
|
1511
|
+
color: '#ff0000'
|
|
1512
|
+
})
|
|
1513
|
+
})
|
|
1514
|
+
}),
|
|
1515
|
+
new Style({
|
|
1516
|
+
image: new Circle({
|
|
1517
|
+
radius: 2,
|
|
1518
|
+
fill: new Fill({
|
|
1519
|
+
color: '#000000'
|
|
1520
|
+
})
|
|
1521
|
+
})
|
|
1522
|
+
})
|
|
1523
|
+
];
|
|
1524
|
+
}
|
|
1525
|
+
default:
|
|
1526
|
+
// If editing mode is active, show bigger vertex
|
|
1527
|
+
if (this._isEditModeOn || this._isDrawModeOn) {
|
|
1528
|
+
return [
|
|
1529
|
+
new Style({
|
|
1530
|
+
stroke: new Stroke({
|
|
1531
|
+
color: 'rgba( 255, 0, 0, 1)',
|
|
1532
|
+
width: 4
|
|
1533
|
+
}),
|
|
1534
|
+
fill: new Fill({
|
|
1535
|
+
color: 'rgba(255, 0, 0, 0.7)'
|
|
1536
|
+
})
|
|
1537
|
+
}),
|
|
1538
|
+
new Style({
|
|
1539
|
+
image: new Circle({
|
|
1540
|
+
radius: 4,
|
|
1541
|
+
fill: new Fill({
|
|
1542
|
+
color: '#ff0000'
|
|
1543
|
+
}),
|
|
1544
|
+
stroke: new Stroke({
|
|
1545
|
+
width: 2,
|
|
1546
|
+
color: 'rgba(5, 5, 5, 0.9)'
|
|
1547
|
+
})
|
|
1548
|
+
}),
|
|
1549
|
+
geometry: (feature) => getVertexs(feature)
|
|
1550
|
+
}),
|
|
1551
|
+
new Style({
|
|
1552
|
+
stroke: new Stroke({
|
|
1553
|
+
color: 'rgba(255, 255, 255, 0.7)',
|
|
1554
|
+
width: 2
|
|
1555
|
+
})
|
|
1556
|
+
})
|
|
1557
|
+
];
|
|
1558
|
+
}
|
|
1559
|
+
else {
|
|
1560
|
+
return [
|
|
1561
|
+
new Style({
|
|
1562
|
+
image: new Circle({
|
|
1563
|
+
radius: 2,
|
|
1564
|
+
fill: new Fill({
|
|
1565
|
+
color: '#000000'
|
|
1566
|
+
})
|
|
1567
|
+
}),
|
|
1568
|
+
geometry: (feature) => getVertexs(feature)
|
|
1569
|
+
}),
|
|
1570
|
+
new Style({
|
|
1571
|
+
stroke: new Stroke({
|
|
1572
|
+
color: '#ff0000',
|
|
1573
|
+
width: 4
|
|
1574
|
+
}),
|
|
1575
|
+
fill: new Fill({
|
|
1576
|
+
color: 'rgba(255, 0, 0, 0.7)'
|
|
1577
|
+
})
|
|
1578
|
+
})
|
|
1579
|
+
];
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
/**
|
|
1584
|
+
*
|
|
1585
|
+
* @param feature
|
|
1586
|
+
* @private
|
|
1587
|
+
*/
|
|
1588
|
+
_editModeOn(feature) {
|
|
1589
|
+
this._editFeatureOriginal = feature.clone();
|
|
1590
|
+
this._isEditModeOn = true;
|
|
1591
|
+
// To refresh the style
|
|
1592
|
+
this._editLayer.getSource().changed();
|
|
1593
|
+
this._removeOverlayHelper(feature);
|
|
1594
|
+
const controlDiv = document.createElement('div');
|
|
1595
|
+
controlDiv.className = 'ol-wfst--changes-control';
|
|
1596
|
+
const elements = document.createElement('div');
|
|
1597
|
+
elements.className = 'ol-wfst--changes-control-el';
|
|
1598
|
+
const elementId = document.createElement('div');
|
|
1599
|
+
elementId.className = 'ol-wfst--changes-control-id';
|
|
1600
|
+
elementId.innerHTML = `<b>${this._i18n.labels.editMode}</b> - <i>${String(feature.getId())}</i>`;
|
|
1601
|
+
const acceptButton = document.createElement('button');
|
|
1602
|
+
acceptButton.type = 'button';
|
|
1603
|
+
acceptButton.textContent = this._i18n.labels.apply;
|
|
1604
|
+
acceptButton.className = 'btn btn-sm btn-primary';
|
|
1605
|
+
acceptButton.onclick = () => {
|
|
1606
|
+
this._showLoading();
|
|
1607
|
+
this._collectionModify.remove(feature);
|
|
1608
|
+
};
|
|
1609
|
+
const cancelButton = document.createElement('button');
|
|
1610
|
+
cancelButton.type = 'button';
|
|
1611
|
+
cancelButton.textContent = this._i18n.labels.cancel;
|
|
1612
|
+
cancelButton.className = 'btn btn-sm btn-secondary';
|
|
1613
|
+
cancelButton.onclick = () => {
|
|
1614
|
+
feature.setGeometry(this._editFeatureOriginal.getGeometry());
|
|
1615
|
+
this._removeFeatureFromEditList(feature);
|
|
1616
|
+
this._collectionModify.remove(feature);
|
|
1617
|
+
};
|
|
1618
|
+
const deleteButton = document.createElement('button');
|
|
1619
|
+
deleteButton.type = 'button';
|
|
1620
|
+
deleteButton.textContent = this._i18n.labels.delete;
|
|
1621
|
+
deleteButton.className = 'btn btn-sm btn-danger-outline';
|
|
1622
|
+
deleteButton.onclick = () => {
|
|
1623
|
+
this._deleteFeature(feature, true);
|
|
1624
|
+
};
|
|
1625
|
+
elements.append(elementId);
|
|
1626
|
+
elements.append(cancelButton);
|
|
1627
|
+
elements.append(acceptButton);
|
|
1628
|
+
elements.append(deleteButton);
|
|
1629
|
+
controlDiv.append(elements);
|
|
1630
|
+
this._controlApplyDiscardChanges = new Control({
|
|
1631
|
+
element: controlDiv
|
|
1632
|
+
});
|
|
1633
|
+
this._map.addControl(this._controlApplyDiscardChanges);
|
|
1634
|
+
}
|
|
1635
|
+
/**
|
|
1636
|
+
* @private
|
|
1637
|
+
*/
|
|
1638
|
+
_editModeOff() {
|
|
1639
|
+
this._isEditModeOn = false;
|
|
1640
|
+
this._map.removeControl(this._controlApplyDiscardChanges);
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Remove a feature from the edit Layer and from the Geoserver
|
|
1644
|
+
*
|
|
1645
|
+
* @param feature
|
|
1646
|
+
* @private
|
|
1647
|
+
*/
|
|
1648
|
+
_deleteFeature(feature, confirm) {
|
|
1649
|
+
const deleteEl = () => {
|
|
1650
|
+
const features = Array.isArray(feature) ? feature : [feature];
|
|
1651
|
+
features.forEach((feature) => {
|
|
1652
|
+
feature.set('_delete_', true, true);
|
|
1653
|
+
this._editLayer.getSource().removeFeature(feature);
|
|
1654
|
+
});
|
|
1655
|
+
this._collectionModify.clear();
|
|
1656
|
+
const layerName = feature.get('_layerName_');
|
|
1657
|
+
const { mode } = this._options.layers.find((layer) => layer.name === layerName);
|
|
1658
|
+
if (mode === 'wfs') {
|
|
1659
|
+
this.interactionWfsSelect.getFeatures().remove(feature);
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
if (confirm) {
|
|
1663
|
+
const confirmModal = Modal.confirm(this._i18n.labels.confirmDelete, Object.assign({}, this._options.modal));
|
|
1664
|
+
confirmModal.show().once('dismiss', function (modal, ev, button) {
|
|
1665
|
+
if (button && button.value) {
|
|
1666
|
+
deleteEl();
|
|
1667
|
+
}
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
deleteEl();
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Add a feature to the Edit Layer to allow editing, and creates an Overlay Helper to show options
|
|
1676
|
+
*
|
|
1677
|
+
* @param feature
|
|
1678
|
+
* @param coordinate
|
|
1679
|
+
* @param layerName
|
|
1680
|
+
* @private
|
|
1681
|
+
*/
|
|
1682
|
+
_addFeatureToEdit(feature, coordinate = null, layerName = null) {
|
|
1683
|
+
const prepareOverlay = () => {
|
|
1684
|
+
const svgFields = `<img src="${img$1}"/>`;
|
|
1685
|
+
const editFieldsEl = document.createElement('div');
|
|
1686
|
+
editFieldsEl.className = 'ol-wfst--edit-button-cnt';
|
|
1687
|
+
editFieldsEl.innerHTML = `<button class="ol-wfst--edit-button" type="button" title="${this._i18n.labels.editFields}">${svgFields}</button>`;
|
|
1688
|
+
editFieldsEl.onclick = () => {
|
|
1689
|
+
this._initEditFieldsModal(feature);
|
|
1690
|
+
};
|
|
1691
|
+
const buttons = document.createElement('div');
|
|
1692
|
+
buttons.append(editFieldsEl);
|
|
1693
|
+
const svgGeom = `<img src="${img$2}"/>`;
|
|
1694
|
+
const editGeomEl = document.createElement('div');
|
|
1695
|
+
editGeomEl.className = 'ol-wfst--edit-button-cnt';
|
|
1696
|
+
editGeomEl.innerHTML = `<button class="ol-wfst--edit-button" type="button" title="${this._i18n.labels.editGeom}">${svgGeom}</button>`;
|
|
1697
|
+
editGeomEl.onclick = () => {
|
|
1698
|
+
this._editModeOn(feature);
|
|
1699
|
+
};
|
|
1700
|
+
buttons.append(editGeomEl);
|
|
1701
|
+
const position = coordinate || getCenter(feature.getGeometry().getExtent());
|
|
1702
|
+
const buttonsOverlay = new Overlay({
|
|
1703
|
+
id: feature.getId(),
|
|
1704
|
+
position: position,
|
|
1705
|
+
positioning: 'center-center',
|
|
1706
|
+
element: buttons,
|
|
1707
|
+
offset: [0, -40],
|
|
1708
|
+
stopEvent: true
|
|
1709
|
+
});
|
|
1710
|
+
this._map.addOverlay(buttonsOverlay);
|
|
1711
|
+
};
|
|
1712
|
+
if (layerName) {
|
|
1713
|
+
// Guardamos el nombre de la capa de donde sale la feature
|
|
1714
|
+
feature.set('_layerName_', layerName);
|
|
1715
|
+
}
|
|
1716
|
+
const props = feature ? feature.getProperties() : '';
|
|
1717
|
+
if (props) {
|
|
1718
|
+
if (feature.getGeometry()) {
|
|
1719
|
+
this._editLayer.getSource().addFeature(feature);
|
|
1720
|
+
this._collectionModify.push(feature);
|
|
1721
|
+
prepareOverlay();
|
|
1722
|
+
if (this._useLockFeature && this._hasLockFeature) {
|
|
1723
|
+
this._lockFeature(feature.getId(), feature.get('_layerName_'));
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
/**
|
|
1729
|
+
* Removes in the DOM the class of the tools
|
|
1730
|
+
* @private
|
|
1731
|
+
*/
|
|
1732
|
+
_resetStateButtons() {
|
|
1733
|
+
const activeBtn = document.querySelector('.ol-wfst--tools-control-btn.wfst--active');
|
|
1734
|
+
if (activeBtn) {
|
|
1735
|
+
activeBtn.classList.remove('wfst--active');
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Confirm modal before transact to the GeoServer the features in the file
|
|
1740
|
+
*
|
|
1741
|
+
* @param content
|
|
1742
|
+
* @param featureToInsert
|
|
1743
|
+
* @private
|
|
1744
|
+
*/
|
|
1745
|
+
_initUploadFileModal(content, featuresToInsert) {
|
|
1746
|
+
const footer = `
|
|
1747
|
+
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">
|
|
1748
|
+
${this._i18n.labels.cancel}
|
|
1749
|
+
</button>
|
|
1750
|
+
<button type="button" class="btn btn-sm btn-primary" data-action="save" data-dismiss="modal">
|
|
1751
|
+
${this._i18n.labels.upload}
|
|
1752
|
+
</button>
|
|
1753
|
+
`;
|
|
1754
|
+
const modal = new Modal(Object.assign(Object.assign({}, this._options.modal), { header: true, headerClose: false, title: this._i18n.labels.uploadFeatures +
|
|
1755
|
+
' ' +
|
|
1756
|
+
this._layerToInsertElements, content: content, backdrop: 'static', footer: footer })).show();
|
|
1757
|
+
modal.on('dismiss', (modal, event) => {
|
|
1758
|
+
// On saving changes
|
|
1759
|
+
if (event.target.dataset.action === 'save') {
|
|
1760
|
+
this._transactWFS('insert', featuresToInsert, this._layerToInsertElements);
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
// On cancel button
|
|
1764
|
+
this._editLayer.getSource().clear();
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Parse and check geometry of uploaded files
|
|
1770
|
+
*
|
|
1771
|
+
* @param evt
|
|
1772
|
+
* @private
|
|
1773
|
+
*/
|
|
1774
|
+
_processUploadFile(evt) {
|
|
1775
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1776
|
+
/**
|
|
1777
|
+
* Read data file
|
|
1778
|
+
* @param file
|
|
1779
|
+
* @private
|
|
1780
|
+
*/
|
|
1781
|
+
const fileReader = (file) => {
|
|
1782
|
+
return new Promise((resolve, reject) => {
|
|
1783
|
+
const reader = new FileReader();
|
|
1784
|
+
reader.addEventListener('load', (e) => __awaiter(this, void 0, void 0, function* () {
|
|
1785
|
+
const fileData = e.target.result;
|
|
1786
|
+
resolve(fileData);
|
|
1787
|
+
}));
|
|
1788
|
+
reader.addEventListener('error', (err) => {
|
|
1789
|
+
console.error('Error' + err);
|
|
1790
|
+
reject();
|
|
1791
|
+
});
|
|
1792
|
+
reader.readAsText(file);
|
|
1793
|
+
});
|
|
1794
|
+
};
|
|
1795
|
+
/**
|
|
1796
|
+
* Attemp to change the geometry feature to the layer
|
|
1797
|
+
* @param feature
|
|
1798
|
+
* @private
|
|
1799
|
+
*/
|
|
1800
|
+
const fixGeometry = (feature) => {
|
|
1801
|
+
// Geometry of the layer
|
|
1802
|
+
const geomTypeLayer = this._geoServerData[this._layerToInsertElements].geomType;
|
|
1803
|
+
const geomTypeFeature = feature.getGeometry().getType();
|
|
1804
|
+
let geom;
|
|
1805
|
+
switch (geomTypeFeature) {
|
|
1806
|
+
case 'Point': {
|
|
1807
|
+
if (geomTypeLayer === 'MultiPoint') {
|
|
1808
|
+
const coords = feature.getGeometry().getCoordinates();
|
|
1809
|
+
geom = new MultiPoint([coords]);
|
|
1810
|
+
}
|
|
1811
|
+
break;
|
|
1812
|
+
}
|
|
1813
|
+
case 'LineString':
|
|
1814
|
+
if (geomTypeLayer === 'MultiLineString') {
|
|
1815
|
+
const coords = feature.getGeometry().getCoordinates();
|
|
1816
|
+
geom = new MultiLineString([coords]);
|
|
1817
|
+
}
|
|
1818
|
+
break;
|
|
1819
|
+
case 'Polygon':
|
|
1820
|
+
if (geomTypeLayer === 'MultiPolygon') {
|
|
1821
|
+
const coords = feature.getGeometry().getCoordinates();
|
|
1822
|
+
geom = new MultiPolygon([coords]);
|
|
1823
|
+
}
|
|
1824
|
+
break;
|
|
1825
|
+
default:
|
|
1826
|
+
geom = null;
|
|
1827
|
+
}
|
|
1828
|
+
if (!geom) {
|
|
1829
|
+
return null;
|
|
1830
|
+
}
|
|
1831
|
+
feature.setGeometry(geom);
|
|
1832
|
+
return feature;
|
|
1833
|
+
};
|
|
1834
|
+
/**
|
|
1835
|
+
* Check if the feature has the same geometry as the target layer
|
|
1836
|
+
* @param feature
|
|
1837
|
+
* @private
|
|
1838
|
+
*/
|
|
1839
|
+
const checkGeometry = (feature) => {
|
|
1840
|
+
// Geometry of the layer
|
|
1841
|
+
const geomTypeLayer = this._geoServerData[this._layerToInsertElements].geomType;
|
|
1842
|
+
const geomTypeFeature = feature.getGeometry().getType();
|
|
1843
|
+
// This geom accepts every type of geometry
|
|
1844
|
+
if (geomTypeLayer === GeometryType.GeometryCollection) {
|
|
1845
|
+
return true;
|
|
1846
|
+
}
|
|
1847
|
+
return geomTypeFeature === geomTypeLayer;
|
|
1848
|
+
};
|
|
1849
|
+
const file = evt.target.files[0];
|
|
1850
|
+
let features;
|
|
1851
|
+
if (!file) {
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
const extension = file.name.split('.').pop().toLowerCase();
|
|
1855
|
+
try {
|
|
1856
|
+
// If the user uses a custom fucntion...
|
|
1857
|
+
if (this._options.processUpload) {
|
|
1858
|
+
features = this._options.processUpload(file);
|
|
1859
|
+
}
|
|
1860
|
+
// If the user functions return features, we dont process anything more
|
|
1861
|
+
if (!features) {
|
|
1862
|
+
const string = yield fileReader(file);
|
|
1863
|
+
if (extension === 'geojson' || extension === 'json') {
|
|
1864
|
+
features = this._formatGeoJSON.readFeatures(string, {
|
|
1865
|
+
featureProjection: this._view.getProjection().getCode()
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
else if (extension === 'kml') {
|
|
1869
|
+
features = this._formatKml.readFeatures(string, {
|
|
1870
|
+
featureProjection: this._view.getProjection().getCode()
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
else {
|
|
1874
|
+
this._showError(this._i18n.errors.badFormat);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
catch (err) {
|
|
1879
|
+
this._showError(this._i18n.errors.badFile, err);
|
|
1880
|
+
}
|
|
1881
|
+
let invalidFeaturesCount = 0;
|
|
1882
|
+
let validFeaturesCount = 0;
|
|
1883
|
+
const featuresToInsert = [];
|
|
1884
|
+
for (let feature of features) {
|
|
1885
|
+
// If the geometry doesn't correspond to the layer, try to fixit.
|
|
1886
|
+
// If we can't, don't use it
|
|
1887
|
+
if (!checkGeometry(feature)) {
|
|
1888
|
+
feature = fixGeometry(feature);
|
|
1889
|
+
}
|
|
1890
|
+
if (feature) {
|
|
1891
|
+
featuresToInsert.push(feature);
|
|
1892
|
+
validFeaturesCount++;
|
|
1893
|
+
}
|
|
1894
|
+
else {
|
|
1895
|
+
invalidFeaturesCount++;
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
if (!validFeaturesCount) {
|
|
1900
|
+
this._showError(this._i18n.errors.noValidGeometry);
|
|
1901
|
+
}
|
|
1902
|
+
else {
|
|
1903
|
+
this._resetStateButtons();
|
|
1904
|
+
this.activateEditMode();
|
|
1905
|
+
const content = `
|
|
1906
|
+
${this._i18n.labels.validFeatures}: ${validFeaturesCount}<br>
|
|
1907
|
+
${invalidFeaturesCount
|
|
1908
|
+
? `${this._i18n.labels.invalidFeatures}: ${invalidFeaturesCount}`
|
|
1909
|
+
: ''}
|
|
1910
|
+
`;
|
|
1911
|
+
this._editLayer.getSource().addFeatures(featuresToInsert);
|
|
1912
|
+
this._initUploadFileModal(content, featuresToInsert);
|
|
1913
|
+
this._view.fit(this._editLayer.getSource().getExtent(), {
|
|
1914
|
+
size: this._map.getSize(),
|
|
1915
|
+
maxZoom: 21,
|
|
1916
|
+
padding: [100, 100, 100, 100]
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
// Reset the input to allow another onChange trigger
|
|
1920
|
+
evt.target.value = null;
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
/**
|
|
1924
|
+
* Update geom Types availibles to select for this layer
|
|
1925
|
+
*
|
|
1926
|
+
* @param layerName
|
|
1927
|
+
* @param geomDrawTypeSelected
|
|
1928
|
+
* @private
|
|
1929
|
+
*/
|
|
1930
|
+
_changeStateSelect(layerName, geomDrawTypeSelected = null) {
|
|
1931
|
+
/**
|
|
1932
|
+
* Set the geometry type in the select according to the geometry of
|
|
1933
|
+
* the layer in the geoserver and disable what does not correspond.
|
|
1934
|
+
*
|
|
1935
|
+
* @param value
|
|
1936
|
+
* @param options
|
|
1937
|
+
* @private
|
|
1938
|
+
*/
|
|
1939
|
+
const setSelectState = (value, options) => {
|
|
1940
|
+
Array.from(this._selectDraw.options).forEach((option) => {
|
|
1941
|
+
option.selected = option.value === value ? true : false;
|
|
1942
|
+
option.disabled =
|
|
1943
|
+
options === 'all'
|
|
1944
|
+
? false
|
|
1945
|
+
: options.includes(option.value)
|
|
1946
|
+
? false
|
|
1947
|
+
: true;
|
|
1948
|
+
option.title = option.disabled
|
|
1949
|
+
? this._i18n.labels.geomTypeNotSupported
|
|
1950
|
+
: '';
|
|
1951
|
+
});
|
|
1952
|
+
};
|
|
1953
|
+
let drawType;
|
|
1954
|
+
if (this._selectDraw) {
|
|
1955
|
+
const geomLayer = this._geoServerData[layerName].geomType;
|
|
1956
|
+
if (geomDrawTypeSelected) {
|
|
1957
|
+
drawType = this._selectDraw.value;
|
|
1958
|
+
}
|
|
1959
|
+
else {
|
|
1960
|
+
if (geomLayer === GeometryType.GeometryCollection) {
|
|
1961
|
+
drawType = GeometryType.LineString; // Default drawing type for GeometryCollection
|
|
1962
|
+
setSelectState(drawType, 'all');
|
|
1963
|
+
}
|
|
1964
|
+
else if (geomLayer === GeometryType.LinearRing) {
|
|
1965
|
+
drawType = GeometryType.LineString; // Default drawing type for GeometryCollection
|
|
1966
|
+
setSelectState(drawType, [
|
|
1967
|
+
GeometryType.Circle,
|
|
1968
|
+
GeometryType.LinearRing,
|
|
1969
|
+
GeometryType.Polygon
|
|
1970
|
+
]);
|
|
1971
|
+
this._selectDraw.value = drawType;
|
|
1972
|
+
}
|
|
1973
|
+
else {
|
|
1974
|
+
drawType = geomLayer;
|
|
1975
|
+
setSelectState(drawType, [geomLayer]);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return drawType;
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* Activate/deactivate the draw mode
|
|
1983
|
+
*
|
|
1984
|
+
* @param layerName
|
|
1985
|
+
* @public
|
|
1986
|
+
*/
|
|
1987
|
+
activateDrawMode(layerName) {
|
|
1988
|
+
/**
|
|
1989
|
+
*
|
|
1990
|
+
* @param layerName
|
|
1991
|
+
* @private
|
|
1992
|
+
*/
|
|
1993
|
+
const addDrawInteraction = (layerName) => {
|
|
1994
|
+
this.activateEditMode(false);
|
|
1995
|
+
// If already exists, remove
|
|
1996
|
+
if (this.interactionDraw) {
|
|
1997
|
+
this._map.removeInteraction(this.interactionDraw);
|
|
1998
|
+
}
|
|
1999
|
+
const geomDrawType = this._selectDraw.value;
|
|
2000
|
+
this.interactionDraw = new Draw({
|
|
2001
|
+
source: this._editLayer.getSource(),
|
|
2002
|
+
type: geomDrawType,
|
|
2003
|
+
style: (feature) => this._styleFunction(feature)
|
|
2004
|
+
});
|
|
2005
|
+
this._map.addInteraction(this.interactionDraw);
|
|
2006
|
+
this.interactionDraw.on('drawstart', (evt) => {
|
|
2007
|
+
super.dispatchEvent(evt);
|
|
2008
|
+
});
|
|
2009
|
+
this.interactionDraw.on('drawend', (evt) => {
|
|
2010
|
+
const feature = evt.feature;
|
|
2011
|
+
this._transactWFS('insert', feature, layerName);
|
|
2012
|
+
super.dispatchEvent(evt);
|
|
2013
|
+
});
|
|
2014
|
+
};
|
|
2015
|
+
if (!this.interactionDraw && !layerName) {
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
if (layerName) {
|
|
2019
|
+
// If layer is set to invisible, show warning
|
|
2020
|
+
if (!this._mapLayers[layerName].getVisible()) {
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
const btn = document.querySelector('.ol-wfst--tools-control-btn-draw');
|
|
2024
|
+
if (btn) {
|
|
2025
|
+
btn.classList.add('wfst--active');
|
|
2026
|
+
}
|
|
2027
|
+
this._viewport.classList.add('draw-mode');
|
|
2028
|
+
addDrawInteraction(String(layerName));
|
|
2029
|
+
}
|
|
2030
|
+
else {
|
|
2031
|
+
this._map.removeInteraction(this.interactionDraw);
|
|
2032
|
+
this._viewport.classList.remove('draw-mode');
|
|
2033
|
+
}
|
|
2034
|
+
this._isDrawModeOn = layerName ? true : false;
|
|
2035
|
+
}
|
|
2036
|
+
/**
|
|
2037
|
+
* Activate/desactivate the edit mode
|
|
2038
|
+
*
|
|
2039
|
+
* @param bool
|
|
2040
|
+
* @public
|
|
2041
|
+
*/
|
|
2042
|
+
activateEditMode(bool = true) {
|
|
2043
|
+
if (bool) {
|
|
2044
|
+
const btn = document.querySelector('.ol-wfst--tools-control-btn-edit');
|
|
2045
|
+
if (btn) {
|
|
2046
|
+
btn.classList.add('wfst--active');
|
|
2047
|
+
}
|
|
2048
|
+
this.activateDrawMode(false);
|
|
2049
|
+
}
|
|
2050
|
+
else {
|
|
2051
|
+
// Deselct features
|
|
2052
|
+
this._collectionModify.clear();
|
|
2053
|
+
}
|
|
2054
|
+
if (this.interactionSelectModify) {
|
|
2055
|
+
this.interactionSelectModify.setActive(bool);
|
|
2056
|
+
}
|
|
2057
|
+
this.interactionModify.setActive(bool);
|
|
2058
|
+
if (this.interactionWfsSelect)
|
|
2059
|
+
this.interactionWfsSelect.setActive(bool);
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Add features directly to the geoserver, in a custom layer
|
|
2063
|
+
* without checking geometry or showing modal to confirm.
|
|
2064
|
+
*
|
|
2065
|
+
* @param layerName
|
|
2066
|
+
* @param features
|
|
2067
|
+
* @public
|
|
2068
|
+
*/
|
|
2069
|
+
insertFeaturesTo(layerName, features) {
|
|
2070
|
+
this._transactWFS('insert', features, layerName);
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Shows a fields form in a modal window to allow changes in the properties of the feature.
|
|
2074
|
+
*
|
|
2075
|
+
* @param feature
|
|
2076
|
+
* @private
|
|
2077
|
+
*/
|
|
2078
|
+
_initEditFieldsModal(feature) {
|
|
2079
|
+
this._editFeature = feature;
|
|
2080
|
+
const properties = feature.getProperties();
|
|
2081
|
+
const layer = feature.get('_layerName_');
|
|
2082
|
+
// Data schema from the geoserver
|
|
2083
|
+
const dataSchema = this._geoServerData[layer].properties;
|
|
2084
|
+
let content = '<form autocomplete="false">';
|
|
2085
|
+
Object.keys(properties).forEach((key) => {
|
|
2086
|
+
// If the feature field exists in the geoserver and is not added by openlayers
|
|
2087
|
+
const field = dataSchema.find((data) => data.name === key);
|
|
2088
|
+
if (field) {
|
|
2089
|
+
const typeXsd = field.type;
|
|
2090
|
+
let type;
|
|
2091
|
+
switch (typeXsd) {
|
|
2092
|
+
case 'xsd:string':
|
|
2093
|
+
type = 'text';
|
|
2094
|
+
break;
|
|
2095
|
+
case 'xsd:number':
|
|
2096
|
+
case 'xsd:int':
|
|
2097
|
+
type = 'number';
|
|
2098
|
+
break;
|
|
2099
|
+
case 'xsd:date-time':
|
|
2100
|
+
type = 'datetime';
|
|
2101
|
+
break;
|
|
2102
|
+
default:
|
|
2103
|
+
type = 'text';
|
|
2104
|
+
}
|
|
2105
|
+
if (type) {
|
|
2106
|
+
content += `
|
|
2107
|
+
<div class="ol-wfst--input-field-container">
|
|
2108
|
+
<label class="ol-wfst--input-field-label" for="${key}">${key}</label>
|
|
2109
|
+
<input placeholder="NULL" class="ol-wfst--input-field-input" type="${type}" name="${key}" value="${properties[key] || ''}">
|
|
2110
|
+
</div>`;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
});
|
|
2114
|
+
content += '</form>';
|
|
2115
|
+
const footer = `
|
|
2116
|
+
<button type="button" class="btn btn-sm btn-link btn-third" data-action="delete" data-dismiss="modal">
|
|
2117
|
+
${this._i18n.labels.delete}
|
|
2118
|
+
</button>
|
|
2119
|
+
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">
|
|
2120
|
+
${this._i18n.labels.cancel}
|
|
2121
|
+
</button>
|
|
2122
|
+
<button type="button" class="btn btn-sm btn-primary" data-action="save" data-dismiss="modal">
|
|
2123
|
+
${this._i18n.labels.save}
|
|
2124
|
+
</button>
|
|
2125
|
+
`;
|
|
2126
|
+
const modal = new Modal(Object.assign(Object.assign({}, this._options.modal), { header: true, headerClose: true, title: `${this._i18n.labels.editElement} ${this._editFeature.getId()} `, content: content, footer: footer })).show();
|
|
2127
|
+
modal.on('dismiss', (modal, event) => {
|
|
2128
|
+
// On saving changes
|
|
2129
|
+
if (event.target.dataset.action === 'save') {
|
|
2130
|
+
const inputs = modal.el.querySelectorAll('input');
|
|
2131
|
+
inputs.forEach((el) => {
|
|
2132
|
+
const value = el.value;
|
|
2133
|
+
const field = el.name;
|
|
2134
|
+
this._editFeature.set(field, value, /*isSilent = */ true);
|
|
2135
|
+
});
|
|
2136
|
+
this._editFeature.changed();
|
|
2137
|
+
this._addFeatureToEditedList(this._editFeature);
|
|
2138
|
+
// Force deselect to trigger handler
|
|
2139
|
+
this._collectionModify.remove(this._editFeature);
|
|
2140
|
+
}
|
|
2141
|
+
else if (event.target.dataset.action === 'delete') {
|
|
2142
|
+
this._deleteFeature(this._editFeature, true);
|
|
2143
|
+
}
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Remove the overlay helper atttached to a specify feature
|
|
2148
|
+
* @param feature
|
|
2149
|
+
* @private
|
|
2150
|
+
*/
|
|
2151
|
+
_removeOverlayHelper(feature) {
|
|
2152
|
+
const featureId = feature.getId();
|
|
2153
|
+
if (!featureId) {
|
|
2154
|
+
return;
|
|
2155
|
+
}
|
|
2156
|
+
const overlay = this._map.getOverlayById(featureId);
|
|
2157
|
+
if (!overlay) {
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
this._map.removeOverlay(overlay);
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
*
|
|
2165
|
+
* @param target
|
|
2166
|
+
* @param sources
|
|
2167
|
+
* @returns
|
|
2168
|
+
* @private
|
|
2169
|
+
*/
|
|
2170
|
+
const deepObjectAssign = (target, ...sources) => {
|
|
2171
|
+
sources.forEach((source) => {
|
|
2172
|
+
Object.keys(source).forEach((key) => {
|
|
2173
|
+
const s_val = source[key];
|
|
2174
|
+
const t_val = target[key];
|
|
2175
|
+
target[key] =
|
|
2176
|
+
t_val &&
|
|
2177
|
+
s_val &&
|
|
2178
|
+
typeof t_val === 'object' &&
|
|
2179
|
+
typeof s_val === 'object' &&
|
|
2180
|
+
!Array.isArray(t_val) // Don't merge arrays
|
|
2181
|
+
? deepObjectAssign(t_val, s_val)
|
|
2182
|
+
: s_val;
|
|
2183
|
+
});
|
|
2184
|
+
});
|
|
2185
|
+
return target;
|
|
2186
|
+
};
|
|
2257
2187
|
|
|
2258
2188
|
export default Wfst;
|
|
2189
|
+
//# sourceMappingURL=ol-wfst.js.map
|