ol-wfst 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ol-wfst.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * ol-wfst - v4.4.0
2
+ * ol-wfst - v5.0.1
3
3
  * https://github.com/GastonZalba/ol-wfst#readme
4
- * Built: Thu Sep 10 2026 23:06:10 GMT-0300 (Argentina Standard Time)
4
+ * Built: Thu Oct 08 2026 20:27:23 GMT-0300 (Argentina Standard Time)
5
5
  */
6
6
  (function (global, factory) {
7
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('ol/style/Fill.js'), require('ol/style/Stroke.js'), require('ol/style/Style.js'), require('ol/control/Control.js'), require('ol/control/FullScreen.js'), require('ol/interaction/Draw.js'), require('ol/interaction/DragBox.js'), require('ol/interaction/Modify.js'), require('ol/interaction/Select.js'), require('ol/interaction/Snap.js'), require('ol/geom/LineString.js'), require('ol/geom/MultiLineString.js'), require('ol/geom/GeometryCollection.js'), require('ol/Collection.js'), require('ol/layer/Vector.js'), require('ol/source/Vector.js'), require('ol/events/Event.js'), require('ol/events/condition.js'), require('ol/Observable.js'), require('ol/coordinate.js'), require('ol/extent.js'), require('ol/layer/Base.js'), require('ol/format/GeoJSON.js'), require('ol/proj.js'), require('ol/loadingstrategy.js'), require('ol/layer/Tile.js'), require('ol/source/TileWMS.js'), require('ol/geom.js'), require('ol/format/KML.js'), require('ol/format/WFS.js'), require('ol/style.js'), require('ol/Object.js'), require('ol/geom/Circle.js'), require('ol/Feature.js'), require('ol/geom/Polygon.js'), require('ol/format/XML.js'), require('ol/xml.js'), require('ol/format/xlink.js'), require('ol/format/xsd.js'), require('ol/Overlay.js')) :
@@ -1149,7 +1149,6 @@
1149
1149
  save: 'Guardar',
1150
1150
  delete: 'Eliminar',
1151
1151
  cancel: 'Cancelar',
1152
- apply: 'Aplicar cambios',
1153
1152
  upload: 'Subir',
1154
1153
  editMode: 'Modo Edición',
1155
1154
  confirmDelete: '¿Estás seguro de borrar el elemento?',
@@ -1170,6 +1169,10 @@
1170
1169
  multipleValues: 'Valores múltiples',
1171
1170
  editElements: 'Editar elementos ({})',
1172
1171
  multipleEditNotice: 'Edición múltiple activada. Los cambios se aplicarán a los {} elementos seleccionados.',
1172
+ tableMode: 'Modo tabla',
1173
+ formMode: 'Modo formulario',
1174
+ feature: 'Elemento',
1175
+ geometry: 'Geometría',
1173
1176
  geoserverLayers: 'Capas de GeoServer'
1174
1177
  },
1175
1178
  errors: {
@@ -1200,7 +1203,6 @@
1200
1203
  save: 'Save',
1201
1204
  delete: 'Delete',
1202
1205
  cancel: 'Cancel',
1203
- apply: 'Apply changes',
1204
1206
  upload: 'Upload',
1205
1207
  editMode: 'Edit Mode',
1206
1208
  confirmDelete: 'Are you sure to delete the feature?',
@@ -1221,6 +1223,10 @@
1221
1223
  multipleValues: 'Multiple values',
1222
1224
  editElements: 'Edit features ({})',
1223
1225
  multipleEditNotice: 'Multi-edit active. Changes will be applied to the {} selected features.',
1226
+ tableMode: 'Table mode',
1227
+ formMode: 'Form mode',
1228
+ feature: 'Feature',
1229
+ geometry: 'Geometry',
1224
1230
  geoserverLayers: 'Geoserver Layers'
1225
1231
  },
1226
1232
  errors: {
@@ -1251,7 +1257,6 @@
1251
1257
  save: '保存',
1252
1258
  delete: '删除',
1253
1259
  cancel: '取消',
1254
- apply: '确认并应用改变',
1255
1260
  upload: '上传',
1256
1261
  editMode: '编辑模式',
1257
1262
  confirmDelete: '确认删除元素?',
@@ -1272,6 +1277,10 @@
1272
1277
  multipleValues: '多个值',
1273
1278
  editElements: '编辑元素({})',
1274
1279
  multipleEditNotice: '多选编辑已激活。更改将应用于所有 {} 个选定元素。',
1280
+ tableMode: '表格模式',
1281
+ formMode: '表单模式',
1282
+ feature: '要素',
1283
+ geometry: '几何',
1275
1284
  geoserverLayers: 'GeoServer 图层'
1276
1285
  },
