@geogirafe/lib-geoportal 1.2.0-dev.2657953927 → 1.2.0-dev.2666667702

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.
@@ -12,6 +12,7 @@ declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGira
12
12
  panelTitle: string;
13
13
  panelTogglePath: string;
14
14
  loading: boolean;
15
+ private readonly debouncedUpdateFilterItems;
15
16
  layers: LayerWms[];
16
17
  layerFilterElements: LayerFilterElement[];
17
18
  columnAliasHelper: ColumnAliasHelper;
@@ -40,7 +41,12 @@ declare class AdvancedFilterComponent extends GirafeHTMLElement implements IGira
40
41
  */
41
42
  private addFilterElementFromLayer;
42
43
  onFilterRemoved(filterElement: LayerFilterElement): void;
44
+ /**
45
+ * Removes a filter element from the UI and optionally from the layer.
46
+ * Note that the filter should only be removed from the layer if this was triggered by a user action in this component.
47
+ */
43
48
  private removeFilterElement;
49
+ private onFilterChangedInLayerTree;
44
50
  onLayerChanged(filterElement: LayerFilterElement, e: Event): Promise<void>;
45
51
  onConditionRemoved(filterElement: LayerFilterElement, condition: FilterConditionElement): void;
46
52
  onConditionAdded(filterElement: LayerFilterElement): void;
@@ -11,6 +11,7 @@ import LayerWms from '../../models/layers/layerwms.js';
11
11
  import ColumnAliasHelper from '../../tools/utils/aliases.js';
12
12
  import LayerFilterElement from './layerfilterelement.js';
13
13
  import GroupLayer from '../../models/layers/grouplayer.js';
14
+ import { debounce } from '../../tools/utils/debounce.js';
14
15
  import { UsedInTemplateOnly } from '../../decorators.js';
15
16
  import FilterConditionElement from './filterconditionelement.js';
16
17
  import LayerCsvExporter from './layercsvexporter.js';
@@ -31,6 +32,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
31
32
  panelTitle = 'advanced-filter-panel';
32
33
  panelTogglePath = 'interface.advancedFilterPanelVisible';
33
34
  loading = false;
35
+ debouncedUpdateFilterItems = debounce(this.updateFilterItemsByLayerState.bind(this), 200);
34
36
  layers = [];
35
37
  layerFilterElements = [];
36
38
  columnAliasHelper;
@@ -48,15 +50,13 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
48
50
  super.girafeTranslate();
49
51
  }
