ol-wfst 1.0.9 → 3.0.2

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