1277
1286
  errors: {
@@ -2387,7 +2396,7 @@
2387
2396
  ${layer.getVisible() ? 'ol-wfst--visible-on' : ''}
2388
2397
  ${layer === getActiveLayerToInsertEls()
2389
2398
  ? 'ol-wfst--selected-on'
2390
- : ''}`, "data-layer": layerName, children: jsxs("label", { htmlFor: `wfst--${layerName}`, children: [jsxs("div", { className: "ol-wfst--tools-control-visible", children: [jsx("span", { className: "ol-wfst--tools-control-visible-btn ol-wfst--visible-btn-on", title: I18N.labels.toggleVisibility, onClick: (evt) => this._visibilityClickHandler(evt), children: visibilityOnSvg() }), jsx("span", { className: "ol-wfst--tools-control-visible-btn ol-wfst--visible-btn-off", title: I18N.labels.toggleVisibility, onClick: (evt) => this._visibilityClickHandler(evt), children: visibilityOffSvg() })] }), input, jsx("span", { title: `${layer instanceof WfsLayer ? 'WFS' : 'WMS'} - ${layer.getDescribeFeatureType()._parsed.geomType}`, children: layer.get(BaseLayerProperty.LABEL) })] }) }));
2399
+ : ''}`, "data-layer": layerName, children: jsxs("label", { htmlFor: `wfst--${layerName}`, children: [jsxs("div", { className: "ol-wfst--layer-control-visible ", children: [jsx("span", { className: "ol-wfst--layer-control-visible -btn ol-wfst--visible-btn-on", title: I18N.labels.toggleVisibility, onClick: (evt) => this._visibilityClickHandler(evt), children: visibilityOnSvg() }), jsx("span", { className: "ol-wfst--layer-control-visible -btn ol-wfst--visible-btn-off", title: I18N.labels.toggleVisibility, onClick: (evt) => this._visibilityClickHandler(evt), children: visibilityOffSvg() })] }), input, jsx("span", { title: `${layer instanceof WfsLayer ? 'WFS' : 'WMS'} - ${layer.getDescribeFeatureType()._parsed.geomType}`, children: layer.get(BaseLayerProperty.LABEL) })] }) }));
2391
2400
  container.appendChild(layerDom);
2392
2401
  if (layer === getActiveLayerToInsertEls()) {
2393
2402
  input.dispatchEvent(new Event('change'));
@@ -2769,13 +2778,13 @@
2769
2778
  super({
2770
2779
  element: (jsx("div", { className: "ol-wfst--changes-control", children: jsxs("div", { className: "ol-wfst--changes-control-el", children: [jsxs("div", { className: "ol-wfst--changes-control-id", children: [jsx("b", { children: I18N.labels.editMode }), " -", ' ', jsx("i", { children: features.length > 1
2771
2780
  ? I18N_('editElements', features.length)
2772
- : String(features[0].getId()) })] }), jsx("button", { type: "button", className: "btn btn-sm btn-secondary", onClick: () => {
2781
+ : String(features[0].getId()) })] }), jsx("button", { type: "button", className: "btn btn-sm btn-danger", onClick: () => {
2782
+ this._dispatch('delete', features);
2783
+ }, children: I18N.labels.delete }), jsx("button", { type: "button", className: "btn btn-sm btn-secondary", onClick: () => {
2773
2784
  this._dispatch('cancel', features);
2774
2785
  }, children: I18N.labels.cancel }), jsx("button", { type: "button", className: "btn btn-sm btn-primary", onClick: () => {
2775
2786
  this._dispatch('apply', features);
2776
- }, children: I18N.labels.apply }), jsx("button", { type: "button", className: "btn btn-sm btn-danger-outline", onClick: () => {
2777
- this._dispatch('delete', features);
2778
- }, children: I18N.labels.delete })] }) }))
2787
+ }, children: I18N.labels.save })] }) }))
2779
2788
  });
2780
2789
  }