50
52
  registerEvents() {
51
- this.subscribe(/layers\.layersList\..*/, () => {
52
- if (this.isPanelVisible) {
53
- void this.updateFilterItemsByLayerState();
54
- }
55
- });
53
+ // Listen for filter changes on the layer list, triggered by changes in the simple filter component
54
+ this.subscribe(/layers\.layersList\..*\.filter/, (oldFilter, newFilter, layer) => this.onFilterChangedInLayerTree(oldFilter, newFilter, layer));
55
+ // Listen for layer visibility changes
56
56
  this.subscribe(/layers\.layersList\..*\.activeState/, (_oldValue, _newValue, layer) => {
57
57
  if (layer instanceof LayerWms && this.isPanelVisible && !this.state.loading) {
58
- this.updateFilterableLayerList();
59
- this.render();
58
+ // Debounce the filter element updates to avoid premature action / rendering while the layer tree is still changing
59
+ void this.debouncedUpdateFilterItems();
60
60
  }
61
61
  });
62
62
  this.subscribe('loading', (_, loading) => {
@@ -88,18 +88,17 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
88
88
  // Update which layers are active and queryable
89
89
  this.updateFilterableLayerList();
90
90
  // Remove filter elements that are no longer needed
91
- for (const filterElement of this.layerFilterElements) {
91
+ const filtersToBeRemoved = this.layerFilterElements.filter((filterElement) => {
92
92
  const layerInTree = this.layers.find((l) => l.id === filterElement.layer?.id);
93
- if (
93
+ return (
94
94
  // Filter element does not have a layer yet
95
95
  filterElement.layer === undefined ||
96
96
  // Layer isn't in layer tree anymore
97
97
  (filterElement.layer && !layerInTree) ||
98
98
  // Filter in layer was removed by simple filter component
99
- (filterElement.layer && layerInTree.filter === undefined && filterElement.hasAppliedConditions())) {
100
- this.removeFilterElement(filterElement);
101
- }
102
- }
99
+ (filterElement.layer && layerInTree.filter === undefined && filterElement.hasAppliedConditions()));
100
+ });
101
+ filtersToBeRemoved.forEach((filterElement) => this.removeFilterElement(filterElement, false));
103
102
  // Add filter elements for layers that are new in the layer tree and do not have a filter element yet
104
103
  for (const layer of this.layers) {
105
104
  if (layer.hasFilter && !this.layerFilterElements.some((f) => f.layer?.id === layer.id)) {
@@ -148,20 +147,38 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
148
147
  this.layerFilterElements.push(filterElement);
149
148
  }
150
149
  onFilterRemoved(filterElement) {
151
- this.removeFilterElement(filterElement);
150
+ this.removeFilterElement(filterElement, true);
152
151
  this.render();
153
152
  }
154
- removeFilterElement(filterElement) {
153
+ /**
154
+ * Removes a filter element from the UI and optionally from the layer.
155
+ * Note that the filter should only be removed from the layer if this was triggered by a user action in this component.
156
+ */
157
+ removeFilterElement(filterElement, removeFilterFromLayer = true) {
155
158
  const idx = this.layerFilterElements.indexOf(filterElement);
156
159
  if (idx !== -1) {
157
160
  filterElement.removeConditions();
158
161
  this.layerFilterElements.splice(idx, 1);
159
- if (filterElement.layer?.filter) {
162
+ if (removeFilterFromLayer && filterElement.layer?.filter) {
160
163
  // Note: Changing layer.filter will trigger the subscription that re-renders the component
161
164
  filterElement.layer.filter = undefined;
162
165
  }
163
166
  }
164
167
  }
168
+ onFilterChangedInLayerTree(oldFilter, newFilter, layer) {
169
+ if (oldFilter === undefined || newFilter === undefined) {
170
+ // Cleanly add or remove filter elements in the UI
171
+ void this.updateFilterItemsByLayerState();
172
+ return;
173
+ }
174
+ // Refresh the displayed filter element with the new filter
175
+ for (const filterElement of this.layerFilterElements) {
176
+ if (filterElement.layer?.id === layer.id) {
177
+ filterElement.setFromLayer(layer).then(() => this.render());
178
+ break;
179
+ }
180
+ }
181
+ }
165
182
  async onLayerChanged(filterElement, e) {
166
183
  if (!filterElement.conditions.length) {
167
184
  // Display an empty condition while layer metadata is being loaded
@@ -176,7 +193,7 @@ ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
176
193
  this.layerFilterElements.push(newFilter);
177
194
  newFilter?.setLayer(layer).then((_) => this.render());
178
195
  // Remove filter from previous layer and from UI
179
- this.removeFilterElement(filterElement);
196
+ this.removeFilterElement(filterElement, true);
180
197
  }
181
198
  else {
182
199
  // Simply switch out layers
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geogirafe.org"
7
7
  },
8
- "version": "1.2.0-dev.2657953927",
8
+ "version": "1.2.0-dev.2666667702",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.2.0-dev.2657953927", "build":"2657953927", "date":"07/07/2026"}
1
+ {"version":"1.2.0-dev.2666667702", "build":"2666667702", "date":"10/07/2026"}
@@ -4,7 +4,7 @@ export var HighlightMode;
4
4
  HighlightMode["HighlightAll"] = "highlight-all";
5
5
  HighlightMode["HighlightPerLayer"] = "highlight-per-layer";
6
6
  })(HighlightMode || (HighlightMode = {}));
7
- import { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './sanitizeconfig.defaults';
7
+ import { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './sanitizeconfig-defaults.js';
8
8
  class GirafeConfig {
9
9
  general;
10
10
  languages;
package/tools/main.d.ts CHANGED
@@ -11,7 +11,7 @@ export { default as PluginManager } from './auth/pluginmanager.js';
11
11
  export { default as ConfigManager } from './configuration/configmanager.js';
12
12
  export type { HighlightMode } from './configuration/girafeconfig.js';
13
13
  export { default as GirafeConfig } from './configuration/girafeconfig.js';
14
- export { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './configuration/sanitizeconfig.defaults';
14
+ export { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './configuration/sanitizeconfig-defaults.js';
15
15
  export { default as GirafeContext } from './context/context.js';
16
16
  export type { default as IGirafeContext } from './context/icontext.js';
17
17
  export { default as CesiumDrawing } from './drawing/cesiumDrawing.js';
@@ -111,8 +111,8 @@ export type { GgUserInteractionListener } from './state/userInteractionManager.j
111
111
  export { default as UserInteractionManager } from './state/userInteractionManager.js';
112
112
  export type { GgUserInteractionEvent } from './state/userinteractionevent.js';
113
113
  export { gGEventDependencies, isPrimaryPointerAction, isAlternateMouseClick, isMouseWheelClick } from './state/userinteractionevent.js';
114
- export type { SwState } from './sw/service-worker.tools';
115
- export { swLog, SwHelper, IndexedDbHelper, CacheHelper } from './sw/service-worker.tools';
114
+ export type { SwState } from './sw/service-worker-tools.js';
115
+ export { swLog, SwHelper, IndexedDbHelper, CacheHelper } from './sw/service-worker-tools.js';
116
116
  export { default as CustomThemesManager } from './themes/customthemesmanager.js';
117
117
  export { default as ThemeFavoritesManager } from './themes/themefavoritesmanager.js';
118
118
  export { DEFAULT_OPACITY, OPACITY_FOR_DEFAULT_BASEMAP } from './themes/themes-config.js';
package/tools/main.js CHANGED
@@ -10,7 +10,7 @@ export { default as OpenIdConnectManager } from './auth/openidconnectmanager.js'
10
10
  export { default as PluginManager } from './auth/pluginmanager.js';
11
11
  export { default as ConfigManager } from './configuration/configmanager.js';
12
12
  export { default as GirafeConfig } from './configuration/girafeconfig.js';
13
- export { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './configuration/sanitizeconfig.defaults';
13
+ export { defaultNewsSanitizeConfig, defaultPermalinkSanitizeConfig, defaultQuerySanitizeConfig } from './configuration/sanitizeconfig-defaults.js';
14
14
  export { default as GirafeContext } from './context/context.js';
15
15
  export { default as CesiumDrawing } from './drawing/cesiumDrawing.js';
16
16
  export { default as DrawingFeature } from './drawing/drawingFeature.js';
@@ -81,7 +81,7 @@ export { default as StateToggleManager } from './state/stateToggleManager.js';
81
81
  export { default as StateManager } from './state/statemanager.js';
82
82
  export { default as UserInteractionManager } from './state/userInteractionManager.js';
83
83
  export { gGEventDependencies, isPrimaryPointerAction, isAlternateMouseClick, isMouseWheelClick } from './state/userinteractionevent.js';
84
- export { swLog, SwHelper, IndexedDbHelper, CacheHelper } from './sw/service-worker.tools';
84
+ export { swLog, SwHelper, IndexedDbHelper, CacheHelper } from './sw/service-worker-tools.js';
85
85
  export { default as CustomThemesManager } from './themes/customthemesmanager.js';
86
86
  export { default as ThemeFavoritesManager } from './themes/themefavoritesmanager.js';
87
87
  export { DEFAULT_OPACITY, OPACITY_FOR_DEFAULT_BASEMAP } from './themes/themes-config.js';
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  import GirafeSingleton from '../../base/GirafeSingleton.js';
3
- import { IndexedDbHelper } from '../sw/service-worker.tools';
3
+ import { IndexedDbHelper } from '../sw/service-worker-tools.js';
4
4
  import { Feature } from 'ol';
5
5
  import VectorLayer from 'ol/layer/Vector.js';
6
6
  import VectorSource from 'ol/source/Vector.js';
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // NOTE REG: Here the extension ".js" MUST be present in the import,
3
3
  // otherwise the service-worker won't be able to find the transpiled file
4
- import { SwHelper, IndexedDbHelper, swLog, CacheHelper } from './service-worker.tools.js';
4
+ import { SwHelper, IndexedDbHelper, swLog, CacheHelper } from './service-worker-tools.js';
5
5
  /**
6
6
  * The service worker state needs to be persisted
7
7
  * because when not using the app, the service worker can be paused by the browser