2781
2790
  _dispatch(type, features) {
@@ -3000,11 +3009,22 @@
3000
3009
  ];
3001
3010
  }
3002
3011
 
3012
+ function tableSvg() {
3013
+ return (new DOMParser().parseFromString("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path d=\"M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H4v-4h4v4zm0-6H4v-4h4v4zm0-6H4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4z\"></path>\n</svg>", 'image/svg+xml')).firstChild;
3014
+ }
3015
+
3016
+ function formSvg() {
3017
+ return (new DOMParser().parseFromString("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path d=\"M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z\"></path>\n</svg>", 'image/svg+xml')).firstChild;
3018
+ }
3019
+
3003
3020
  /**
3004
3021
  * Shows a fields form in a modal window to allow changes in the properties of
3005
- * one or several features. When editing multiple features, fields whose value
3006
- * differs across the selection show the "multiple values" placeholder and only
3007
- * the fields actually changed are applied to the whole selection.
3022
+ * one or several features. When editing multiple features, a "table mode"
3023
+ * button renders one feature per row, spreadsheet-style, so each feature can be
3024
+ * edited separately (like an Excel sheet). Otherwise a single form is shown
3025
+ * where fields whose value differs across the selection show the "multiple
3026
+ * values" placeholder and only the fields actually changed are applied to the
3027
+ * whole selection.
3008
3028
  *
3009
3029
  * @param features
3010
3030
  * @private
@@ -3013,10 +3033,12 @@
3013
3033
  constructor(options) {
3014
3034
  super();
3015
3035
  this._options = options;
3036
+ this._tableMode = false;
3037
+ this._fieldList = [];
3016
3038
  this._modal = new Modal(Object.assign(Object.assign({}, this._options.modal), { header: true, headerClose: true, title: '', content: '<div></div>', footer: `
3017
3039
  <button
3018
3040
  type="button"
3019
- class="btn btn-sm btn-third"
3041
+ class="btn btn-sm btn-danger"
3020
3042
  data-action="delete"
3021
3043
  data-dismiss="modal"
3022
3044
  >
@@ -3041,29 +3063,12 @@
3041
3063
  this._modal.on('dismiss', (modal, event) => {
3042
3064
  // On saving changes
3043
3065
  if (event.target.dataset.action === 'save') {
3044
- const formElements = modal.el.querySelector('form')
3045
- .elements;
3046
- const multipleFields = new Set(Array.from(formElements)
3047
- .filter((el) => el.dataset.multiple === 'true')
3048
- .map((el) => el.name));
3049
- Array.from(formElements).forEach((el) => {
3050
- const value = el.value;
3051
- const field = el.name;
3052
- // Do not overwrite untouched fields that had
3053
- // multiple values in the selection
3054
- if (multipleFields.has(field) && value === '') {
3055
- return;
3056
- }
3057
- this._features.forEach((feature) => {
3058
- if (feature.get(field) !== value) {
3059
- feature.set(field, value, /* isSilent = */ true);
3060
- }
3061
- });
3062
- });
3063
- this._features.forEach((feature) => {
3064
- feature.changed();
3065
- addFeatureToEditedList(feature);
3066
- });
3066
+ if (this._tableMode) {
3067
+ this._saveTable(modal);
3068
+ }
3069
+ else {
3070
+ this._saveForm(modal);
3071
+ }
3067
3072
  this._dispatch('save', this._features);
3068
3073
  }
3069
3074
  else if (event.target.dataset.action === 'delete') {
@@ -3073,6 +3078,8 @@
3073
3078
  }
3074
3079
  show(features) {
3075
3080
  this._features = Array.isArray(features) ? features : [features];
3081
+ // Keep the form (current behavior) as default entry view
3082
+ this._tableMode = false;
3076
3083
  const multiple = this._features.length > 1;
3077
3084
  const modalTitle = multiple
3078
3085
  ? I18N_('editElements', this._features.length)
@@ -3081,67 +3088,184 @@
3081
3088
  // Data schema from the geoserver
3082
3089
  const layer = getStoredLayer(layerName);
3083
3090
  const describeFeatureType = layer.getDescribeFeatureType()._parsed;
3084
- const fieldList = describeFeatureType.properties.filter((field) => field.name !== describeFeatureType.geomField);
3085
- this._modal._html.body.innerHTML = '';
3086
- this._modal._html.body.append(jsxs("div", { children: [multiple && (jsx("div", { className: "ol-wfst--edit-modal-notice", children: I18N_('multipleEditNotice', this._features.length) })), jsx("form", { autocomplete: "false", children: fieldList.flatMap((field) => {
3087
- const key = field.name;
3088
- const values = this._features.map((feature) => feature.get(key));
3089
- const uniqueValues = Array.from(new Set(values.map((value) => String(value !== null && value !== void 0 ? value : ''))));
3090
- const hasMultipleValues = multiple && uniqueValues.length > 1;
3091
- const value = hasMultipleValues
3092
- ? null
3093
- : uniqueValues[0] || null;
3094
- const typeXsd = field.type;
3095
- let type;
3096
- switch (typeXsd) {
3097
- case 'xsd:double':
3098
- case 'xsd:number':
3099
- case 'xsd:int':
3100
- type = 'number';
3101
- break;
3102
- case 'xsd:date':
3103
- type = 'date';
3104
- break;
3105
- case 'xsd:date-time':
3106
- type = 'datetime';
3107
- break;
3108
- case 'xsd:string':
3109
- default:
3110
- type = 'text';
3111
- }
3112
- let input = (jsx("input", { placeholder: hasMultipleValues
3113
- ? I18N.labels.multipleValues
3114
- : 'NULL', className: 'ol-wfst--input-field-input' +
3115
- (hasMultipleValues
3116
- ? ' ol-wfst--input-multiple'
3117
- : ''), type: type, name: key, value: value, "data-multiple": hasMultipleValues ? 'true' : null }));
3118
- if (layer.beforeShowFieldsModal) {
3119
- const hookInput = layer.beforeShowFieldsModal(field, value, input);
3120
- if (!hookInput) {
3121
- return [];
3122
- }
3123
- if (typeof hookInput === 'string') {
3124
- input = new DOMParser().parseFromString(hookInput, 'text/html').body.childNodes[0];
3125
- }
3126
- else {
3127
- input = hookInput;
3128
- }
3129
- }
3130
- if (hasMultipleValues) {
3131
- input.dataset.multiple = 'true';
3132
- input.classList.add('ol-wfst--input-multiple');
3133
- }
3134
- return (jsxs("div", { className: "ol-wfst--input-field-container", children: [jsx("label", { className: "ol-wfst--input-field-label", htmlFor: key, children: key }), input] }));
3135
- }) })] }));
3091
+ this._fieldList = describeFeatureType.properties.filter((field) => field.name !== describeFeatureType.geomField);
3092
+ this._layer = layer;
3093
+ this._modal._html.dialog.classList.remove('ol-wfst--edit-table-modal');
3094
+ this._renderBody();
3136
3095
  this._modal._html.header.innerHTML = modalTitle;
3137
3096
  this._modal.show();
3138
3097
  }
3098
+ _renderBody() {
3099
+ const multiple = this._features.length > 1;
3100
+ this._modal._html.body.innerHTML = '';
3101
+ this._modal._html.body.append(jsxs("div", { children: [multiple && (jsxs("div", { className: "ol-wfst--edit-modal-notice", children: [jsx("span", { className: "ol-wfst--edit-modal-notice-txt", children: I18N_('multipleEditNotice', this._features.length) }), jsx("button", { type: "button", className: "ol-wfst--edit-modal-toolbar-btn", title: this._tableMode
3102
+ ? I18N.labels.formMode
3103
+ : I18N.labels.tableMode, onClick: () => this._toggleTable(), children: this._tableMode ? formSvg() : tableSvg() })] })), this._tableMode ? this._renderTable() : this._renderForm()] }));
3104
+ }
3105
+ _toggleTable() {
3106
+ this._tableMode = !this._tableMode;
3107
+ this._modal._html.dialog.classList.toggle('ol-wfst--edit-table-modal', this._tableMode);
3108
+ this._renderBody();
3109
+ }
3110
+ _renderForm() {
3111
+ const multiple = this._features.length > 1;
3112
+ return (jsx("form", { autocomplete: "false", children: this._fieldList.flatMap((field) => {
3113
+ const key = field.name;
3114
+ const values = this._features.map((feature) => feature.get(key));
3115
+ const uniqueValues = Array.from(new Set(values.map((value) => String(value !== null && value !== void 0 ? value : ''))));
3116
+ const hasMultipleValues = multiple && uniqueValues.length > 1;
3117
+ const value = hasMultipleValues
3118
+ ? null
3119
+ : uniqueValues[0] || null;
3120
+ const type = this._inputType(field.type);
3121
+ let input = (jsx("input", { placeholder: hasMultipleValues
3122
+ ? I18N.labels.multipleValues
3123
+ : 'NULL', className: 'ol-wfst--input-field-input' +
3124
+ (hasMultipleValues
3125
+ ? ' ol-wfst--input-multiple'
3126
+ : ''), type: type, name: key, value: value, "data-multiple": hasMultipleValues ? 'true' : null }));
3127
+ if (this._layer.beforeShowFieldsModal) {
3128
+ const hookInput = this._layer.beforeShowFieldsModal(field, value, input);
3129
+ if (!hookInput) {
3130
+ return [];
3131
+ }
3132
+ if (typeof hookInput === 'string') {
3133
+ input = new DOMParser().parseFromString(hookInput, 'text/html').body.childNodes[0];
3134
+ }
3135
+ else {
3136
+ input = hookInput;
3137
+ }
3138
+ }
3139
+ if (hasMultipleValues) {
3140
+ input.dataset.multiple = 'true';
3141
+ input.classList.add('ol-wfst--input-multiple');
3142
+ }
3143
+ return (jsxs("div", { className: "ol-wfst--input-field-container", children: [jsx("label", { className: "ol-wfst--input-field-label", htmlFor: key, children: key }), input] }));
3144
+ }) }));
3145
+ }
3146
+ _renderTable() {
3147
+ return (jsx("form", { autocomplete: "false", children: jsx("div", { className: "ol-wfst--edit-table-wrap", children: jsxs("table", { className: "ol-wfst--edit-table", children: [jsx("thead", { children: jsxs("tr", { children: [jsx("th", { children: I18N.labels.feature }), jsx("th", { children: I18N.labels.geometry }), this._fieldList.map((field) => (jsx("th", { children: field.name })))] }) }), jsx("tbody", { children: this._features.map((feature, idx) => {
3148
+ var _a;
3149
+ return (jsxs("tr", { children: [jsx("td", { className: "ol-wfst--edit-table-fid", children: String((_a = feature.getId()) !== null && _a !== void 0 ? _a : idx + 1) }), jsx("td", { className: "ol-wfst--edit-table-geom", children: geometryTypeLabel(feature.getGeometry()) }), this._fieldList.map((field) => {
3150
+ var _a;
3151
+ const key = field.name;
3152
+ const type = this._inputType(field.type);
3153
+ const value = (_a = feature.get(key)) !== null && _a !== void 0 ? _a : '';
3154
+ let input = (jsx("input", { type: type, name: key, className: "ol-wfst--input-field-input", "data-feat-idx": String(idx), value: String(value) }));
3155
+ if (this._layer.beforeShowFieldsModal) {
3156
+ const hookInput = this._layer.beforeShowFieldsModal(field, value, input);
3157
+ if (!hookInput) {
3158
+ return jsx("td", {});
3159
+ }
3160
+ if (typeof hookInput === 'string') {
3161
+ input =
3162
+ new DOMParser().parseFromString(hookInput, 'text/html').body
3163
+ .childNodes[0];
3164
+ }
3165
+ else {
3166
+ input = hookInput;
3167
+ }
3168
+ input.setAttribute('name', key);
3169
+ input.setAttribute('data-feat-idx', String(idx));
3170
+ input.classList.add('ol-wfst--input-field-input');
3171
+ }
3172
+ return jsx("td", { children: input });
3173
+ })] }));
3174
+ }) })] }) }) }));
3175
+ }
3176
+ _inputType(typeXsd) {
3177
+ switch (typeXsd) {
3178
+ case 'xsd:double':
3179
+ case 'xsd:number':
3180
+ case 'xsd:int':
3181
+ return 'number';
3182
+ case 'xsd:date':
3183
+ return 'date';
3184
+ case 'xsd:date-time':
3185
+ return 'datetime';
3186
+ case 'xsd:string':
3187
+ default:
3188
+ return 'text';
3189
+ }
3190
+ }
3191
+ _saveForm(modal) {
3192
+ const formElements = modal.el.querySelector('form')
3193
+ .elements;
3194
+ const multipleFields = new Set(Array.from(formElements)
3195
+ .filter((el) => el.dataset.multiple === 'true')
3196
+ .map((el) => el.name));
3197
+ Array.from(formElements).forEach((el) => {
3198
+ const value = el.value;
3199
+ const field = el.name;
3200
+ // Do not overwrite untouched fields that had
3201
+ // multiple values in the selection
3202
+ if (multipleFields.has(field) && value === '') {
3203
+ return;
3204
+ }
3205
+ this._features.forEach((feature) => {
3206
+ if (feature.get(field) !== value) {
3207
+ feature.set(field, value, /* isSilent = */ true);
3208
+ }
3209
+ });
3210
+ });
3211
+ this._features.forEach((feature) => {
3212
+ feature.changed();
3213
+ addFeatureToEditedList(feature);
3214
+ });
3215
+ }
3216
+ _saveTable(modal) {
3217
+ const inputList = Array.from(modal.el.querySelectorAll('form input[data-feat-idx]'));
3218
+ const grouped = new Map();
3219
+ inputList.forEach((input) => {
3220
+ const idx = Number(input.dataset.featIdx);
3221
+ if (!grouped.has(idx)) {
3222
+ grouped.set(idx, []);
3223
+ }
3224
+ grouped.get(idx).push(input);
3225
+ });
3226
+ grouped.forEach((inputs, idx) => {
3227
+ const feature = this._features[idx];
3228
+ if (!feature) {
3229
+ return;
3230
+ }
3231
+ inputs.forEach((input) => {
3232
+ const field = input.name;
3233
+ const value = input.value;
3234
+ if (feature.get(field) !== value) {
3235
+ feature.set(field, value, /* isSilent = */ true);
3236
+ }
3237
+ });
3238
+ });
3239
+ this._features.forEach((feature) => {
3240
+ feature.changed();
3241
+ addFeatureToEditedList(feature);
3242
+ });
3243
+ }
3139
3244
  _dispatch(type, features) {
3140
3245
  const evt = new VectorSource.VectorSourceEvent(type, features[0]);
3141
3246
  evt.features = features;
3142
3247
  this.dispatchEvent(evt);
3143
3248
  }
3144
3249
  }
3250
+ function geometryTypeLabel(geometry) {
3251
+ if (!geometry) {
3252
+ return '-';
3253
+ }
3254
+ if (geometry instanceof GeometryCollection) {
3255
+ const types = new Set();
3256
+ const collect = (geom) => {
3257
+ if (geom instanceof GeometryCollection) {
3258
+ geom.getGeometriesArray().forEach(collect);
3259
+ }
3260
+ else {
3261
+ types.add(geom.getType());
3262
+ }
3263
+ };
3264
+ collect(geometry);
3265
+ return types.size ? Array.from(types).join(', ') : '-';
3266
+ }
3267
+ return geometry.getType();
3268
+ }
3145
3269
 
3146
3270
  /**
3147
3271
  * @module ol/format/WFSCapabilities
@@ -4745,6 +4869,7 @@
4745
4869
  this._map = super.getMap();
4746
4870
  this._view = this._map.getView();
4747
4871
  this._viewport = this._map.getViewport();
4872
+ this._map.getTargetElement().classList.add('ol-wfst--map');
4748
4873
  setMap(this._map);
4749
4874
  //@ts-expect-error
4750
4875
  this._uploads.on('addedFeatures', ({ features }) => {
@@ -5234,6 +5359,23 @@
5234
5359
  activateQueryMode(bool = true) {
5235
5360
  var _a, _b;
5236
5361
  if (bool) {
5362
+ // While a geometry/fields edit is in progress the tools toolbar is
5363
+ // hidden)Skip, so the only way out is Apply, Discard or Delete.
5364
+ // Guard here too so programmatic calls cannot leave the edit mode.
5365
+ if (getMode() === Modes.Edit) {
5366
+ return;
5367
+ }
5368
+ // If features are merely selected (not being edited), deselect
5369
+ // them without transacting: each removal restores the feature to
5370
+ // its original layer and turns the edit mode off.
5371
+ if (this._collectionModify.getLength()) {
5372
+ this._collectionModify
5373
+ .getArray()
5374
+ .slice()
5375
+ .forEach((feature) => {
5376
+ this._collectionModify.remove(feature);
5377
+ });
5378
+ }
5237
5379
  // Leave any draw interaction active
5238
5380
  if (this._interactionDraw) {
5239
5381
  this._map.removeInteraction(this._interactionDraw);
@@ -5624,6 +5766,29 @@
5624
5766
  }
5625
5767
  });
5626
5768
  }
5769
+ /**
5770
+ * Hide the whole tools toolbar (geometry/draw/select/query buttons and
5771
+ * the layer selector). It is hidden while a geometry/fields edit is in
5772
+ * progress so the only way out is Apply, Discard or Delete.
5773
+ *
5774
+ * @private
5775
+ */
5776
+ _hideControls() {
5777
+ // While an edit is in progress the tools toolbar and the layers widget
5778
+ // disappear together: the only controls left on screen are Apply,
5779
+ // Discard and Delete.
5780
+ this._controlWidgetToolsDiv.classList.add('ol-wfst--controls--hidden');
5781
+ this._layersWidgetDiv.classList.add('ol-wfst--controls--hidden');
5782
+ }
5783
+ /**
5784
+ * Show the tools toolbar again.
5785
+ *
5786
+ * @private
5787
+ */
5788
+ _showControls() {
5789
+ this._controlWidgetToolsDiv.classList.remove('ol-wfst--controls--hidden');
5790
+ this._layersWidgetDiv.classList.remove('ol-wfst--controls--hidden');
5791
+ }
5627
5792
  /**
5628
5793
  *
5629
5794
  * @param features
@@ -5636,6 +5801,10 @@
5636
5801
  feature.clone();
5637
5802
  });
5638
5803
  activateMode(Modes.Edit);
5804
+ // While a geometry/fields edit is in progress the whole tools toolbar
5805
+ // and the layers widget are hidden together, so the only way out is
5806
+ // Apply, Discard or Delete
5807
+ this._hideControls();
5639
5808
  // Show the "continue drawing" buttons on the line endpoints
5640
5809
  this._syncExtendLineOverlays();
5641
5810
  // To refresh the style
@@ -5679,6 +5848,8 @@
5679
5848
  * @private
5680
5849
  */
5681
5850
  _editModeOff() {
5851
+ // Restore the tools toolbar and the layers widget together
5852
+ this._showControls();
5682
5853
  activateMode(null);
5683
5854
  this._destroyExtendLineOverlays();
5684
5855
  this._map.removeControl(this._controlApplyDiscardChanges);
@@ -5975,10 +6146,10 @@
5975
6146
  * Remove features from the edit Layer and from the Geoserver
5976
6147
  *
5977
6148
  * @param feature
5978
- * @param confirm
6149
+ * @param askToConfirm
5979
6150
  * @private
5980
6151
  */
5981
- _deleteFeature(feature, confirm) {
6152
+ _deleteFeature(feature, askToConfirm) {
5982
6153
  const deleteEl = () => {
5983
6154
  var _a;
5984
6155
  const features = Array.isArray(feature) ? feature : [feature];
@@ -5999,14 +6170,21 @@
5999
6170
  });
6000
6171
  }
6001
6172
  };
6002
- if (confirm) {
6173
+ if (askToConfirm) {
6003
6174
  const features = Array.isArray(feature) ? feature : [feature];
6004
6175
  const message = features.length > 1
6005
6176
  ? I18N_('confirmDeleteElements', features.length)
6006
6177
  : I18N.labels.confirmDelete;
6007
- const confirmModal = Modal.confirm(message, Object.assign({}, this._options.modal));
6008
- confirmModal.show().once('dismiss', function (modal, ev, button) {
6009
- if (button && button.value) {
6178
+ const confirmModal = Modal.confirm(message, Object.assign(Object.assign({}, this._options.modal), { footer: `
6179
+ <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">
6180
+ ${I18N.labels.cancel}
6181
+ </button>
6182
+ <button type="button" class="btn btn-sm btn-danger" data-action="delete" data-dismiss="modal">
6183
+ ${I18N.labels.delete}
6184
+ </button>
6185
+ ` }));
6186
+ confirmModal.show().once('dismiss', function (modal, event) {
6187
+ if (event.target.dataset.action == 'delete') {
6010
6188
  deleteEl();
6011
6189
  }
6012
6190
  });