geonetwork-ui 2.11.0-dev.c42282af5 → 2.11.0-dev.cf22e64cf

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 (41) hide show
  1. package/fesm2022/geonetwork-ui.mjs +1093 -1233
  2. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  3. package/index.d.ts +61 -54
  4. package/index.d.ts.map +1 -1
  5. package/package.json +1 -1
  6. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +15 -2
  7. package/src/libs/common/domain/src/lib/model/search/filter.model.ts +4 -1
  8. package/src/libs/feature/map/src/index.ts +0 -2
  9. package/src/libs/feature/map/src/lib/feature-map.module.ts +1 -8
  10. package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.ts +8 -3
  11. package/src/libs/feature/search/src/index.ts +2 -0
  12. package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.ts +8 -3
  13. package/src/libs/feature/{map/src/lib → search/src/lib/geocoding}/geocoding.service.ts +16 -7
  14. package/src/libs/feature/search/src/lib/location-search/location-search.component.html +8 -0
  15. package/src/libs/feature/search/src/lib/location-search/location-search.component.ts +40 -0
  16. package/src/libs/feature/search/src/lib/search-filters-summary-item/search-filters-summary-item.component.ts +1 -0
  17. package/src/libs/feature/search/src/lib/state/reducer.ts +1 -4
  18. package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +6 -0
  19. package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.html +10 -1
  20. package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +8 -0
  21. package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.html +2 -2
  22. package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.ts +8 -2
  23. package/src/libs/ui/layout/src/lib/block-list/block-list.component.css +1 -0
  24. package/src/libs/util/app-config/src/lib/app-config.ts +20 -0
  25. package/src/libs/util/app-config/src/lib/fixtures.ts +16 -1
  26. package/src/libs/util/app-config/src/lib/model.ts +14 -1
  27. package/src/libs/util/shared/src/lib/utils/geojson.ts +16 -0
  28. package/translations/de.json +4 -2
  29. package/translations/en.json +6 -4
  30. package/translations/es.json +4 -2
  31. package/translations/fr.json +11 -9
  32. package/translations/it.json +4 -2
  33. package/translations/nl.json +4 -2
  34. package/translations/pt.json +4 -2
  35. package/translations/sk.json +4 -2
  36. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.css +0 -0
  37. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.html +0 -41
  38. package/src/libs/feature/map/src/lib/geocoding/geocoding.component.ts +0 -112
  39. package/src/libs/feature/map/src/lib/style/index.ts +0 -2
  40. package/src/libs/feature/map/src/lib/style/map-style.fixtures.ts +0 -47
  41. package/src/libs/feature/map/src/lib/style/map-style.service.ts +0 -108
@@ -6,7 +6,7 @@ import GeoJSON from 'ol/format/GeoJSON.js';
6
6
  import { parse as parse$1 } from 'ol/xml.js';
7
7
  import { format } from 'date-fns/format';
8
8
  import { Namespace, Literal, lit, parse as parse$2, sym, BlankNode, graph } from 'rdflib';
9
- import { lastValueFrom, fromEvent, startWith, map as map$2, shareReplay, filter, pairwise, of, switchMap, Subject, forkJoin, combineLatest, from, exhaustMap, throwError, takeLast, firstValueFrom, merge, BehaviorSubject, timer, ReplaySubject, Subscription, first, distinctUntilChanged as distinctUntilChanged$1, animationFrameScheduler, debounceTime as debounceTime$1, Observable, buffer, tap as tap$2, combineLatestWith, take as take$1, catchError as catchError$1, takeUntil, EMPTY, mergeMap as mergeMap$1, withLatestFrom as withLatestFrom$1 } from 'rxjs';
9
+ import { lastValueFrom, fromEvent, startWith, map as map$2, shareReplay, filter, pairwise, of, switchMap, Subject, forkJoin, combineLatest, from, exhaustMap, throwError, takeLast, firstValueFrom, merge, BehaviorSubject, timer, ReplaySubject, Subscription, first, distinctUntilChanged as distinctUntilChanged$1, animationFrameScheduler, debounceTime as debounceTime$1, Observable, buffer, tap as tap$2, combineLatestWith, take as take$1, catchError as catchError$1, EMPTY, mergeMap as mergeMap$1, withLatestFrom as withLatestFrom$1, takeUntil } from 'rxjs';
10
10
  import * as i0 from '@angular/core';
11
11
  import { InjectionToken, inject, Injectable, NgModule, Injector, provideAppInitializer, makeEnvironmentProviders, ElementRef, afterNextRender, booleanAttribute, Input, Directive, HostListener, Renderer2, DestroyRef, EventEmitter, Output, ViewChild, ChangeDetectionStrategy, Component, ViewEncapsulation, ChangeDetectorRef, HostBinding, ViewContainerRef, TemplateRef, ViewChildren, ContentChild, input, output, signal, viewChild, computed, ContentChildren, NgZone, ComponentFactoryResolver, viewChildren } from '@angular/core';
12
12
  import { HttpClient, HttpHeaders, HttpParams, HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi, HttpEventType } from '@angular/common/http';
@@ -26,7 +26,6 @@ import { getLength } from 'ol/sphere.js';
26
26
  import { LineString } from 'ol/geom.js';
27
27
  import * as i1 from '@ngrx/store';
28
28
  import { createAction, props, createReducer, on, createFeatureSelector, createSelector, Store, select, StoreModule } from '@ngrx/store';
29
- import { queryDataGouvFr, queryGeonames, queryGeoadmin } from '@geospatial-sdk/geocoding';
30
29
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
31
30
  import { FeaturesClickEventType, FeaturesHoverEventType, MapClickEventType, MapExtentChangeEventType, SourceLoadErrorType, computeMapContextDiff, createViewFromLayer } from '@geospatial-sdk/core';
32
31
  import { createMapFromContext, applyContextDiffToMap, listen } from '@geospatial-sdk/openlayers';
@@ -37,11 +36,8 @@ import { createLegendFromLayer } from '@geospatial-sdk/legend';
37
36
  import { mouseOnly, noModifierKeys, primaryAction, platformModifierKeyOnly } from 'ol/events/condition.js';
38
37
  import { defaults, DragPan, MouseWheelZoom } from 'ol/interaction.js';
39
38
  import { extend } from 'ol/extent.js';
40
- import * as TOML from '@ltd/j-toml';
41
- import { Style, Stroke, Fill, Circle } from 'ol/style.js';
42
- import CircleStyle from 'ol/style/Circle.js';
43
39
  import EmblaCarousel from 'embla-carousel';
44
- import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, iconoirTrash, iconoirSquareDashed, iconoirImport, iconoirCheckCircle, iconoirReduce, iconoirNavArrowUp, iconoirNavArrowDown, iconoirExpand, iconoirSettings, iconoirDownload, iconoirPlus, iconoirBin, iconoirMediaImageXmark, iconoirMediaImage, iconoirAppWindow, iconoirCode, iconoirDatabase, iconoirAppleWallet, iconoirBank, iconoirList, iconoirTranslate, iconoirLock, iconoirUser, iconoirArrowLeft, iconoirLightBulbOn, iconoirBadgeCheck, iconoirSystemShut, iconoirCircle, iconoirAttachment, iconoirRefresh } from '@ng-icons/iconoir';
40
+ import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, iconoirUpload, iconoirTrash, iconoirSquareDashed, iconoirCheckCircle, iconoirReduce, iconoirNavArrowUp, iconoirNavArrowDown, iconoirExpand, iconoirSettings, iconoirDownload, iconoirPlus, iconoirBin, iconoirMediaImageXmark, iconoirMediaImage, iconoirAppWindow, iconoirCode, iconoirDatabase, iconoirAppleWallet, iconoirBank, iconoirList, iconoirTranslate, iconoirLock, iconoirUser, iconoirArrowLeft, iconoirLightBulbOn, iconoirImport, iconoirBadgeCheck, iconoirSystemShut, iconoirCircle, iconoirAttachment, iconoirRefresh } from '@ng-icons/iconoir';
45
41
  import { MatButtonModule } from '@angular/material/button';
46
42
  import * as i1$7 from '@angular/cdk/overlay';
47
43
  import { ScrollStrategyOptions, OverlayModule, CdkConnectedOverlay, ScrollDispatcher, Overlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
@@ -74,6 +70,7 @@ import { MatTabsModule } from '@angular/material/tabs';
74
70
  import * as i2$2 from '@ngrx/effects';
75
71
  import { Actions, createEffect, ofType, EffectsModule } from '@ngrx/effects';
76
72
  import { valid as valid$1 } from 'geojson-validation';
73
+ import { queryGeoplateforme, queryGeonames, queryGeoadmin } from '@geospatial-sdk/geocoding';
77
74
  import { TemplatePortal } from '@angular/cdk/portal';
78
75
  import { parse as parse$3 } from 'marked';
79
76
  import * as i2$3 from '@angular/cdk/scrolling';
@@ -101,6 +98,7 @@ import { TextFieldModule } from '@angular/cdk/text-field';
101
98
  import * as i2$5 from '@ngrx/router-store';
102
99
  import { getRouterSelectors, routerReducer, StoreRouterConnectingModule, FullRouterStateSerializer } from '@ngrx/router-store';
103
100
  import { navigation } from '@ngrx/router-store/data-persistence';
101
+ import * as TOML from '@ltd/j-toml';
104
102
 
105
103
  class MetadataMapperContext {
106
104
  }
@@ -19596,6 +19594,19 @@ function isBoundingBox(value) {
19596
19594
  value.length === 4 &&
19597
19595
  value.every((item) => typeof item === 'number'));
19598
19596
  }
19597
+ /**
19598
+ * Checks that a bounding box's coordinates stay within the valid
19599
+ * longitude (-180/180) and latitude (-90/90) ranges.
19600
+ */
19601
+ function isBoundingBoxWithinWorldExtent(bbox) {
19602
+ const [minX, minY, maxX, maxY] = bbox;
19603
+ return (minX >= -180 &&
19604
+ maxX <= 180 &&
19605
+ minY >= -90 &&
19606
+ maxY <= 90 &&
19607
+ minX <= maxX &&
19608
+ minY <= maxY);
19609
+ }
19599
19610
  function getGeometryBoundingBox(geometry) {
19600
19611
  // use the bounding box if specified in the GeoJSON object
19601
19612
  if (geometry.bbox) {
@@ -20439,7 +20450,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
20439
20450
  }] } });
20440
20451
 
20441
20452
  var name = "geonetwork-ui";
20442
- var version = "2.11.0-dev.c42282af5";
20453
+ var version = "2.11.0-dev.cf22e64cf";
20443
20454
  var engines = {
20444
20455
  node: ">=24"
20445
20456
  };
@@ -20869,12 +20880,25 @@ class ElasticsearchService {
20869
20880
  }
20870
20881
  return Object.values(filters).find(isBoundingBox);
20871
20882
  }
20872
- // if a field registered min/max runtime fields, its dates form an interval
20873
- // the record matches if that interval intersects the filter range
20883
+ // builds a query matching records whose dates intersect the filter range
20874
20884
  buildDateRangeQuery(searchField, dateRange) {
20885
+ // fields ending with 'DateRange' maps as ES range type
20886
+ if (searchField.endsWith('DateRange')) {
20887
+ return {
20888
+ range: {
20889
+ [searchField]: {
20890
+ ...(dateRange.start && { gte: formatDate(dateRange.start) }),
20891
+ ...(dateRange.end && { lte: formatDate(dateRange.end) }),
20892
+ format: 'yyyy-MM-dd',
20893
+ relation: 'intersects',
20894
+ },
20895
+ },
20896
+ };
20897
+ }
20875
20898
  const minField = `${searchField}Min`;
20876
20899
  const maxField = `${searchField}Max`;
20877
20900
  if (minField in this.runtimeFields && maxField in this.runtimeFields) {
20901
+ // min/max runtime fields form an interval per record; match if it intersects the filter range
20878
20902
  const filter = [
20879
20903
  dateRange.start && {
20880
20904
  range: {
@@ -22615,48 +22639,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
22615
22639
  type: Injectable
22616
22640
  }] });
22617
22641
 
22618
- const GEOCODING_PROVIDER = new InjectionToken('geocoding-provider');
22619
- class GeocodingService {
22620
- constructor() {
22621
- this.provider = inject(GEOCODING_PROVIDER);
22622
- }
22623
- query(text) {
22624
- let queryObservable;
22625
- switch (this.provider[0]) {
22626
- case 'geoadmin':
22627
- queryObservable = from(queryGeoadmin(text, this.provider[1]));
22628
- break;
22629
- case 'geonames':
22630
- queryObservable = from(queryGeonames(text, this.provider[1]));
22631
- break;
22632
- case 'data-gouv-fr':
22633
- queryObservable = from(queryDataGouvFr(text, this.provider[1]));
22634
- break;
22635
- default:
22636
- return throwError(() => new Error(`Unsupported geocoding provider: ${this.provider[0]}`));
22637
- }
22638
- return queryObservable.pipe(catchError((error) => throwError(error)));
22639
- }
22640
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
22641
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, providedIn: 'root' }); }
22642
- }
22643
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, decorators: [{
22644
- type: Injectable,
22645
- args: [{
22646
- providedIn: 'root',
22647
- }]
22648
- }] });
22649
-
22650
22642
  class FeatureMapModule {
22651
22643
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
22652
22644
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, imports: [i1.StoreFeatureModule] }); }
22653
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, providers: [
22654
- MapFacade,
22655
- {
22656
- provide: GEOCODING_PROVIDER,
22657
- useValue: ['geonames', { maxRows: 5 }],
22658
- },
22659
- ], imports: [StoreModule.forFeature(MAP_FEATURE_KEY, mapReducer)] }); }
22645
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, providers: [MapFacade], imports: [StoreModule.forFeature(MAP_FEATURE_KEY, mapReducer)] }); }
22660
22646
  }
22661
22647
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, decorators: [{
22662
22648
  type: NgModule,
@@ -22664,13 +22650,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
22664
22650
  imports: [
22665
22651
  StoreModule.forFeature(MAP_FEATURE_KEY, mapReducer),
22666
22652
  ],
22667
- providers: [
22668
- MapFacade,
22669
- {
22670
- provide: GEOCODING_PROVIDER,
22671
- useValue: ['geonames', { maxRows: 5 }],
22672
- },
22673
- ],
22653
+ providers: [MapFacade],
22674
22654
  }]
22675
22655
  }] });
22676
22656
 
@@ -23113,1117 +23093,409 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
23113
23093
  }]
23114
23094
  }] });
23115
23095
 
23116
- const flatten = (base, obj, keepLevel = false) => Object.keys(obj).reduce((prev, curr) => {
23117
- const path = base ? `${base}.${curr}` : curr;
23118
- const val = obj[curr];
23119
- if (keepLevel) {
23120
- return { ...prev, [path]: flatten('', val) };
23096
+ class AnchorLinkDirective {
23097
+ constructor() {
23098
+ this.changeDetector = inject(ChangeDetectorRef);
23099
+ this.disabled = false;
23100
+ this.observer = new MutationObserver(() => {
23101
+ this.refreshDisabledState();
23102
+ });
23103
+ this.inView = false;
23104
+ this.initialized = false;
23121
23105
  }
23122
- else if (typeof val === 'object' && !Array.isArray(val)) {
23123
- return {
23124
- ...prev,
23125
- ...flatten(path, val),
23126
- };
23106
+ get elementClass() {
23107
+ if (this.disabled) {
23108
+ return this.disabledClass;
23109
+ }
23110
+ if (this.inView) {
23111
+ return `${this.inViewClass} ${this.enabledClass}`;
23112
+ }
23113
+ else {
23114
+ return `${this.outOfViewClass} ${this.enabledClass}`;
23115
+ }
23127
23116
  }
23128
- else {
23129
- return { ...prev, [path]: val };
23117
+ ngOnInit() {
23118
+ this.observer.observe(document.body, {
23119
+ childList: true,
23120
+ subtree: true,
23121
+ });
23122
+ this.refreshDisabledState();
23130
23123
  }
23131
- }, {});
23132
- const checkKeys = (input, mandatory, optional) => {
23133
- const keys = Object.keys(input);
23134
- const missing = mandatory.filter((key) => keys.indexOf(key) === -1);
23135
- const unrecognized = keys.filter((key) => mandatory.indexOf(key) === -1 && optional.indexOf(key) === -1);
23136
- return {
23137
- missing,
23138
- unrecognized,
23139
- };
23140
- };
23141
- /**
23142
- * Only keeps recognized keys, flatten nested values (to allow having "." in keys),
23143
- * pushes warnings and errors to the given arrays; returns null in case of error
23144
- */
23145
- function parseConfigSection(fullConfigObj, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors) {
23146
- if (typeof fullConfigObj[sectionName] !== 'object') {
23147
- if (mandatoryKeys.length === 0)
23148
- return null;
23149
- outErrors.push(`The [${sectionName}] mandatory section is missing.`);
23150
- return null;
23124
+ ngAfterViewChecked() {
23125
+ if (!this.initialized && !this.disabled) {
23126
+ const target = document.getElementById(this.targetId);
23127
+ if (target) {
23128
+ this.initializeIntersectionObserver(target);
23129
+ this.initialized = true;
23130
+ }
23131
+ }
23151
23132
  }
23152
- const sectionConf = fullConfigObj[sectionName];
23153
- const keysCheck = checkKeys(sectionConf, mandatoryKeys, optionalKeys);
23154
- if (keysCheck.missing.length) {
23155
- // note: this is not thrown to allow merging several Errors down the line
23156
- outErrors.push(`In the [${sectionName}] section: ${keysCheck.missing.join(', ')}`);
23157
- return null;
23133
+ initializeIntersectionObserver(target) {
23134
+ this.intersectionObserver = new IntersectionObserver((entries) => {
23135
+ entries.forEach((entry) => {
23136
+ this.inView = entry.isIntersecting;
23137
+ this.changeDetector.detectChanges();
23138
+ });
23139
+ }, {
23140
+ root: null,
23141
+ rootMargin: '-30% 0% -60% 0%',
23142
+ });
23143
+ this.intersectionObserver.observe(target);
23158
23144
  }
23159
- else if (keysCheck.unrecognized.length) {
23160
- outWarnings.push(`In the [${sectionName}] section: ${keysCheck.unrecognized.join(', ')}`);
23161
- keysCheck.unrecognized.forEach((key) => delete sectionConf[key]);
23145
+ ngOnDestroy() {
23146
+ this.observer.disconnect();
23147
+ if (this.intersectionObserver) {
23148
+ this.intersectionObserver.disconnect();
23149
+ }
23162
23150
  }
23163
- return sectionConf;
23151
+ refreshDisabledState() {
23152
+ const targetNotPresent = !document.getElementById(this.targetId);
23153
+ if (targetNotPresent !== this.disabled) {
23154
+ this.disabled = targetNotPresent;
23155
+ this.changeDetector.detectChanges();
23156
+ }
23157
+ }
23158
+ scrollToTarget() {
23159
+ const target = document.getElementById(this.targetId);
23160
+ if (!target)
23161
+ return;
23162
+ target.scrollIntoView({
23163
+ behavior: 'smooth',
23164
+ block: 'start',
23165
+ });
23166
+ }
23167
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AnchorLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
23168
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.19", type: AnchorLinkDirective, isStandalone: true, selector: "[gnUiAnchorLink]", inputs: { targetId: ["gnUiAnchorLink", "targetId"], disabledClass: ["gnUiAnchorLinkDisabledClass", "disabledClass"], enabledClass: ["gnUiAnchorLinkEnabledClass", "enabledClass"], inViewClass: ["gnUiAnchorLinkInViewClass", "inViewClass"], outOfViewClass: ["gnUiAnchorLinkOutOfViewClass", "outOfViewClass"] }, host: { listeners: { "click": "scrollToTarget()" }, properties: { "class": "this.elementClass" } }, ngImport: i0 }); }
23164
23169
  }
23165
- /**
23166
- * Same as parseConfigSection but keeps all keys, recognized or not
23167
- * Also the first level is the language code (e.g. 'en')
23168
- * This is optional
23169
- */
23170
- function parseTranslationsConfigSection(fullConfigObj, sectionName) {
23171
- if (typeof fullConfigObj[sectionName] !== 'object') {
23172
- return {};
23170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AnchorLinkDirective, decorators: [{
23171
+ type: Directive,
23172
+ args: [{
23173
+ selector: '[gnUiAnchorLink]',
23174
+ standalone: true,
23175
+ }]
23176
+ }], propDecorators: { targetId: [{
23177
+ type: Input,
23178
+ args: ['gnUiAnchorLink']
23179
+ }], disabledClass: [{
23180
+ type: Input,
23181
+ args: ['gnUiAnchorLinkDisabledClass']
23182
+ }], enabledClass: [{
23183
+ type: Input,
23184
+ args: ['gnUiAnchorLinkEnabledClass']
23185
+ }], inViewClass: [{
23186
+ type: Input,
23187
+ args: ['gnUiAnchorLinkInViewClass']
23188
+ }], outOfViewClass: [{
23189
+ type: Input,
23190
+ args: ['gnUiAnchorLinkOutOfViewClass']
23191
+ }], elementClass: [{
23192
+ type: HostBinding,
23193
+ args: ['class']
23194
+ }], scrollToTarget: [{
23195
+ type: HostListener,
23196
+ args: ['click']
23197
+ }] } });
23198
+
23199
+ class PaginationDotsComponent {
23200
+ constructor() {
23201
+ this.containerClass = '';
23173
23202
  }
23174
- return flatten('', fullConfigObj[sectionName], true);
23203
+ // 1-based
23204
+ get steps() {
23205
+ return Array.from({ length: this.listComponent.pagesCount }, (_, i) => i + 1);
23206
+ }
23207
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationDotsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23208
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: PaginationDotsComponent, isStandalone: true, selector: "gn-ui-pagination-dots", inputs: { listComponent: "listComponent", containerClass: "containerClass" }, ngImport: i0, template: "@if (listComponent.pagesCount > 1) {\n <div\n class=\"overflow-hidden flex flex-row justify-center gap-[14px] p-1\"\n [ngClass]=\"containerClass\"\n >\n @for (step of steps; track step) {\n <button\n type=\"button\"\n class=\"pagination-dot\"\n (click)=\"listComponent.goToPage(step)\"\n [ngClass]=\"\n listComponent.currentPage === step ? 'bg-primary' : 'bg-gray-400'\n \"\n ></button>\n }\n </div>\n}\n", styles: [".pagination-dot{width:6px;height:6px;border-radius:6px;position:relative;flex-shrink:0}.pagination-dot:after{content:\"\";position:absolute;left:-7px;top:-7px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], viewProviders: [
23209
+ provideIcons({
23210
+ iconoirNavArrowRight,
23211
+ iconoirNavArrowLeft,
23212
+ }),
23213
+ ] }); }
23175
23214
  }
23176
- /**
23177
- * Same as parseConfigSection but handles an array of configs; this is
23178
- * considered optional; returns null in case of error in at least one of
23179
- * the sections
23180
- */
23181
- function parseMultiConfigSection(fullConfigObj, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors) {
23182
- const sections = fullConfigObj[sectionName];
23183
- if (!sections) {
23184
- return [];
23215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationDotsComponent, decorators: [{
23216
+ type: Component,
23217
+ args: [{ selector: 'gn-ui-pagination-dots', standalone: true, imports: [CommonModule], viewProviders: [
23218
+ provideIcons({
23219
+ iconoirNavArrowRight,
23220
+ iconoirNavArrowLeft,
23221
+ }),
23222
+ ], template: "@if (listComponent.pagesCount > 1) {\n <div\n class=\"overflow-hidden flex flex-row justify-center gap-[14px] p-1\"\n [ngClass]=\"containerClass\"\n >\n @for (step of steps; track step) {\n <button\n type=\"button\"\n class=\"pagination-dot\"\n (click)=\"listComponent.goToPage(step)\"\n [ngClass]=\"\n listComponent.currentPage === step ? 'bg-primary' : 'bg-gray-400'\n \"\n ></button>\n }\n </div>\n}\n", styles: [".pagination-dot{width:6px;height:6px;border-radius:6px;position:relative;flex-shrink:0}.pagination-dot:after{content:\"\";position:absolute;left:-7px;top:-7px;width:20px;height:20px}\n"] }]
23223
+ }], propDecorators: { listComponent: [{
23224
+ type: Input
23225
+ }], containerClass: [{
23226
+ type: Input
23227
+ }] } });
23228
+
23229
+ class CarouselComponent {
23230
+ constructor() {
23231
+ this.changeDetector = inject(ChangeDetectorRef);
23232
+ this.containerClass = '';
23233
+ this.stepsContainerClass = 'w-full bottom-0 top-auto';
23234
+ this.currentStepChange = new EventEmitter();
23235
+ this.steps = [];
23236
+ this.currentStep = 0;
23237
+ this.refreshSteps = () => {
23238
+ this.steps = this.emblaApi.scrollSnapList();
23239
+ this.currentStep = this.emblaApi.selectedScrollSnap();
23240
+ this.currentStepChange.emit(this.currentStep);
23241
+ this.changeDetector.detectChanges();
23242
+ };
23185
23243
  }
23186
- if (!Array.isArray(sections)) {
23187
- outErrors.push(`Expected [[${sectionName}]] to be an array of sections.`);
23188
- return null;
23244
+ // Paginable API
23245
+ get isFirstPage() {
23246
+ return this.currentStep === 0;
23189
23247
  }
23190
- const result = sections.map((section) => parseConfigSection({ [sectionName]: section }, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors));
23191
- if (result.some((r) => r === null)) {
23192
- return null;
23248
+ get isLastPage() {
23249
+ return this.currentStep === this.steps.length - 1;
23193
23250
  }
23194
- return result;
23195
- }
23196
- function checkMetadataLanguage(parsedConfigSection, outWarnings) {
23197
- const lang2 = toLang2(parsedConfigSection.metadata_language.toLowerCase());
23198
- if (lang2?.length !== 2) {
23199
- outWarnings.push(`In the [global] section: metadata_language = "${parsedConfigSection.metadata_language}" is not a recognized ISO 639 language code`);
23251
+ get currentPage() {
23252
+ return this.currentStep + 1; // this is 1-based
23200
23253
  }
23201
- return parsedConfigSection;
23202
- }
23203
- function checkNewRecordDefaultLanguage(parsedConfigSection, outWarnings) {
23204
- const lang2 = toLang2(parsedConfigSection.new_record_default_language.toLowerCase());
23205
- if (!(lang2 in LANG_2_TO_3_MAPPER)) {
23206
- outWarnings.push(`In the [editing] section: new_record_default_language = "${parsedConfigSection.new_record_default_language}" is not a recognized ISO 639 language code`);
23207
- return {
23208
- ...parsedConfigSection,
23209
- new_record_default_language: undefined,
23210
- };
23254
+ get pagesCount() {
23255
+ return this.steps.length;
23211
23256
  }
23212
- return {
23213
- ...parsedConfigSection,
23214
- new_record_default_language: lang2,
23215
- };
23216
- }
23217
- function checkNewRecordStandard(parsedConfigSection, outWarnings) {
23218
- const standard = parsedConfigSection.new_record_standard;
23219
- const normalizedStandard = typeof standard === 'string' ? standard.trim().toLowerCase() : null;
23220
- if (normalizedStandard === 'iso19139' ||
23221
- normalizedStandard === 'iso19115-3') {
23222
- return {
23223
- ...parsedConfigSection,
23224
- new_record_standard: normalizedStandard,
23225
- };
23257
+ goToPage(stepIndex) {
23258
+ this.emblaApi.scrollTo(stepIndex - 1); // this is 0-based
23226
23259
  }
23227
- outWarnings.push(`In the [editing] section: new_record_standard = "${standard}" is not a supported metadata standard`);
23228
- return {
23229
- ...parsedConfigSection,
23230
- new_record_standard: undefined,
23231
- };
23260
+ goToPrevPage() {
23261
+ if (this.isFirstPage)
23262
+ return;
23263
+ this.emblaApi.scrollPrev();
23264
+ }
23265
+ goToNextPage() {
23266
+ if (this.isLastPage)
23267
+ return;
23268
+ this.emblaApi.scrollNext();
23269
+ }
23270
+ ngAfterViewInit() {
23271
+ this.emblaApi = EmblaCarousel(this.carouselOverflowContainer.nativeElement, {
23272
+ duration: 15,
23273
+ });
23274
+ this.emblaApi
23275
+ .on('init', this.refreshSteps)
23276
+ .on('reInit', this.refreshSteps)
23277
+ .on('select', this.refreshSteps);
23278
+ }
23279
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23280
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: CarouselComponent, isStandalone: true, selector: "gn-ui-carousel", inputs: { containerClass: "containerClass", stepsContainerClass: "stepsContainerClass" }, outputs: { currentStepChange: "currentStepChange" }, viewQueries: [{ propertyName: "carouselOverflowContainer", first: true, predicate: ["carouselOverflowContainer"], descendants: true }], ngImport: i0, template: "<div #carouselOverflowContainer class=\"w-full block\">\n <div class=\"carousel-container flex\" [ngClass]=\"containerClass\">\n <ng-content></ng-content>\n </div>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + stepsContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host{position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PaginationDotsComponent, selector: "gn-ui-pagination-dots", inputs: ["listComponent", "containerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
23232
23281
  }
23282
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CarouselComponent, decorators: [{
23283
+ type: Component,
23284
+ args: [{ selector: 'gn-ui-carousel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PaginationDotsComponent], template: "<div #carouselOverflowContainer class=\"w-full block\">\n <div class=\"carousel-container flex\" [ngClass]=\"containerClass\">\n <ng-content></ng-content>\n </div>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + stepsContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host{position:relative}\n"] }]
23285
+ }], propDecorators: { carouselOverflowContainer: [{
23286
+ type: ViewChild,
23287
+ args: ['carouselOverflowContainer']
23288
+ }], containerClass: [{
23289
+ type: Input
23290
+ }], stepsContainerClass: [{
23291
+ type: Input
23292
+ }], currentStepChange: [{
23293
+ type: Output
23294
+ }] } });
23233
23295
 
23234
- /**
23235
- * This loader extends the default one based on JSON files but also loads custom translations
23236
- * defined in the app configuration
23237
- * Implements a fallback on default lang if translated labels are empty
23238
- */
23239
- class FileWithOverridesTranslateLoader extends FileTranslateLoader {
23240
- getTranslation(lang) {
23241
- const baseLang = lang.substring(0, 2); // removing the right part of e.g. en_EN
23242
- return super.getTranslation(baseLang).pipe(map$1((translations) => ({
23243
- ...translations,
23244
- ...getCustomTranslations(baseLang),
23245
- })));
23296
+ class ProgressBarComponent {
23297
+ constructor() {
23298
+ this.value = 0;
23299
+ this.type = 'default';
23300
+ }
23301
+ get progress() {
23302
+ return this.value > 0 ? (this.value < 100 ? this.value : 100) : 0;
23303
+ }
23304
+ get color() {
23305
+ switch (this.type) {
23306
+ case 'default':
23307
+ return {
23308
+ outerBar: 'bg-gray-200',
23309
+ innerBar: 'bg-gray-100',
23310
+ text: 'text-gray-900',
23311
+ };
23312
+ case 'primary':
23313
+ return {
23314
+ outerBar: 'bg-primary',
23315
+ innerBar: 'bg-primary-lighter',
23316
+ text: 'text-white',
23317
+ };
23318
+ case 'secondary':
23319
+ return {
23320
+ outerBar: 'bg-secondary',
23321
+ innerBar: 'bg-secondary-lighter',
23322
+ text: 'text-white',
23323
+ };
23324
+ case 'light':
23325
+ return {
23326
+ outerBar: 'bg-primary-white',
23327
+ innerBar: 'bg-primary',
23328
+ text: 'text-main',
23329
+ };
23330
+ }
23246
23331
  }
23332
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23333
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ProgressBarComponent, isStandalone: true, selector: "gn-ui-progress-bar", inputs: { value: "value", type: "type" }, ngImport: i0, template: "@switch (type) {\n <!-- Light Theme -->\n @case ('light') {\n <div class=\"flex items-center relative\">\n <div\n class=\"flex-shrink-0 {{ color.text }} font-medium mr-2\n text-opacity-100 !text-slate-800\"\n data-cy=\"progressPercentage\"\n >\n {{ progress }}%\n </div>\n <div class=\"flex-grow h-[4px] w-[52px] {{ color.outerBar }} rounded-full\">\n <div\n [style.width.%]=\"progress\"\n class=\"{{ color.innerBar }} transition-width duration-500\n ease-in-out rounded-full shadow-sm w-[52px] h-[4px]\"\n ></div>\n </div>\n </div>\n }\n <!-- Default / Primary / Secondary Themes -->\n @default {\n <div class=\"flex h-full {{ color.outerBar }} rounded-t-lg rounded-b-lg\">\n <div\n [style.width.%]=\"progress\"\n class=\"flex {{ color.innerBar }} my-1 mx-1 transition-width\n duration-500 ease-in-out rounded-t-md rounded-b-md shadow-xl\"\n >\n <div\n class=\"flex items-center pl-2 py-1 {{ color.text }} font-bold text-4\"\n >\n {{ progress }}%\n </div>\n </div>\n </div>\n }\n}\n", styles: [".font-bold{font-weight:var(--progress-bar-font-weight, \"bold\")}\n"] }); }
23247
23334
  }
23335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ProgressBarComponent, decorators: [{
23336
+ type: Component,
23337
+ args: [{ selector: 'gn-ui-progress-bar', standalone: true, imports: [], template: "@switch (type) {\n <!-- Light Theme -->\n @case ('light') {\n <div class=\"flex items-center relative\">\n <div\n class=\"flex-shrink-0 {{ color.text }} font-medium mr-2\n text-opacity-100 !text-slate-800\"\n data-cy=\"progressPercentage\"\n >\n {{ progress }}%\n </div>\n <div class=\"flex-grow h-[4px] w-[52px] {{ color.outerBar }} rounded-full\">\n <div\n [style.width.%]=\"progress\"\n class=\"{{ color.innerBar }} transition-width duration-500\n ease-in-out rounded-full shadow-sm w-[52px] h-[4px]\"\n ></div>\n </div>\n </div>\n }\n <!-- Default / Primary / Secondary Themes -->\n @default {\n <div class=\"flex h-full {{ color.outerBar }} rounded-t-lg rounded-b-lg\">\n <div\n [style.width.%]=\"progress\"\n class=\"flex {{ color.innerBar }} my-1 mx-1 transition-width\n duration-500 ease-in-out rounded-t-md rounded-b-md shadow-xl\"\n >\n <div\n class=\"flex items-center pl-2 py-1 {{ color.text }} font-bold text-4\"\n >\n {{ progress }}%\n </div>\n </div>\n </div>\n }\n}\n", styles: [".font-bold{font-weight:var(--progress-bar-font-weight, \"bold\")}\n"] }]
23338
+ }], propDecorators: { value: [{
23339
+ type: Input
23340
+ }], type: [{
23341
+ type: Input
23342
+ }] } });
23248
23343
 
23249
- const MISSING_CONFIG_ERROR = `Application configuration was not initialized correctly.
23250
- This error might show up in case of an invalid/malformed configuration file.
23251
-
23252
- Note: make sure that you have called \`loadAppConfig\` from '../../../../../libs/util/app-config/src' before starting the Angular application.`;
23253
- let globalConfig = null;
23254
- function getGlobalConfig() {
23255
- if (globalConfig === null)
23256
- throw new Error(MISSING_CONFIG_ERROR);
23257
- return globalConfig;
23258
- }
23259
- let themeConfig = null;
23260
- function getThemeConfig() {
23261
- if (themeConfig === null)
23262
- throw new Error(MISSING_CONFIG_ERROR);
23263
- return themeConfig;
23264
- }
23265
- let mapConfig = null;
23266
- function getOptionalMapConfig() {
23267
- return mapConfig;
23268
- }
23269
- let searchConfig = null;
23270
- function getOptionalSearchConfig() {
23271
- return searchConfig;
23272
- }
23273
- let editorConfig = null;
23274
- function getOptionalEditorConfig() {
23275
- return editorConfig;
23276
- }
23277
- let metadataQualityConfig = null;
23278
- function getMetadataQualityConfig() {
23279
- return (metadataQualityConfig ||
23280
- {
23281
- ENABLED: false,
23344
+ class PopoverComponent {
23345
+ constructor() {
23346
+ this.viewContainerRef = inject(ViewContainerRef);
23347
+ this.renderer = inject(Renderer2);
23348
+ }
23349
+ getContent() {
23350
+ if (this.content instanceof TemplateRef) {
23351
+ if (this.view) {
23352
+ this.view.destroy();
23353
+ }
23354
+ this.view = this.viewContainerRef.createEmbeddedView(this.content);
23355
+ this.view.detectChanges();
23356
+ const wrapper = this.renderer.createElement('div'); // Create a wrapper div
23357
+ this.view.rootNodes.forEach((node) => {
23358
+ this.renderer.appendChild(wrapper, node); // Append each root node to the wrapper
23359
+ });
23360
+ return wrapper;
23361
+ }
23362
+ return this.content;
23363
+ }
23364
+ ngAfterViewInit() {
23365
+ this.tippyInstance = tippy(this.popoverContent.nativeElement, {
23366
+ content: this.getContent(),
23367
+ allowHTML: true,
23368
+ theme: this.theme,
23282
23369
  });
23283
- }
23284
- let customTranslations = null;
23285
- function getCustomTranslations(langCode) {
23286
- if (customTranslations === null)
23287
- throw new Error(MISSING_CONFIG_ERROR);
23288
- return langCode in customTranslations ? customTranslations[langCode] : {};
23289
- }
23290
- let appConfigLoaded = false;
23291
- function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
23292
- console.log(`[geonetwork-ui] Loading application configuration from ${configUrl}`);
23293
- return fetch(configUrl)
23294
- .then((resp) => {
23295
- if (!resp.ok)
23296
- throw new Error('Configuration file could not be loaded');
23297
- return resp.text();
23298
- })
23299
- .then((conf) => {
23300
- let parsed;
23301
- try {
23302
- parsed = TOML.parse(conf, { joiner: '\n', bigint: false });
23370
+ }
23371
+ ngOnChanges(changes) {
23372
+ if (changes['theme']) {
23373
+ this.theme = changes['theme'].currentValue;
23374
+ if (this.tippyInstance) {
23375
+ this.tippyInstance.setProps({ theme: this.theme });
23376
+ }
23303
23377
  }
23304
- catch (e) {
23305
- throw new Error(`An error occurred when parsing the configuration file: ${e.message}`);
23378
+ if (changes['content']) {
23379
+ this.content = changes['content'].currentValue;
23380
+ if (this.tippyInstance) {
23381
+ this.tippyInstance.setContent(this.getContent());
23382
+ }
23306
23383
  }
23307
- const errors = [];
23308
- const warnings = [];
23309
- let parsedGlobalSection = parseConfigSection(parsed, 'global', ['geonetwork4_api_url'], [
23310
- 'datahub_url',
23311
- 'edit_url_template',
23312
- 'proxy_path',
23313
- 'metadata_language',
23314
- 'login_url',
23315
- 'logout_url',
23316
- 'settings_url',
23317
- 'web_component_embedder_url',
23318
- 'languages',
23319
- 'contact_email',
23320
- 'reuse_form_url',
23321
- ], warnings, errors);
23322
- if (parsedGlobalSection?.metadata_language) {
23323
- parsedGlobalSection = checkMetadataLanguage(parsedGlobalSection, warnings);
23384
+ }
23385
+ ngOnDestroy() {
23386
+ if (this.tippyInstance) {
23387
+ this.tippyInstance.destroy();
23324
23388
  }
23325
- globalConfig =
23326
- parsedGlobalSection === null
23327
- ? null
23328
- : {
23329
- GN4_API_URL: parsedGlobalSection.geonetwork4_api_url,
23330
- DATAHUB_URL: parsedGlobalSection.datahub_url,
23331
- EDIT_URL_TEMPLATE: parsedGlobalSection.edit_url_template,
23332
- PROXY_PATH: parsedGlobalSection.proxy_path,
23333
- METADATA_LANGUAGE: parsedGlobalSection.metadata_language
23334
- ? parsedGlobalSection.metadata_language.toLowerCase()
23335
- : undefined,
23336
- LOGIN_URL: parsedGlobalSection.login_url,
23337
- LOGOUT_URL: parsedGlobalSection.logout_url,
23338
- SETTINGS_URL: parsedGlobalSection.settings_url,
23339
- WEB_COMPONENT_EMBEDDER_URL: parsedGlobalSection.web_component_embedder_url,
23340
- LANGUAGES: parsedGlobalSection.languages,
23341
- CONTACT_EMAIL: parsedGlobalSection.contact_email,
23342
- REUSE_FORM_URL: parsedGlobalSection.reuse_form_url,
23343
- };
23344
- const parsedLayersSections = parseMultiConfigSection(parsed, 'map_layer', ['type'], ['name', 'url', 'data', 'styleUrl', 'accessToken'], warnings, errors);
23345
- const parsedMapSection = parseConfigSection(parsed, 'map', [], [
23346
- 'max_zoom',
23347
- 'do_not_tile_wms',
23348
- 'max_extent',
23349
- 'max_feature_count',
23350
- 'baselayer',
23351
- 'do_not_use_default_basemap',
23352
- 'external_viewer_url_template',
23353
- 'external_viewer_open_new_tab',
23354
- ], warnings, errors);
23355
- mapConfig =
23356
- parsedMapSection === null || parsedLayersSections === null
23357
- ? null
23358
- : {
23359
- MAX_ZOOM: parsedMapSection.max_zoom,
23360
- DO_NOT_TILE_WMS: parsedMapSection.do_not_tile_wms,
23361
- MAX_EXTENT: parsedMapSection.max_extent,
23362
- MAX_FEATURE_COUNT: parsedMapSection.max_feature_count,
23363
- EXTERNAL_VIEWER_URL_TEMPLATE: parsedMapSection.external_viewer_url_template,
23364
- EXTERNAL_VIEWER_OPEN_NEW_TAB: parsedMapSection.external_viewer_open_new_tab,
23365
- DO_NOT_USE_DEFAULT_BASEMAP: !!parsedMapSection.do_not_use_default_basemap,
23366
- MAP_LAYERS: parsedLayersSections.map((map_layer) => ({
23367
- TYPE: map_layer.type,
23368
- URL: map_layer.url,
23369
- NAME: map_layer.name,
23370
- DATA: map_layer.data,
23371
- STYLE_URL: map_layer.styleUrl,
23372
- ACCESS_TOKEN: map_layer.accessToken,
23373
- })),
23374
- };
23375
- const parsedThemeSection = parseConfigSection(parsed, 'theme', ['primary_color', 'secondary_color', 'main_color', 'background_color'], [
23376
- 'header_foreground_color',
23377
- 'main_font',
23378
- 'title_font',
23379
- 'fonts_stylesheet_url',
23380
- 'thumbnail_placeholder',
23381
- 'header_background',
23382
- 'favicon',
23383
- ], warnings, errors);
23384
- themeConfig =
23385
- parsedThemeSection === null
23386
- ? null
23387
- : {
23388
- PRIMARY_COLOR: parsedThemeSection.primary_color,
23389
- SECONDARY_COLOR: parsedThemeSection.secondary_color,
23390
- MAIN_COLOR: parsedThemeSection.main_color,
23391
- BACKGROUND_COLOR: parsedThemeSection.background_color,
23392
- HEADER_FOREGROUND_COLOR: parsedThemeSection.header_foreground_color,
23393
- THUMBNAIL_PLACEHOLDER: parsedThemeSection.thumbnail_placeholder,
23394
- HEADER_BACKGROUND: parsedThemeSection.header_background,
23395
- TITLE_FONT: parsedThemeSection.title_font,
23396
- MAIN_FONT: parsedThemeSection.main_font,
23397
- FONTS_STYLESHEET_URL: parsedThemeSection.fonts_stylesheet_url,
23398
- FAVICON: parsedThemeSection.favicon,
23399
- };
23400
- const parsedSearchSection = parseConfigSection(parsed, 'search', [], [
23401
- 'record_kind_quick_filter',
23402
- 'filter_geometry_data',
23403
- 'filter_geometry_url',
23404
- 'do_not_use_default_search_preset',
23405
- 'search_preset',
23406
- 'advanced_filters',
23407
- 'limit',
23408
- 'spatial_extent_max_file_size',
23409
- ], warnings, errors);
23410
- const parsedSearchParams = parseMultiConfigSection(parsed, 'search_preset', ['name'], ['sort', 'filters'], warnings, errors);
23411
- searchConfig =
23412
- parsedSearchSection === null
23413
- ? null
23414
- : {
23415
- RECORD_KIND_QUICK_FILTER: parsedSearchSection.record_kind_quick_filter,
23416
- FILTER_GEOMETRY_DATA: parsedSearchSection.filter_geometry_data,
23417
- FILTER_GEOMETRY_URL: parsedSearchSection.filter_geometry_url,
23418
- DO_NOT_USE_DEFAULT_SEARCH_PRESET: !!parsedSearchSection.do_not_use_default_search_preset,
23419
- SEARCH_PRESET: parsedSearchParams.map((param) => ({
23420
- sort: param.sort,
23421
- name: param.name,
23422
- filters: param.filters,
23423
- })),
23424
- ADVANCED_FILTERS: parsedSearchSection.advanced_filters,
23425
- LIMIT: parsedSearchSection.limit,
23426
- SPATIAL_EXTENT_MAX_FILE_SIZE: parsedSearchSection.spatial_extent_max_file_size,
23427
- };
23428
- const parsedMetadataQualitySection = parseConfigSection(parsed, 'metadata-quality', [], ['enabled'], warnings, errors);
23429
- metadataQualityConfig =
23430
- parsedMetadataQualitySection === null
23431
- ? null
23432
- : {
23433
- ENABLED: parsedMetadataQualitySection.enabled,
23434
- SORTABLE: parsedMetadataQualitySection.sortable,
23435
- };
23436
- let parsedEditingSection = parseConfigSection(parsed, 'editing', [], ['new_record_default_language', 'new_record_standard'], warnings, errors);
23437
- if (parsedEditingSection !== null &&
23438
- parsedEditingSection.new_record_default_language !== undefined) {
23439
- parsedEditingSection = checkNewRecordDefaultLanguage(parsedEditingSection, warnings);
23440
- }
23441
- if (parsedEditingSection !== null &&
23442
- parsedEditingSection.new_record_standard !== undefined) {
23443
- parsedEditingSection = checkNewRecordStandard(parsedEditingSection, warnings);
23444
- }
23445
- editorConfig =
23446
- parsedEditingSection === null
23447
- ? null
23448
- : {
23449
- NEW_RECORD_DEFAULT_LANGUAGE: parsedEditingSection.new_record_default_language,
23450
- NEW_RECORD_STANDARD: parsedEditingSection.new_record_standard,
23451
- };
23452
- customTranslations = parseTranslationsConfigSection(parsed, 'translations');
23453
- if (errors.length) {
23454
- throw new Error(`One or more mandatory settings were missing from the configuration file.
23455
- ${errors.join('\n')}`);
23456
- }
23457
- else if (warnings.length) {
23458
- console.warn(`One or more unexpected settings were encountered in the configuration file.
23459
- ${warnings.join('\n')}`);
23389
+ if (this.view) {
23390
+ this.view.destroy();
23460
23391
  }
23461
- appConfigLoaded = true;
23462
- });
23463
- }
23464
- function isConfigLoaded() {
23465
- return appConfigLoaded;
23466
- }
23467
- function _reset() {
23468
- globalConfig = null;
23469
- themeConfig = null;
23470
- editorConfig = null;
23471
- customTranslations = null;
23392
+ }
23393
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23394
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: PopoverComponent, isStandalone: true, selector: "gn-ui-popover", inputs: { content: "content", theme: "theme" }, viewQueries: [{ propertyName: "popoverContent", first: true, predicate: ["popoverContent"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<span #popoverContent>\n <ng-content></ng-content>\n</span>\n", styles: [""] }); }
23472
23395
  }
23473
- const TRANSLATE_WITH_OVERRIDES_CONFIG = {
23474
- compiler: {
23475
- provide: TranslateCompiler,
23476
- useClass: TranslateMessageFormatCompiler,
23477
- },
23478
- loader: [
23479
- {
23480
- provide: TRANSLATE_HTTP_LOADER_CONFIG,
23481
- useValue: {
23482
- prefix: './assets/i18n/',
23483
- suffix: '.json',
23484
- },
23485
- },
23486
- {
23487
- provide: TranslateLoader,
23488
- useClass: FileWithOverridesTranslateLoader,
23489
- deps: [HttpClient, TRANSLATE_HTTP_LOADER_CONFIG],
23490
- },
23491
- ],
23492
- };
23493
-
23494
- const okAppConfigFixture = () => `
23495
- [global]
23496
- geonetwork4_api_url = "/geonetwork/srv/api"
23497
- proxy_path = "/proxy/?url="
23498
- metadata_language = "fre"
23499
- login_url = "/cas/login?service="
23500
- logout_url = "/geonetwork/signout"
23501
- settings_url = "/geonetwork/settings"
23502
- web_component_embedder_url = "/datahub/wc-embedder.html"
23503
-
23504
- [map]
23505
- max_zoom = 10
23506
- max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855]
23507
- do_not_use_default_basemap = false
23508
- external_viewer_url_template = 'https://example.com/myviewer?'
23509
- external_viewer_open_new_tab = true
23510
- [[map_layer]]
23511
- type = "wms"
23512
- url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
23513
- name = "masque_hdf_ign_carto_latin1"
23514
- [[map_layer]]
23515
- type = "wfs"
23516
- url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
23517
- name = "masque_hdf_ign_carto_latin1"
23518
-
23519
- [theme]
23520
- primary_color = "#093564"
23521
- secondary_color = "#c2e9dc"
23522
- main_color = "#212029" # All-purpose text color
23523
- background_color = "#fdfbff"
23524
- thumbnail_placeholder = 'assets/img/placeholder.svg'
23525
- header_background = 'teal'
23526
- header_foreground_color = "#872e2e"
23527
- main_font = 'sans-serif'
23528
- title_font = 'serif'
23529
- fonts_stylesheet_url = "https://fonts.googleapis.com/css2?family=Open+Sans"
23530
-
23531
- [search]
23532
- record_kind_quick_filter = false
23533
- filter_geometry_url = 'https://my.domain.org/geom.json'
23534
- do_not_use_default_search_preset = false
23535
- advanced_filters = ['publicationYear', 'documentStandard', 'inspireKeyword', 'topic', 'license']
23536
-
23537
- [[search_preset]]
23538
- sort = "-createDate"
23539
- name = 'filterByOrgs'
23540
- filters.q = 'Carto'
23541
- filters.organisation = ['Org1', 'Org2']
23542
- filters.format = ['ESRI Shapefile']
23543
- filters.topic = ['boundaries']
23544
- filters.publicationYear = ['2023', '2022']
23545
- filters.spatial = ['yes']
23546
-
23547
- [translations.en]
23548
- "my.first.key" = 'First label.'
23549
- "my.second.key" = """
23550
- Second label,
23551
- on two lines."""
23552
-
23553
- [translations.de]
23554
- my.first.key = 'Erste Etikett.'
23555
-
23556
- [translations.fr]
23557
- my.sample.text = "Un bon exemple de texte."
23558
- "my.quoted.text" = 'du texte entre guillements.'
23559
- `;
23560
- const appConfigWithTranslationFixture = () => okAppConfigFixture();
23561
- const minimalAppConfigFixture = () => `
23562
- [global]
23563
- geonetwork4_api_url = "/geonetwork/srv/api"
23564
- proxy_path = "/proxy/?url="
23396
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopoverComponent, decorators: [{
23397
+ type: Component,
23398
+ args: [{ selector: 'gn-ui-popover', standalone: true, imports: [], template: "<span #popoverContent>\n <ng-content></ng-content>\n</span>\n" }]
23399
+ }], propDecorators: { popoverContent: [{
23400
+ type: ViewChild,
23401
+ args: ['popoverContent', { static: false }]
23402
+ }], content: [{
23403
+ type: Input
23404
+ }], theme: [{
23405
+ type: Input
23406
+ }] } });
23565
23407
 
23566
- [theme]
23567
- primary_color = "#093564"
23568
- secondary_color = "#c2e9dc"
23569
- main_color = "#212029" # All-purpose text color
23570
- background_color = "#fdfbff"
23571
- `;
23572
- const mapConfigFixture = () => ({
23573
- MAX_ZOOM: 10,
23574
- MAX_EXTENT: [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855],
23575
- DO_NOT_USE_DEFAULT_BASEMAP: false,
23576
- DO_NOT_TILE_WMS: false,
23577
- EXTERNAL_VIEWER_URL_TEMPLATE: 'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["${layer_name}"],"sources":[{"url":"${service_url}","type":"${service_type}"}]}]',
23578
- EXTERNAL_VIEWER_OPEN_NEW_TAB: true,
23579
- MAP_LAYERS: [
23580
- {
23581
- TYPE: 'xyz',
23582
- URL: 'https://some-basemap-server',
23583
- },
23584
- {
23585
- TYPE: 'wms',
23586
- URL: 'https://some-wms-server',
23587
- NAME: 'some_layername',
23588
- },
23589
- {
23590
- TYPE: 'wfs',
23591
- URL: 'https://some-wfs-server',
23592
- NAME: 'some_layername',
23593
- },
23594
- ],
23595
- });
23596
- const malformedConfigFixture = () => `
23597
- {
23598
- "I thought": "we were still doing json"
23408
+ class LoadingMaskComponent {
23409
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LoadingMaskComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23410
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: LoadingMaskComponent, isStandalone: true, selector: "gn-ui-loading-mask", inputs: { message: "message" }, ngImport: i0, template: "<div class=\"h-full flex flex-col justify-center items-center relative backdrop\">\n <div class=\"absolute background bg-white inset-0\"></div>\n <mat-spinner [diameter]=\"28\" class=\"relative\"></mat-spinner>\n <span class=\"text-sm text-gray-700 mt-3 relative\">{{ message }}</span>\n</div>\n", styles: ["::ng-deep .mat-spinner circle{stroke:var(--color-gray-700);opacity:.5}.backdrop{background-color:#fff6}@supports (-webkit-backdrop-filter: blur()) or (backdrop-filter: blur()){.backdrop{background-color:transparent;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}}.background{opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
23599
23411
  }
23600
- `;
23601
- const missingMandatoryConfigFixture = () => `
23602
- [theme]
23603
- primary_color = "#093564"
23604
- secondary_color = "#c2e9dc"
23605
- background_color = "#fdfbff"
23606
- main_font = 'sans-serif'
23607
- `;
23608
- const wrongLanguageCodeConfigFixture = () => `
23609
- [global]
23610
- geonetwork4_api_url = "/geonetwork/srv/api"
23611
- proxy_path = "/proxy/?url="
23612
- metadata_language = "abc"
23613
-
23614
- [map]
23615
-
23616
- [theme]
23617
- primary_color = "#093564"
23618
- secondary_color = "#c2e9dc"
23619
- main_color = "#212029" # All-purpose text color
23620
- background_color = "#fdfbff"
23621
- `;
23622
- const unrecognizedKeysConfigFixture = () => `
23623
- [global]
23624
- geonetwork4_api_url = "/geonetwork/srv/api"
23625
- proxy_path = "/proxy/?url="
23626
- metadata_language = "fre"
23627
- another_path = '/whatever'
23628
-
23629
- [map]
23630
- max_zoom = 10
23631
- max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855]
23632
- do_not_use_default_basemap = false
23633
- external_viewer_url_template = 'https://example.com/myviewer?'
23634
- external_viewer_open_new_tab = true
23635
- another_zoom = 15
23636
- [[map_layer]]
23637
- type = "wms"
23638
- url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
23639
- name = "masque_hdf_ign_carto_latin1"
23640
- [[map_layer]]
23641
- type = "wfs"
23642
- url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
23643
- name = "masque_hdf_ign_carto_latin1"
23644
- another_layer = "wrong layer definition"
23645
-
23646
- [theme]
23647
- primary_color = "#093564"
23648
- secondary_color = "#c2e9dc"
23649
- main_color = "#212029" # All-purpose text color
23650
- background_color = "#fdfbff"
23651
- thumbnail_placeholder = 'assets/img/placeholder.svg'
23652
- header_background = 'teal'
23653
- header_foreground_color = "#872e2e"
23654
- main_font = 'sans-serif'
23655
- title_font = 'serif'
23656
- another_color = 'red'
23657
- `;
23412
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LoadingMaskComponent, decorators: [{
23413
+ type: Component,
23414
+ args: [{ selector: 'gn-ui-loading-mask', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatProgressSpinnerModule], standalone: true, template: "<div class=\"h-full flex flex-col justify-center items-center relative backdrop\">\n <div class=\"absolute background bg-white inset-0\"></div>\n <mat-spinner [diameter]=\"28\" class=\"relative\"></mat-spinner>\n <span class=\"text-sm text-gray-700 mt-3 relative\">{{ message }}</span>\n</div>\n", styles: ["::ng-deep .mat-spinner circle{stroke:var(--color-gray-700);opacity:.5}.backdrop{background-color:#fff6}@supports (-webkit-backdrop-filter: blur()) or (backdrop-filter: blur()){.backdrop{background-color:transparent;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}}.background{opacity:.7}\n"] }]
23415
+ }], propDecorators: { message: [{
23416
+ type: Input
23417
+ }] } });
23658
23418
 
23659
- function getMapContextLayerFromConfig(config) {
23660
- switch (config.TYPE) {
23661
- case 'wms':
23662
- return {
23663
- type: 'wms',
23664
- url: config.URL,
23665
- name: config.NAME,
23666
- };
23667
- case 'wfs':
23668
- return {
23669
- type: 'wfs',
23670
- url: config.URL,
23671
- featureType: config.NAME,
23672
- };
23673
- case 'xyz':
23674
- return {
23675
- type: config.TYPE,
23676
- url: config.URL,
23677
- };
23678
- case 'geojson':
23679
- return {
23680
- type: config.TYPE,
23681
- ...(config.DATA ? { data: config.DATA } : { url: config.URL }),
23682
- };
23683
- case 'maplibre-style':
23684
- return {
23685
- type: config.TYPE,
23686
- styleUrl: config.STYLE_URL,
23687
- accessToken: config.ACCESS_TOKEN,
23688
- };
23689
- }
23419
+ class ColorScaleComponent {
23420
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ColorScaleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23421
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: ColorScaleComponent, isStandalone: true, selector: "gn-ui-color-scale", ngImport: i0, template: "<div class=\"flex flex-row items-center\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">primary</div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-black\"\n title=\"primary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darkest\"\n title=\"primary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darker\"\n title=\"primary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary border-2 border-primary-darkest\"\n title=\"primary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lighter\"\n title=\"primary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lightest\"\n title=\"primary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-white\"\n title=\"primary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">\n secondary\n </div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-black\"\n title=\"secondary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darkest\"\n title=\"secondary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darker\"\n title=\"secondary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary border-2 border-secondary-darkest\"\n title=\"secondary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lighter\"\n title=\"secondary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lightest\"\n title=\"secondary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-white\"\n title=\"secondary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">main</div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-main\" title=\"main\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-900\" title=\"gray-900\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-800\" title=\"gray-800\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-700\" title=\"gray-700\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-600\" title=\"gray-600\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-500\" title=\"gray-500\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-400\" title=\"gray-400\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-300\" title=\"gray-300\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-200\" title=\"gray-200\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-100\" title=\"gray-100\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-50\" title=\"gray-50\"></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-background\"\n title=\"background\"\n ></div>\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32\">background</div>\n</div>\n", styles: [""] }); }
23690
23422
  }
23423
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ColorScaleComponent, decorators: [{
23424
+ type: Component,
23425
+ args: [{ selector: 'gn-ui-color-scale', standalone: true, template: "<div class=\"flex flex-row items-center\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">primary</div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-black\"\n title=\"primary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darkest\"\n title=\"primary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darker\"\n title=\"primary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary border-2 border-primary-darkest\"\n title=\"primary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lighter\"\n title=\"primary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lightest\"\n title=\"primary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-white\"\n title=\"primary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">\n secondary\n </div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-black\"\n title=\"secondary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darkest\"\n title=\"secondary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darker\"\n title=\"secondary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary border-2 border-secondary-darkest\"\n title=\"secondary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lighter\"\n title=\"secondary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lightest\"\n title=\"secondary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-white\"\n title=\"secondary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">main</div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-main\" title=\"main\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-900\" title=\"gray-900\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-800\" title=\"gray-800\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-700\" title=\"gray-700\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-600\" title=\"gray-600\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-500\" title=\"gray-500\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-400\" title=\"gray-400\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-300\" title=\"gray-300\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-200\" title=\"gray-200\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-100\" title=\"gray-100\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-50\" title=\"gray-50\"></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-background\"\n title=\"background\"\n ></div>\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32\">background</div>\n</div>\n" }]
23426
+ }] });
23691
23427
 
23692
- class MapStyleService {
23428
+ class PopupAlertComponent {
23693
23429
  constructor() {
23694
- this.styles = {
23695
- default: this.createStyleFunction(this.createGeometryStyles({
23696
- color: isConfigLoaded() ? getThemeConfig().PRIMARY_COLOR : 'blue',
23697
- })),
23698
- defaultHL: this.createStyleFunction(this.createGeometryStyles({
23699
- color: isConfigLoaded() ? getThemeConfig().SECONDARY_COLOR : 'red',
23700
- isFocused: true,
23701
- })),
23702
- };
23430
+ this.changeDetector = inject(ChangeDetectorRef);
23431
+ this.type = 'info';
23432
+ this.position = 'top';
23433
+ this.expanded = false;
23434
+ this.timeout = null;
23703
23435
  }
23704
- createGeometryStyles(options) {
23705
- const { color, isFocused } = options;
23706
- const zIndex = isFocused ? 10 : undefined;
23707
- return {
23708
- polygon: new Style({
23709
- fill: new Fill({
23710
- color: this.computeTransparentFillColor(color),
23711
- }),
23712
- stroke: new Stroke({
23713
- color: 'white',
23714
- width: 2,
23715
- }),
23716
- zIndex,
23717
- }),
23718
- point: new Style({
23719
- image: new CircleStyle({
23720
- fill: new Fill({
23721
- color,
23722
- }),
23723
- stroke: new Stroke({
23724
- color: 'white',
23725
- width: isFocused ? 3 : 2,
23726
- }),
23727
- radius: isFocused ? 8 : 7,
23728
- }),
23729
- zIndex,
23730
- }),
23731
- line: [
23732
- new Style({
23733
- stroke: new Stroke({
23734
- color: 'white',
23735
- width: isFocused ? 8 : 6,
23736
- }),
23737
- zIndex,
23738
- }),
23739
- new Style({
23740
- stroke: new Stroke({
23741
- color,
23742
- width: isFocused ? 3 : 2,
23743
- }),
23744
- zIndex,
23745
- }),
23746
- ],
23747
- };
23436
+ get showDuration() {
23437
+ const chars = this.content.nativeElement.innerHTML.length;
23438
+ return Math.max(3000, chars * 20);
23748
23439
  }
23749
- createStyleFunction(styleByGeometryType) {
23750
- return (feature) => {
23751
- const geometryType = feature?.getGeometry()?.getType();
23752
- switch (geometryType) {
23753
- case 'LinearRing':
23754
- case 'LineString':
23755
- case 'MultiLineString':
23756
- return styleByGeometryType.line;
23757
- case 'Point':
23758
- case 'MultiPoint':
23759
- return styleByGeometryType.point;
23760
- case 'Circle':
23761
- case 'Polygon':
23762
- case 'MultiPolygon':
23763
- return styleByGeometryType.polygon;
23764
- default:
23765
- return styleByGeometryType.point;
23766
- }
23767
- };
23440
+ ngOnInit() {
23441
+ this.expandAndClose();
23442
+ }
23443
+ expand() {
23444
+ this.expanded = true;
23445
+ this.changeDetector.detectChanges();
23446
+ clearTimeout(this.timeout);
23768
23447
  }
23769
- computeTransparentFillColor(color, alpha = 0.25) {
23770
- return chroma(color).alpha(alpha).css();
23448
+ expandAndClose() {
23449
+ this.expanded = true;
23450
+ this.changeDetector.detectChanges();
23451
+ clearTimeout(this.timeout);
23452
+ this.timeout = setTimeout(() => {
23453
+ this.expanded = false;
23454
+ this.changeDetector.detectChanges();
23455
+ }, this.showDuration);
23771
23456
  }
23772
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MapStyleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
23773
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MapStyleService, providedIn: 'root' }); }
23457
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopupAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23458
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: PopupAlertComponent, isStandalone: true, selector: "gn-ui-popup-alert", inputs: { icon: "icon", type: "type", position: "position" }, providers: [
23459
+ provideIcons({ matErrorOutlineOutline }),
23460
+ provideNgIconsConfig({
23461
+ size: '1.5em',
23462
+ }),
23463
+ ], viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "<div class=\"h-full relative container\">\n <div\n class=\"pointer-events-auto absolute text-white flex flex-row p-2 rounded message\"\n role=\"alert\"\n [ngClass]=\"{\n 'position-bottom': position === 'bottom',\n 'position-top': position === 'top',\n expanded: this.expanded,\n 'bg-red-500': type === 'danger',\n 'bg-yellow-500': type === 'warning',\n 'bg-blue-500': type === 'info',\n }\"\n (mouseenter)=\"expand()\"\n (mouseleave)=\"expandAndClose()\"\n >\n <ng-icon class=\"mr-2 shrink-0 select-none\" [name]=\"icon\"></ng-icon>\n <div class=\"grow\" #content [ngClass]=\"{ invisible: !expanded }\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{pointer-events:none}.container{filter:drop-shadow(0px 4px 3px rgba(0,0,0,.2))}.message{transition:clip-path .3s cubic-bezier(.25,.46,.45,.94)}.message.expanded{clip-path:circle(100%)}.position-top{clip-path:circle(19px at 20px 20px);align-items:start;top:0;left:0}.position-bottom{clip-path:circle(19px at 20px calc(100% - 20px));align-items:end;bottom:0;left:0}.container ::ng-deep a{text-decoration:underline;font-weight:700}.container ::ng-deep a:hover{opacity:.85}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
23774
23464
  }
23775
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MapStyleService, decorators: [{
23776
- type: Injectable,
23777
- args: [{
23778
- providedIn: 'root',
23779
- }]
23780
- }] });
23465
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopupAlertComponent, decorators: [{
23466
+ type: Component,
23467
+ args: [{ selector: 'gn-ui-popup-alert', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, NgIconComponent], providers: [
23468
+ provideIcons({ matErrorOutlineOutline }),
23469
+ provideNgIconsConfig({
23470
+ size: '1.5em',
23471
+ }),
23472
+ ], template: "<div class=\"h-full relative container\">\n <div\n class=\"pointer-events-auto absolute text-white flex flex-row p-2 rounded message\"\n role=\"alert\"\n [ngClass]=\"{\n 'position-bottom': position === 'bottom',\n 'position-top': position === 'top',\n expanded: this.expanded,\n 'bg-red-500': type === 'danger',\n 'bg-yellow-500': type === 'warning',\n 'bg-blue-500': type === 'info',\n }\"\n (mouseenter)=\"expand()\"\n (mouseleave)=\"expandAndClose()\"\n >\n <ng-icon class=\"mr-2 shrink-0 select-none\" [name]=\"icon\"></ng-icon>\n <div class=\"grow\" #content [ngClass]=\"{ invisible: !expanded }\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{pointer-events:none}.container{filter:drop-shadow(0px 4px 3px rgba(0,0,0,.2))}.message{transition:clip-path .3s cubic-bezier(.25,.46,.45,.94)}.message.expanded{clip-path:circle(100%)}.position-top{clip-path:circle(19px at 20px 20px);align-items:start;top:0;left:0}.position-bottom{clip-path:circle(19px at 20px calc(100% - 20px));align-items:end;bottom:0;left:0}.container ::ng-deep a{text-decoration:underline;font-weight:700}.container ::ng-deep a:hover{opacity:.85}\n"] }]
23473
+ }], propDecorators: { icon: [{
23474
+ type: Input
23475
+ }], type: [{
23476
+ type: Input
23477
+ }], position: [{
23478
+ type: Input
23479
+ }], content: [{
23480
+ type: ViewChild,
23481
+ args: ['content']
23482
+ }] } });
23781
23483
 
23782
- const colorPrimary = 'blue';
23783
- const colorSecondary = 'red';
23784
- const colorStroke = 'white';
23785
- const defaultMapStyleFixture = () => new Style({
23786
- image: new Circle({
23787
- fill: new Fill({
23788
- color: colorPrimary,
23789
- }),
23790
- stroke: new Stroke({
23791
- color: colorStroke,
23792
- width: 2,
23793
- }),
23794
- radius: 5,
23795
- }),
23796
- fill: new Fill({
23797
- color: 'rgba(0,0,255,0.25)',
23798
- }),
23799
- stroke: new Stroke({
23800
- color: colorStroke,
23801
- width: 2,
23802
- }),
23803
- });
23804
- const defaultMapStyleHlFixture = () => new Style({
23805
- image: new Circle({
23806
- fill: new Fill({
23807
- color: colorSecondary,
23808
- }),
23809
- stroke: new Stroke({
23810
- color: colorStroke,
23811
- width: 3,
23812
- }),
23813
- radius: 6,
23814
- }),
23815
- fill: new Fill({
23816
- color: 'rgba(255,0,0,0.25)',
23817
- }),
23818
- stroke: new Stroke({
23819
- color: colorSecondary,
23820
- width: 3,
23821
- }),
23822
- });
23484
+ class SpinningLoaderComponent {
23485
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpinningLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23486
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: SpinningLoaderComponent, isStandalone: true, selector: "gn-ui-spinning-loader", ngImport: i0, template: "<span>\n <svg\n class=\"animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</span>\n", styles: [""] }); }
23487
+ }
23488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpinningLoaderComponent, decorators: [{
23489
+ type: Component,
23490
+ args: [{ selector: 'gn-ui-spinning-loader', standalone: true, template: "<span>\n <svg\n class=\"animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</span>\n" }]
23491
+ }] });
23823
23492
 
23824
- class AnchorLinkDirective {
23493
+ class ButtonComponent {
23825
23494
  constructor() {
23826
- this.changeDetector = inject(ChangeDetectorRef);
23495
+ this.btnClass = 'gn-ui-btn-default';
23827
23496
  this.disabled = false;
23828
- this.observer = new MutationObserver(() => {
23829
- this.refreshDisabledState();
23830
- });
23831
- this.inView = false;
23832
- this.initialized = false;
23833
- }
23834
- get elementClass() {
23835
- if (this.disabled) {
23836
- return this.disabledClass;
23837
- }
23838
- if (this.inView) {
23839
- return `${this.inViewClass} ${this.enabledClass}`;
23840
- }
23841
- else {
23842
- return `${this.outOfViewClass} ${this.enabledClass}`;
23843
- }
23844
- }
23845
- ngOnInit() {
23846
- this.observer.observe(document.body, {
23847
- childList: true,
23848
- subtree: true,
23849
- });
23850
- this.refreshDisabledState();
23851
- }
23852
- ngAfterViewChecked() {
23853
- if (!this.initialized && !this.disabled) {
23854
- const target = document.getElementById(this.targetId);
23855
- if (target) {
23856
- this.initializeIntersectionObserver(target);
23857
- this.initialized = true;
23858
- }
23859
- }
23860
- }
23861
- initializeIntersectionObserver(target) {
23862
- this.intersectionObserver = new IntersectionObserver((entries) => {
23863
- entries.forEach((entry) => {
23864
- this.inView = entry.isIntersecting;
23865
- this.changeDetector.detectChanges();
23866
- });
23867
- }, {
23868
- root: null,
23869
- rootMargin: '-30% 0% -60% 0%',
23870
- });
23871
- this.intersectionObserver.observe(target);
23872
- }
23873
- ngOnDestroy() {
23874
- this.observer.disconnect();
23875
- if (this.intersectionObserver) {
23876
- this.intersectionObserver.disconnect();
23877
- }
23878
- }
23879
- refreshDisabledState() {
23880
- const targetNotPresent = !document.getElementById(this.targetId);
23881
- if (targetNotPresent !== this.disabled) {
23882
- this.disabled = targetNotPresent;
23883
- this.changeDetector.detectChanges();
23884
- }
23885
- }
23886
- scrollToTarget() {
23887
- const target = document.getElementById(this.targetId);
23888
- if (!target)
23889
- return;
23890
- target.scrollIntoView({
23891
- behavior: 'smooth',
23892
- block: 'start',
23893
- });
23894
- }
23895
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AnchorLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
23896
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.19", type: AnchorLinkDirective, isStandalone: true, selector: "[gnUiAnchorLink]", inputs: { targetId: ["gnUiAnchorLink", "targetId"], disabledClass: ["gnUiAnchorLinkDisabledClass", "disabledClass"], enabledClass: ["gnUiAnchorLinkEnabledClass", "enabledClass"], inViewClass: ["gnUiAnchorLinkInViewClass", "inViewClass"], outOfViewClass: ["gnUiAnchorLinkOutOfViewClass", "outOfViewClass"] }, host: { listeners: { "click": "scrollToTarget()" }, properties: { "class": "this.elementClass" } }, ngImport: i0 }); }
23897
- }
23898
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AnchorLinkDirective, decorators: [{
23899
- type: Directive,
23900
- args: [{
23901
- selector: '[gnUiAnchorLink]',
23902
- standalone: true,
23903
- }]
23904
- }], propDecorators: { targetId: [{
23905
- type: Input,
23906
- args: ['gnUiAnchorLink']
23907
- }], disabledClass: [{
23908
- type: Input,
23909
- args: ['gnUiAnchorLinkDisabledClass']
23910
- }], enabledClass: [{
23911
- type: Input,
23912
- args: ['gnUiAnchorLinkEnabledClass']
23913
- }], inViewClass: [{
23914
- type: Input,
23915
- args: ['gnUiAnchorLinkInViewClass']
23916
- }], outOfViewClass: [{
23917
- type: Input,
23918
- args: ['gnUiAnchorLinkOutOfViewClass']
23919
- }], elementClass: [{
23920
- type: HostBinding,
23921
- args: ['class']
23922
- }], scrollToTarget: [{
23923
- type: HostListener,
23924
- args: ['click']
23925
- }] } });
23926
-
23927
- class PaginationDotsComponent {
23928
- constructor() {
23929
- this.containerClass = '';
23930
- }
23931
- // 1-based
23932
- get steps() {
23933
- return Array.from({ length: this.listComponent.pagesCount }, (_, i) => i + 1);
23934
- }
23935
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationDotsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
23936
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: PaginationDotsComponent, isStandalone: true, selector: "gn-ui-pagination-dots", inputs: { listComponent: "listComponent", containerClass: "containerClass" }, ngImport: i0, template: "@if (listComponent.pagesCount > 1) {\n <div\n class=\"overflow-hidden flex flex-row justify-center gap-[14px] p-1\"\n [ngClass]=\"containerClass\"\n >\n @for (step of steps; track step) {\n <button\n type=\"button\"\n class=\"pagination-dot\"\n (click)=\"listComponent.goToPage(step)\"\n [ngClass]=\"\n listComponent.currentPage === step ? 'bg-primary' : 'bg-gray-400'\n \"\n ></button>\n }\n </div>\n}\n", styles: [".pagination-dot{width:6px;height:6px;border-radius:6px;position:relative;flex-shrink:0}.pagination-dot:after{content:\"\";position:absolute;left:-7px;top:-7px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], viewProviders: [
23937
- provideIcons({
23938
- iconoirNavArrowRight,
23939
- iconoirNavArrowLeft,
23940
- }),
23941
- ] }); }
23942
- }
23943
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationDotsComponent, decorators: [{
23944
- type: Component,
23945
- args: [{ selector: 'gn-ui-pagination-dots', standalone: true, imports: [CommonModule], viewProviders: [
23946
- provideIcons({
23947
- iconoirNavArrowRight,
23948
- iconoirNavArrowLeft,
23949
- }),
23950
- ], template: "@if (listComponent.pagesCount > 1) {\n <div\n class=\"overflow-hidden flex flex-row justify-center gap-[14px] p-1\"\n [ngClass]=\"containerClass\"\n >\n @for (step of steps; track step) {\n <button\n type=\"button\"\n class=\"pagination-dot\"\n (click)=\"listComponent.goToPage(step)\"\n [ngClass]=\"\n listComponent.currentPage === step ? 'bg-primary' : 'bg-gray-400'\n \"\n ></button>\n }\n </div>\n}\n", styles: [".pagination-dot{width:6px;height:6px;border-radius:6px;position:relative;flex-shrink:0}.pagination-dot:after{content:\"\";position:absolute;left:-7px;top:-7px;width:20px;height:20px}\n"] }]
23951
- }], propDecorators: { listComponent: [{
23952
- type: Input
23953
- }], containerClass: [{
23954
- type: Input
23955
- }] } });
23956
-
23957
- class CarouselComponent {
23958
- constructor() {
23959
- this.changeDetector = inject(ChangeDetectorRef);
23960
- this.containerClass = '';
23961
- this.stepsContainerClass = 'w-full bottom-0 top-auto';
23962
- this.currentStepChange = new EventEmitter();
23963
- this.steps = [];
23964
- this.currentStep = 0;
23965
- this.refreshSteps = () => {
23966
- this.steps = this.emblaApi.scrollSnapList();
23967
- this.currentStep = this.emblaApi.selectedScrollSnap();
23968
- this.currentStepChange.emit(this.currentStep);
23969
- this.changeDetector.detectChanges();
23970
- };
23971
- }
23972
- // Paginable API
23973
- get isFirstPage() {
23974
- return this.currentStep === 0;
23975
- }
23976
- get isLastPage() {
23977
- return this.currentStep === this.steps.length - 1;
23978
- }
23979
- get currentPage() {
23980
- return this.currentStep + 1; // this is 1-based
23981
- }
23982
- get pagesCount() {
23983
- return this.steps.length;
23984
- }
23985
- goToPage(stepIndex) {
23986
- this.emblaApi.scrollTo(stepIndex - 1); // this is 0-based
23987
- }
23988
- goToPrevPage() {
23989
- if (this.isFirstPage)
23990
- return;
23991
- this.emblaApi.scrollPrev();
23992
- }
23993
- goToNextPage() {
23994
- if (this.isLastPage)
23995
- return;
23996
- this.emblaApi.scrollNext();
23997
- }
23998
- ngAfterViewInit() {
23999
- this.emblaApi = EmblaCarousel(this.carouselOverflowContainer.nativeElement, {
24000
- duration: 15,
24001
- });
24002
- this.emblaApi
24003
- .on('init', this.refreshSteps)
24004
- .on('reInit', this.refreshSteps)
24005
- .on('select', this.refreshSteps);
24006
- }
24007
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24008
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: CarouselComponent, isStandalone: true, selector: "gn-ui-carousel", inputs: { containerClass: "containerClass", stepsContainerClass: "stepsContainerClass" }, outputs: { currentStepChange: "currentStepChange" }, viewQueries: [{ propertyName: "carouselOverflowContainer", first: true, predicate: ["carouselOverflowContainer"], descendants: true }], ngImport: i0, template: "<div #carouselOverflowContainer class=\"w-full block\">\n <div class=\"carousel-container flex\" [ngClass]=\"containerClass\">\n <ng-content></ng-content>\n </div>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + stepsContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host{position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PaginationDotsComponent, selector: "gn-ui-pagination-dots", inputs: ["listComponent", "containerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
24009
- }
24010
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CarouselComponent, decorators: [{
24011
- type: Component,
24012
- args: [{ selector: 'gn-ui-carousel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PaginationDotsComponent], template: "<div #carouselOverflowContainer class=\"w-full block\">\n <div class=\"carousel-container flex\" [ngClass]=\"containerClass\">\n <ng-content></ng-content>\n </div>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + stepsContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host{position:relative}\n"] }]
24013
- }], propDecorators: { carouselOverflowContainer: [{
24014
- type: ViewChild,
24015
- args: ['carouselOverflowContainer']
24016
- }], containerClass: [{
24017
- type: Input
24018
- }], stepsContainerClass: [{
24019
- type: Input
24020
- }], currentStepChange: [{
24021
- type: Output
24022
- }] } });
24023
-
24024
- class ProgressBarComponent {
24025
- constructor() {
24026
- this.value = 0;
24027
- this.type = 'default';
24028
- }
24029
- get progress() {
24030
- return this.value > 0 ? (this.value < 100 ? this.value : 100) : 0;
24031
- }
24032
- get color() {
24033
- switch (this.type) {
24034
- case 'default':
24035
- return {
24036
- outerBar: 'bg-gray-200',
24037
- innerBar: 'bg-gray-100',
24038
- text: 'text-gray-900',
24039
- };
24040
- case 'primary':
24041
- return {
24042
- outerBar: 'bg-primary',
24043
- innerBar: 'bg-primary-lighter',
24044
- text: 'text-white',
24045
- };
24046
- case 'secondary':
24047
- return {
24048
- outerBar: 'bg-secondary',
24049
- innerBar: 'bg-secondary-lighter',
24050
- text: 'text-white',
24051
- };
24052
- case 'light':
24053
- return {
24054
- outerBar: 'bg-primary-white',
24055
- innerBar: 'bg-primary',
24056
- text: 'text-main',
24057
- };
24058
- }
24059
- }
24060
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24061
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ProgressBarComponent, isStandalone: true, selector: "gn-ui-progress-bar", inputs: { value: "value", type: "type" }, ngImport: i0, template: "@switch (type) {\n <!-- Light Theme -->\n @case ('light') {\n <div class=\"flex items-center relative\">\n <div\n class=\"flex-shrink-0 {{ color.text }} font-medium mr-2\n text-opacity-100 !text-slate-800\"\n data-cy=\"progressPercentage\"\n >\n {{ progress }}%\n </div>\n <div class=\"flex-grow h-[4px] w-[52px] {{ color.outerBar }} rounded-full\">\n <div\n [style.width.%]=\"progress\"\n class=\"{{ color.innerBar }} transition-width duration-500\n ease-in-out rounded-full shadow-sm w-[52px] h-[4px]\"\n ></div>\n </div>\n </div>\n }\n <!-- Default / Primary / Secondary Themes -->\n @default {\n <div class=\"flex h-full {{ color.outerBar }} rounded-t-lg rounded-b-lg\">\n <div\n [style.width.%]=\"progress\"\n class=\"flex {{ color.innerBar }} my-1 mx-1 transition-width\n duration-500 ease-in-out rounded-t-md rounded-b-md shadow-xl\"\n >\n <div\n class=\"flex items-center pl-2 py-1 {{ color.text }} font-bold text-4\"\n >\n {{ progress }}%\n </div>\n </div>\n </div>\n }\n}\n", styles: [".font-bold{font-weight:var(--progress-bar-font-weight, \"bold\")}\n"] }); }
24062
- }
24063
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ProgressBarComponent, decorators: [{
24064
- type: Component,
24065
- args: [{ selector: 'gn-ui-progress-bar', standalone: true, imports: [], template: "@switch (type) {\n <!-- Light Theme -->\n @case ('light') {\n <div class=\"flex items-center relative\">\n <div\n class=\"flex-shrink-0 {{ color.text }} font-medium mr-2\n text-opacity-100 !text-slate-800\"\n data-cy=\"progressPercentage\"\n >\n {{ progress }}%\n </div>\n <div class=\"flex-grow h-[4px] w-[52px] {{ color.outerBar }} rounded-full\">\n <div\n [style.width.%]=\"progress\"\n class=\"{{ color.innerBar }} transition-width duration-500\n ease-in-out rounded-full shadow-sm w-[52px] h-[4px]\"\n ></div>\n </div>\n </div>\n }\n <!-- Default / Primary / Secondary Themes -->\n @default {\n <div class=\"flex h-full {{ color.outerBar }} rounded-t-lg rounded-b-lg\">\n <div\n [style.width.%]=\"progress\"\n class=\"flex {{ color.innerBar }} my-1 mx-1 transition-width\n duration-500 ease-in-out rounded-t-md rounded-b-md shadow-xl\"\n >\n <div\n class=\"flex items-center pl-2 py-1 {{ color.text }} font-bold text-4\"\n >\n {{ progress }}%\n </div>\n </div>\n </div>\n }\n}\n", styles: [".font-bold{font-weight:var(--progress-bar-font-weight, \"bold\")}\n"] }]
24066
- }], propDecorators: { value: [{
24067
- type: Input
24068
- }], type: [{
24069
- type: Input
24070
- }] } });
24071
-
24072
- class PopoverComponent {
24073
- constructor() {
24074
- this.viewContainerRef = inject(ViewContainerRef);
24075
- this.renderer = inject(Renderer2);
24076
- }
24077
- getContent() {
24078
- if (this.content instanceof TemplateRef) {
24079
- if (this.view) {
24080
- this.view.destroy();
24081
- }
24082
- this.view = this.viewContainerRef.createEmbeddedView(this.content);
24083
- this.view.detectChanges();
24084
- const wrapper = this.renderer.createElement('div'); // Create a wrapper div
24085
- this.view.rootNodes.forEach((node) => {
24086
- this.renderer.appendChild(wrapper, node); // Append each root node to the wrapper
24087
- });
24088
- return wrapper;
24089
- }
24090
- return this.content;
24091
- }
24092
- ngAfterViewInit() {
24093
- this.tippyInstance = tippy(this.popoverContent.nativeElement, {
24094
- content: this.getContent(),
24095
- allowHTML: true,
24096
- theme: this.theme,
24097
- });
24098
- }
24099
- ngOnChanges(changes) {
24100
- if (changes['theme']) {
24101
- this.theme = changes['theme'].currentValue;
24102
- if (this.tippyInstance) {
24103
- this.tippyInstance.setProps({ theme: this.theme });
24104
- }
24105
- }
24106
- if (changes['content']) {
24107
- this.content = changes['content'].currentValue;
24108
- if (this.tippyInstance) {
24109
- this.tippyInstance.setContent(this.getContent());
24110
- }
24111
- }
24112
- }
24113
- ngOnDestroy() {
24114
- if (this.tippyInstance) {
24115
- this.tippyInstance.destroy();
24116
- }
24117
- if (this.view) {
24118
- this.view.destroy();
24119
- }
24120
- }
24121
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24122
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: PopoverComponent, isStandalone: true, selector: "gn-ui-popover", inputs: { content: "content", theme: "theme" }, viewQueries: [{ propertyName: "popoverContent", first: true, predicate: ["popoverContent"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<span #popoverContent>\n <ng-content></ng-content>\n</span>\n", styles: [""] }); }
24123
- }
24124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopoverComponent, decorators: [{
24125
- type: Component,
24126
- args: [{ selector: 'gn-ui-popover', standalone: true, imports: [], template: "<span #popoverContent>\n <ng-content></ng-content>\n</span>\n" }]
24127
- }], propDecorators: { popoverContent: [{
24128
- type: ViewChild,
24129
- args: ['popoverContent', { static: false }]
24130
- }], content: [{
24131
- type: Input
24132
- }], theme: [{
24133
- type: Input
24134
- }] } });
24135
-
24136
- class LoadingMaskComponent {
24137
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LoadingMaskComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24138
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: LoadingMaskComponent, isStandalone: true, selector: "gn-ui-loading-mask", inputs: { message: "message" }, ngImport: i0, template: "<div class=\"h-full flex flex-col justify-center items-center relative backdrop\">\n <div class=\"absolute background bg-white inset-0\"></div>\n <mat-spinner [diameter]=\"28\" class=\"relative\"></mat-spinner>\n <span class=\"text-sm text-gray-700 mt-3 relative\">{{ message }}</span>\n</div>\n", styles: ["::ng-deep .mat-spinner circle{stroke:var(--color-gray-700);opacity:.5}.backdrop{background-color:#fff6}@supports (-webkit-backdrop-filter: blur()) or (backdrop-filter: blur()){.backdrop{background-color:transparent;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}}.background{opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
24139
- }
24140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LoadingMaskComponent, decorators: [{
24141
- type: Component,
24142
- args: [{ selector: 'gn-ui-loading-mask', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatProgressSpinnerModule], standalone: true, template: "<div class=\"h-full flex flex-col justify-center items-center relative backdrop\">\n <div class=\"absolute background bg-white inset-0\"></div>\n <mat-spinner [diameter]=\"28\" class=\"relative\"></mat-spinner>\n <span class=\"text-sm text-gray-700 mt-3 relative\">{{ message }}</span>\n</div>\n", styles: ["::ng-deep .mat-spinner circle{stroke:var(--color-gray-700);opacity:.5}.backdrop{background-color:#fff6}@supports (-webkit-backdrop-filter: blur()) or (backdrop-filter: blur()){.backdrop{background-color:transparent;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}}.background{opacity:.7}\n"] }]
24143
- }], propDecorators: { message: [{
24144
- type: Input
24145
- }] } });
24146
-
24147
- class ColorScaleComponent {
24148
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ColorScaleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24149
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: ColorScaleComponent, isStandalone: true, selector: "gn-ui-color-scale", ngImport: i0, template: "<div class=\"flex flex-row items-center\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">primary</div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-black\"\n title=\"primary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darkest\"\n title=\"primary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darker\"\n title=\"primary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary border-2 border-primary-darkest\"\n title=\"primary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lighter\"\n title=\"primary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lightest\"\n title=\"primary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-white\"\n title=\"primary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">\n secondary\n </div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-black\"\n title=\"secondary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darkest\"\n title=\"secondary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darker\"\n title=\"secondary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary border-2 border-secondary-darkest\"\n title=\"secondary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lighter\"\n title=\"secondary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lightest\"\n title=\"secondary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-white\"\n title=\"secondary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">main</div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-main\" title=\"main\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-900\" title=\"gray-900\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-800\" title=\"gray-800\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-700\" title=\"gray-700\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-600\" title=\"gray-600\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-500\" title=\"gray-500\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-400\" title=\"gray-400\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-300\" title=\"gray-300\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-200\" title=\"gray-200\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-100\" title=\"gray-100\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-50\" title=\"gray-50\"></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-background\"\n title=\"background\"\n ></div>\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32\">background</div>\n</div>\n", styles: [""] }); }
24150
- }
24151
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ColorScaleComponent, decorators: [{
24152
- type: Component,
24153
- args: [{ selector: 'gn-ui-color-scale', standalone: true, template: "<div class=\"flex flex-row items-center\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">primary</div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-black\"\n title=\"primary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darkest\"\n title=\"primary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-darker\"\n title=\"primary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary border-2 border-primary-darkest\"\n title=\"primary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lighter\"\n title=\"primary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-lightest\"\n title=\"primary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-primary-white\"\n title=\"primary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">\n secondary\n </div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-black\"\n title=\"secondary-black\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darkest\"\n title=\"secondary-darkest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-darker\"\n title=\"secondary-darker\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary border-2 border-secondary-darkest\"\n title=\"secondary\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lighter\"\n title=\"secondary-lighter\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-lightest\"\n title=\"secondary-lightest\"\n ></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-secondary-white\"\n title=\"secondary-white\"\n ></div>\n</div>\n<div class=\"flex flex-row\">\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32 text-right\">main</div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-main\" title=\"main\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-900\" title=\"gray-900\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-800\" title=\"gray-800\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-700\" title=\"gray-700\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-600\" title=\"gray-600\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-500\" title=\"gray-500\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-400\" title=\"gray-400\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-300\" title=\"gray-300\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-200\" title=\"gray-200\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-100\" title=\"gray-100\"></div>\n <div class=\"shadow-md rounded w-6 h-6 m-2 bg-gray-50\" title=\"gray-50\"></div>\n <div\n class=\"shadow-md rounded w-6 h-6 m-2 bg-background\"\n title=\"background\"\n ></div>\n <div class=\"text-xs text-gray-700 font-bold m-2 w-32\">background</div>\n</div>\n" }]
24154
- }] });
24155
-
24156
- class PopupAlertComponent {
24157
- constructor() {
24158
- this.changeDetector = inject(ChangeDetectorRef);
24159
- this.type = 'info';
24160
- this.position = 'top';
24161
- this.expanded = false;
24162
- this.timeout = null;
24163
- }
24164
- get showDuration() {
24165
- const chars = this.content.nativeElement.innerHTML.length;
24166
- return Math.max(3000, chars * 20);
24167
- }
24168
- ngOnInit() {
24169
- this.expandAndClose();
24170
- }
24171
- expand() {
24172
- this.expanded = true;
24173
- this.changeDetector.detectChanges();
24174
- clearTimeout(this.timeout);
24175
- }
24176
- expandAndClose() {
24177
- this.expanded = true;
24178
- this.changeDetector.detectChanges();
24179
- clearTimeout(this.timeout);
24180
- this.timeout = setTimeout(() => {
24181
- this.expanded = false;
24182
- this.changeDetector.detectChanges();
24183
- }, this.showDuration);
24184
- }
24185
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopupAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24186
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: PopupAlertComponent, isStandalone: true, selector: "gn-ui-popup-alert", inputs: { icon: "icon", type: "type", position: "position" }, providers: [
24187
- provideIcons({ matErrorOutlineOutline }),
24188
- provideNgIconsConfig({
24189
- size: '1.5em',
24190
- }),
24191
- ], viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "<div class=\"h-full relative container\">\n <div\n class=\"pointer-events-auto absolute text-white flex flex-row p-2 rounded message\"\n role=\"alert\"\n [ngClass]=\"{\n 'position-bottom': position === 'bottom',\n 'position-top': position === 'top',\n expanded: this.expanded,\n 'bg-red-500': type === 'danger',\n 'bg-yellow-500': type === 'warning',\n 'bg-blue-500': type === 'info',\n }\"\n (mouseenter)=\"expand()\"\n (mouseleave)=\"expandAndClose()\"\n >\n <ng-icon class=\"mr-2 shrink-0 select-none\" [name]=\"icon\"></ng-icon>\n <div class=\"grow\" #content [ngClass]=\"{ invisible: !expanded }\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{pointer-events:none}.container{filter:drop-shadow(0px 4px 3px rgba(0,0,0,.2))}.message{transition:clip-path .3s cubic-bezier(.25,.46,.45,.94)}.message.expanded{clip-path:circle(100%)}.position-top{clip-path:circle(19px at 20px 20px);align-items:start;top:0;left:0}.position-bottom{clip-path:circle(19px at 20px calc(100% - 20px));align-items:end;bottom:0;left:0}.container ::ng-deep a{text-decoration:underline;font-weight:700}.container ::ng-deep a:hover{opacity:.85}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
24192
- }
24193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PopupAlertComponent, decorators: [{
24194
- type: Component,
24195
- args: [{ selector: 'gn-ui-popup-alert', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, NgIconComponent], providers: [
24196
- provideIcons({ matErrorOutlineOutline }),
24197
- provideNgIconsConfig({
24198
- size: '1.5em',
24199
- }),
24200
- ], template: "<div class=\"h-full relative container\">\n <div\n class=\"pointer-events-auto absolute text-white flex flex-row p-2 rounded message\"\n role=\"alert\"\n [ngClass]=\"{\n 'position-bottom': position === 'bottom',\n 'position-top': position === 'top',\n expanded: this.expanded,\n 'bg-red-500': type === 'danger',\n 'bg-yellow-500': type === 'warning',\n 'bg-blue-500': type === 'info',\n }\"\n (mouseenter)=\"expand()\"\n (mouseleave)=\"expandAndClose()\"\n >\n <ng-icon class=\"mr-2 shrink-0 select-none\" [name]=\"icon\"></ng-icon>\n <div class=\"grow\" #content [ngClass]=\"{ invisible: !expanded }\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{pointer-events:none}.container{filter:drop-shadow(0px 4px 3px rgba(0,0,0,.2))}.message{transition:clip-path .3s cubic-bezier(.25,.46,.45,.94)}.message.expanded{clip-path:circle(100%)}.position-top{clip-path:circle(19px at 20px 20px);align-items:start;top:0;left:0}.position-bottom{clip-path:circle(19px at 20px calc(100% - 20px));align-items:end;bottom:0;left:0}.container ::ng-deep a{text-decoration:underline;font-weight:700}.container ::ng-deep a:hover{opacity:.85}\n"] }]
24201
- }], propDecorators: { icon: [{
24202
- type: Input
24203
- }], type: [{
24204
- type: Input
24205
- }], position: [{
24206
- type: Input
24207
- }], content: [{
24208
- type: ViewChild,
24209
- args: ['content']
24210
- }] } });
24211
-
24212
- class SpinningLoaderComponent {
24213
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpinningLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24214
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: SpinningLoaderComponent, isStandalone: true, selector: "gn-ui-spinning-loader", ngImport: i0, template: "<span>\n <svg\n class=\"animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</span>\n", styles: [""] }); }
24215
- }
24216
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpinningLoaderComponent, decorators: [{
24217
- type: Component,
24218
- args: [{ selector: 'gn-ui-spinning-loader', standalone: true, template: "<span>\n <svg\n class=\"animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n</span>\n" }]
24219
- }] });
24220
-
24221
- class ButtonComponent {
24222
- constructor() {
24223
- this.btnClass = 'gn-ui-btn-default';
24224
- this.disabled = false;
24225
- this.extraClass = '';
24226
- this.buttonClick = new EventEmitter();
23497
+ this.extraClass = '';
23498
+ this.buttonClick = new EventEmitter();
24227
23499
  }
24228
23500
  set type(value) {
24229
23501
  // btn-classes are written in full to be picked up by tailwind
@@ -24481,7 +23753,7 @@ class AutocompleteComponent {
24481
23753
  this.enterBtnPosition = event.target['value'].length * 8 + 80;
24482
23754
  }
24483
23755
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
24484
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AutocompleteComponent, isStandalone: true, selector: "gn-ui-autocomplete", inputs: { placeholder: "placeholder", enterButton: "enterButton", action: "action", value: "value", clearOnSelection: "clearOnSelection", preventCompleteOnSelection: "preventCompleteOnSelection", autoFocus: "autoFocus", minCharacterCount: "minCharacterCount", allowSubmit: "allowSubmit", forceTrackPosition: "forceTrackPosition", displayWithFn: "displayWithFn" }, outputs: { itemSelected: "itemSelected", inputSubmitted: "inputSubmitted", inputCleared: "inputCleared", isSearchActive: "isSearchActive" }, providers: [
23756
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AutocompleteComponent, isStandalone: true, selector: "gn-ui-autocomplete", inputs: { placeholder: "placeholder", enterButton: "enterButton", action: "action", value: "value", clearOnSelection: "clearOnSelection", preventCompleteOnSelection: "preventCompleteOnSelection", autoFocus: "autoFocus", minCharacterCount: "minCharacterCount", allowSubmit: "allowSubmit", forceTrackPosition: "forceTrackPosition", displayWithTemplate: "displayWithTemplate", displayWithFn: "displayWithFn" }, outputs: { itemSelected: "itemSelected", inputSubmitted: "inputSubmitted", inputCleared: "inputCleared", isSearchActive: "isSearchActive" }, providers: [
24485
23757
  provideIcons({
24486
23758
  iconoirSearch,
24487
23759
  matClose,
@@ -24490,7 +23762,7 @@ class AutocompleteComponent {
24490
23762
  provideNgIconsConfig({
24491
23763
  size: '1.75rem',
24492
23764
  }),
24493
- ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: MatAutocompleteTrigger, descendants: true }, { propertyName: "autocomplete", first: true, predicate: MatAutocomplete, descendants: true }, { propertyName: "inputRef", first: true, predicate: ["searchInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<span class=\"w-full inline-block relative\">\n @if (!allowSubmit) {\n <div\n class=\"absolute inset-y-[--icon-padding] left-[--icon-padding] w-[--icon-width] pointer-events-none\"\n >\n <ng-icon name=\"iconoirSearch\" class=\"text-primary search\"></ng-icon>\n </div>\n }\n <div class=\"flex flex-row\">\n <input\n #searchInput\n type=\"text\"\n class=\"gn-ui-text-input\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [matAutocomplete]=\"auto\"\n (keyup.enter)=\"handleSearch()\"\n [ngClass]=\"{\n 'text-primary': searchActive && enterButton,\n 'text-gray-900': !searchActive,\n 'px-[--icon-width]': !allowSubmit,\n }\"\n />\n @if (searchInput.value && displayEnterBtn) {\n <gn-ui-button\n type=\"gray\"\n extraClass=\"w-32 h-8 !opacity-100\"\n [ngStyle]=\"{ left: enterBtnPosition + 'px' }\"\n class=\"absolute\"\n disabled=\"true\"\n >\n <ng-icon\n name=\"iconoirLongArrowDownLeft\"\n class=\"!w-4 text-gray-900 font-bold\"\n ></ng-icon>\n <span translate class=\"text-bold text-gray-900 font-bold\">\n Enter to search\n </span>\n </gn-ui-button>\n }\n </div>\n @if (searchInput.value) {\n <gn-ui-button\n type=\"primary\"\n [extraClass]=\"getExtraClass()\"\n data-test=\"clear-btn\"\n aria-label=\"Clear\"\n (buttonClick)=\"clear()\"\n >\n <ng-icon class=\"text-white\" name=\"matClose\"></ng-icon>\n </gn-ui-button>\n }\n @if (allowSubmit) {\n <gn-ui-button\n type=\"light\"\n extraClass=\"border-0 border-l-[1px] border-gray-300 hover:border-gray-500 text-primary hover:text-primary-darkest focus:text-primary-darkest absolute inset-y-[--icon-padding] right-[--icon-padding]\"\n aria-label=\"Trigger search\"\n data-test=\"autocomplete-submit-btn\"\n (buttonClick)=\"handleSearch()\"\n >\n <ng-icon name=\"iconoirSearch\"></ng-icon>\n </gn-ui-button>\n }\n\n @if (error) {\n <gn-ui-popup-alert\n class=\"absolute mt-2 w-full top-[100%] left-0\"\n icon=\"matErrorOutlineOutline\"\n position=\"top\"\n type=\"warning\"\n >\n <span translate>search.autocomplete.error</span>\n {{ error }}\n </gn-ui-popup-alert>\n }\n</span>\n\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"handleSelection($event)\"\n [displayWith]=\"displayWithFnInternal\"\n>\n @for (suggestion of suggestions$ | async; track suggestion) {\n <mat-option [value]=\"suggestion\" class=\"p-2 suggestion text-start\">\n {{ displayWithFnInternal(suggestion) }}\n </mat-option>\n }\n</mat-autocomplete>\n", styles: ["span{--icon-padding: var(--gn-ui-text-input-border-size, 2px);--icon-width: calc(var(--gn-ui-text-input-padding, .6em) * 2 + 1.25em)}span>*:not(gn-ui-popup-alert){font-size:var(--gn-ui-text-input-font-size, 1em)}input:placeholder-shown{text-overflow:ellipsis}gn-ui-button{--gn-ui-button-rounded: 0;--gn-ui-button-width: var(--icon-width);--gn-ui-button-padding: 0;font-size:1em}ng-icon.search{margin-top:.6rem;margin-left:.6rem}gn-ui-button:last-of-type{--gn-ui-button-rounded: 0 var(--gn-ui-text-input-rounded, .25em) var(--gn-ui-text-input-rounded, .25em) 0}.mat-mdc-option.suggestion.mat-mdc-option-active{background-color:var(--color-primary-lightest)}\n"], dependencies: [{ kind: "component", type: PopupAlertComponent, selector: "gn-ui-popup-alert", inputs: ["icon", "type", "position"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i1$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i1$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
23765
+ ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: MatAutocompleteTrigger, descendants: true }, { propertyName: "autocomplete", first: true, predicate: MatAutocomplete, descendants: true }, { propertyName: "inputRef", first: true, predicate: ["searchInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<span class=\"w-full inline-block relative\">\n @if (!allowSubmit) {\n <div\n class=\"absolute inset-y-[--icon-padding] left-[--icon-padding] w-[--icon-width] pointer-events-none\"\n >\n <ng-icon name=\"iconoirSearch\" class=\"text-primary search\"></ng-icon>\n </div>\n }\n <div class=\"flex flex-row\">\n <input\n #searchInput\n type=\"text\"\n class=\"gn-ui-text-input\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [matAutocomplete]=\"auto\"\n (keyup.enter)=\"handleSearch()\"\n [ngClass]=\"{\n 'text-primary': searchActive && enterButton,\n 'text-gray-900': !searchActive,\n 'px-[--icon-width]': !allowSubmit,\n }\"\n />\n @if (searchInput.value && displayEnterBtn) {\n <gn-ui-button\n type=\"gray\"\n extraClass=\"w-32 h-8 !opacity-100\"\n [ngStyle]=\"{ left: enterBtnPosition + 'px' }\"\n class=\"absolute\"\n disabled=\"true\"\n >\n <ng-icon\n name=\"iconoirLongArrowDownLeft\"\n class=\"!w-4 text-gray-900 font-bold\"\n ></ng-icon>\n <span translate class=\"text-bold text-gray-900 font-bold\">\n Enter to search\n </span>\n </gn-ui-button>\n }\n </div>\n @if (searchInput.value) {\n <gn-ui-button\n type=\"primary\"\n [extraClass]=\"getExtraClass()\"\n data-test=\"clear-btn\"\n aria-label=\"Clear\"\n (buttonClick)=\"clear()\"\n >\n <ng-icon class=\"text-white\" name=\"matClose\"></ng-icon>\n </gn-ui-button>\n }\n @if (allowSubmit) {\n <gn-ui-button\n type=\"light\"\n extraClass=\"border-0 border-l-[1px] border-gray-300 hover:border-gray-500 text-primary hover:text-primary-darkest focus:text-primary-darkest absolute inset-y-[--icon-padding] right-[--icon-padding]\"\n aria-label=\"Trigger search\"\n data-test=\"autocomplete-submit-btn\"\n (buttonClick)=\"handleSearch()\"\n >\n <ng-icon name=\"iconoirSearch\"></ng-icon>\n </gn-ui-button>\n }\n\n @if (error) {\n <gn-ui-popup-alert\n class=\"absolute mt-2 w-full top-[100%] left-0\"\n icon=\"matErrorOutlineOutline\"\n position=\"top\"\n type=\"warning\"\n >\n <span translate>search.autocomplete.error</span>\n {{ error }}\n </gn-ui-popup-alert>\n }\n</span>\n\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"handleSelection($event)\"\n [displayWith]=\"displayWithFnInternal\"\n>\n @for (suggestion of suggestions$ | async; track suggestion) {\n <mat-option [value]=\"suggestion\" class=\"p-2 suggestion text-start\">\n @if (displayWithTemplate) {\n <ng-container\n *ngTemplateOutlet=\"\n displayWithTemplate;\n context: { $implicit: suggestion }\n \"\n ></ng-container>\n } @else {\n {{ displayWithFnInternal(suggestion) }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: ["span{--icon-padding: var(--gn-ui-text-input-border-size, 2px);--icon-width: calc(var(--gn-ui-text-input-padding, .6em) * 2 + 1.25em)}span>*:not(gn-ui-popup-alert){font-size:var(--gn-ui-text-input-font-size, 1em)}input:placeholder-shown{text-overflow:ellipsis}gn-ui-button{--gn-ui-button-rounded: 0;--gn-ui-button-width: var(--icon-width);--gn-ui-button-padding: 0;font-size:1em}ng-icon.search{margin-top:.6rem;margin-left:.6rem}gn-ui-button:last-of-type{--gn-ui-button-rounded: 0 var(--gn-ui-text-input-rounded, .25em) var(--gn-ui-text-input-rounded, .25em) 0}.mat-mdc-option.suggestion.mat-mdc-option-active{background-color:var(--color-primary-lightest)}\n"], dependencies: [{ kind: "component", type: PopupAlertComponent, selector: "gn-ui-popup-alert", inputs: ["icon", "type", "position"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i1$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i1$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
24494
23766
  }
24495
23767
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutocompleteComponent, decorators: [{
24496
23768
  type: Component,
@@ -24511,7 +23783,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
24511
23783
  provideNgIconsConfig({
24512
23784
  size: '1.75rem',
24513
23785
  }),
24514
- ], template: "<span class=\"w-full inline-block relative\">\n @if (!allowSubmit) {\n <div\n class=\"absolute inset-y-[--icon-padding] left-[--icon-padding] w-[--icon-width] pointer-events-none\"\n >\n <ng-icon name=\"iconoirSearch\" class=\"text-primary search\"></ng-icon>\n </div>\n }\n <div class=\"flex flex-row\">\n <input\n #searchInput\n type=\"text\"\n class=\"gn-ui-text-input\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [matAutocomplete]=\"auto\"\n (keyup.enter)=\"handleSearch()\"\n [ngClass]=\"{\n 'text-primary': searchActive && enterButton,\n 'text-gray-900': !searchActive,\n 'px-[--icon-width]': !allowSubmit,\n }\"\n />\n @if (searchInput.value && displayEnterBtn) {\n <gn-ui-button\n type=\"gray\"\n extraClass=\"w-32 h-8 !opacity-100\"\n [ngStyle]=\"{ left: enterBtnPosition + 'px' }\"\n class=\"absolute\"\n disabled=\"true\"\n >\n <ng-icon\n name=\"iconoirLongArrowDownLeft\"\n class=\"!w-4 text-gray-900 font-bold\"\n ></ng-icon>\n <span translate class=\"text-bold text-gray-900 font-bold\">\n Enter to search\n </span>\n </gn-ui-button>\n }\n </div>\n @if (searchInput.value) {\n <gn-ui-button\n type=\"primary\"\n [extraClass]=\"getExtraClass()\"\n data-test=\"clear-btn\"\n aria-label=\"Clear\"\n (buttonClick)=\"clear()\"\n >\n <ng-icon class=\"text-white\" name=\"matClose\"></ng-icon>\n </gn-ui-button>\n }\n @if (allowSubmit) {\n <gn-ui-button\n type=\"light\"\n extraClass=\"border-0 border-l-[1px] border-gray-300 hover:border-gray-500 text-primary hover:text-primary-darkest focus:text-primary-darkest absolute inset-y-[--icon-padding] right-[--icon-padding]\"\n aria-label=\"Trigger search\"\n data-test=\"autocomplete-submit-btn\"\n (buttonClick)=\"handleSearch()\"\n >\n <ng-icon name=\"iconoirSearch\"></ng-icon>\n </gn-ui-button>\n }\n\n @if (error) {\n <gn-ui-popup-alert\n class=\"absolute mt-2 w-full top-[100%] left-0\"\n icon=\"matErrorOutlineOutline\"\n position=\"top\"\n type=\"warning\"\n >\n <span translate>search.autocomplete.error</span>\n {{ error }}\n </gn-ui-popup-alert>\n }\n</span>\n\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"handleSelection($event)\"\n [displayWith]=\"displayWithFnInternal\"\n>\n @for (suggestion of suggestions$ | async; track suggestion) {\n <mat-option [value]=\"suggestion\" class=\"p-2 suggestion text-start\">\n {{ displayWithFnInternal(suggestion) }}\n </mat-option>\n }\n</mat-autocomplete>\n", styles: ["span{--icon-padding: var(--gn-ui-text-input-border-size, 2px);--icon-width: calc(var(--gn-ui-text-input-padding, .6em) * 2 + 1.25em)}span>*:not(gn-ui-popup-alert){font-size:var(--gn-ui-text-input-font-size, 1em)}input:placeholder-shown{text-overflow:ellipsis}gn-ui-button{--gn-ui-button-rounded: 0;--gn-ui-button-width: var(--icon-width);--gn-ui-button-padding: 0;font-size:1em}ng-icon.search{margin-top:.6rem;margin-left:.6rem}gn-ui-button:last-of-type{--gn-ui-button-rounded: 0 var(--gn-ui-text-input-rounded, .25em) var(--gn-ui-text-input-rounded, .25em) 0}.mat-mdc-option.suggestion.mat-mdc-option-active{background-color:var(--color-primary-lightest)}\n"] }]
23786
+ ], template: "<span class=\"w-full inline-block relative\">\n @if (!allowSubmit) {\n <div\n class=\"absolute inset-y-[--icon-padding] left-[--icon-padding] w-[--icon-width] pointer-events-none\"\n >\n <ng-icon name=\"iconoirSearch\" class=\"text-primary search\"></ng-icon>\n </div>\n }\n <div class=\"flex flex-row\">\n <input\n #searchInput\n type=\"text\"\n class=\"gn-ui-text-input\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [matAutocomplete]=\"auto\"\n (keyup.enter)=\"handleSearch()\"\n [ngClass]=\"{\n 'text-primary': searchActive && enterButton,\n 'text-gray-900': !searchActive,\n 'px-[--icon-width]': !allowSubmit,\n }\"\n />\n @if (searchInput.value && displayEnterBtn) {\n <gn-ui-button\n type=\"gray\"\n extraClass=\"w-32 h-8 !opacity-100\"\n [ngStyle]=\"{ left: enterBtnPosition + 'px' }\"\n class=\"absolute\"\n disabled=\"true\"\n >\n <ng-icon\n name=\"iconoirLongArrowDownLeft\"\n class=\"!w-4 text-gray-900 font-bold\"\n ></ng-icon>\n <span translate class=\"text-bold text-gray-900 font-bold\">\n Enter to search\n </span>\n </gn-ui-button>\n }\n </div>\n @if (searchInput.value) {\n <gn-ui-button\n type=\"primary\"\n [extraClass]=\"getExtraClass()\"\n data-test=\"clear-btn\"\n aria-label=\"Clear\"\n (buttonClick)=\"clear()\"\n >\n <ng-icon class=\"text-white\" name=\"matClose\"></ng-icon>\n </gn-ui-button>\n }\n @if (allowSubmit) {\n <gn-ui-button\n type=\"light\"\n extraClass=\"border-0 border-l-[1px] border-gray-300 hover:border-gray-500 text-primary hover:text-primary-darkest focus:text-primary-darkest absolute inset-y-[--icon-padding] right-[--icon-padding]\"\n aria-label=\"Trigger search\"\n data-test=\"autocomplete-submit-btn\"\n (buttonClick)=\"handleSearch()\"\n >\n <ng-icon name=\"iconoirSearch\"></ng-icon>\n </gn-ui-button>\n }\n\n @if (error) {\n <gn-ui-popup-alert\n class=\"absolute mt-2 w-full top-[100%] left-0\"\n icon=\"matErrorOutlineOutline\"\n position=\"top\"\n type=\"warning\"\n >\n <span translate>search.autocomplete.error</span>\n {{ error }}\n </gn-ui-popup-alert>\n }\n</span>\n\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"handleSelection($event)\"\n [displayWith]=\"displayWithFnInternal\"\n>\n @for (suggestion of suggestions$ | async; track suggestion) {\n <mat-option [value]=\"suggestion\" class=\"p-2 suggestion text-start\">\n @if (displayWithTemplate) {\n <ng-container\n *ngTemplateOutlet=\"\n displayWithTemplate;\n context: { $implicit: suggestion }\n \"\n ></ng-container>\n } @else {\n {{ displayWithFnInternal(suggestion) }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: ["span{--icon-padding: var(--gn-ui-text-input-border-size, 2px);--icon-width: calc(var(--gn-ui-text-input-padding, .6em) * 2 + 1.25em)}span>*:not(gn-ui-popup-alert){font-size:var(--gn-ui-text-input-font-size, 1em)}input:placeholder-shown{text-overflow:ellipsis}gn-ui-button{--gn-ui-button-rounded: 0;--gn-ui-button-width: var(--icon-width);--gn-ui-button-padding: 0;font-size:1em}ng-icon.search{margin-top:.6rem;margin-left:.6rem}gn-ui-button:last-of-type{--gn-ui-button-rounded: 0 var(--gn-ui-text-input-rounded, .25em) var(--gn-ui-text-input-rounded, .25em) 0}.mat-mdc-option.suggestion.mat-mdc-option-active{background-color:var(--color-primary-lightest)}\n"] }]
24515
23787
  }], propDecorators: { placeholder: [{
24516
23788
  type: Input
24517
23789
  }], enterButton: [{
@@ -24549,6 +23821,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
24549
23821
  }], inputRef: [{
24550
23822
  type: ViewChild,
24551
23823
  args: ['searchInput']
23824
+ }], displayWithTemplate: [{
23825
+ type: Input
24552
23826
  }], displayWithFn: [{
24553
23827
  type: Input
24554
23828
  }] } });
@@ -26070,6 +25344,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
26070
25344
  marker('search.filters.spatialExtent.import');
26071
25345
  marker('search.filters.spatialExtent.helpText');
26072
25346
  marker('search.filters.spatialExtent.error.title');
25347
+ marker('search.filters.spatialExtent.error.outOfBounds');
26073
25348
  const LABEL_FROM_FILE = marker('search.filters.spatialExtent.bboxFromFile');
26074
25349
  const LABEL_FROM_FILE_DELETE = marker('search.filters.spatialExtent.bboxFromFileDelete');
26075
25350
  const LABEL_INITIAL = marker('search.filters.spatialExtent.bboxInitial');
@@ -26150,6 +25425,10 @@ class SpatialExtentDropdownComponent {
26150
25425
  return;
26151
25426
  }
26152
25427
  const bbox = getGeometryBoundingBox(geometry);
25428
+ if (!isBoundingBoxWithinWorldExtent(bbox)) {
25429
+ this.setError(marker('search.filters.spatialExtent.error.outOfBounds'));
25430
+ return;
25431
+ }
26153
25432
  this.bbox = bbox;
26154
25433
  this.fileName = file.name;
26155
25434
  this.bboxChange.emit(bbox);
@@ -26187,14 +25466,14 @@ class SpatialExtentDropdownComponent {
26187
25466
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SpatialExtentDropdownComponent, isStandalone: true, selector: "gn-ui-spatial-extent-dropdown", inputs: { title: "title", maxFileSizeMb: "maxFileSizeMb", initialBbox: "initialBbox" }, outputs: { bboxChange: "bboxChange", errorChange: "errorChange" }, providers: [
26188
25467
  provideIcons({
26189
25468
  iconoirCheckCircle,
26190
- iconoirImport,
26191
25469
  iconoirSquareDashed,
26192
25470
  iconoirTrash,
25471
+ iconoirUpload,
26193
25472
  matClose,
26194
25473
  matExpandLess,
26195
25474
  matExpandMore,
26196
25475
  }),
26197
- ], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "fileInput", first: true, predicate: DragAndDropFileInputComponent, descendants: true }], ngImport: i0, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[8px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirImport\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"selectionDeleteLabelKey | translate: selectionLabelParams\"\n (buttonClick)=\"removeSelection($event)\"\n extraClass=\"group gap-x-2 w-full h-[28px] px-[8px] py-[4px] mb-[12px] bg-primary-lighter text-white\"\n data-test=\"spatial-extent-selected-item\"\n >\n <ng-icon\n name=\"iconoirSquareDashed\"\n class=\"shrink-0\"\n size=\"15px\"\n ></ng-icon>\n <span class=\"group-hover:hidden truncate text-sm m-auto\">\n {{ selectionLabelKey | translate: selectionLabelParams }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ selectionDeleteLabelKey | translate: selectionLabelParams }}\n </span>\n <ng-icon\n name=\"iconoirCheckCircle\"\n class=\"group-hover:hidden shrink-0\"\n size=\"14px\"\n ></ng-icon>\n <ng-icon\n name=\"iconoirTrash\"\n class=\"!hidden group-hover:!block shrink-0\"\n size=\"15px\"\n ></ng-icon>\n </gn-ui-button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$7.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$7.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: DragAndDropFileInputComponent, selector: "gn-ui-drag-and-drop-file-input", inputs: ["placeholder", "accept", "maxFileSizeMb", "icon", "dropzoneBackgroundColor", "textClass", "extraClass", "showFileName"], outputs: ["fileChange", "errorChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
25476
+ ], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "fileInput", first: true, predicate: DragAndDropFileInputComponent, descendants: true }], ngImport: i0, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[12px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirUpload\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"selectionDeleteLabelKey | translate: selectionLabelParams\"\n (buttonClick)=\"removeSelection($event)\"\n extraClass=\"group gap-x-2 w-full h-[28px] px-[8px] py-[4px] mb-[12px] bg-primary-lighter text-white\"\n data-test=\"spatial-extent-selected-item\"\n >\n <ng-icon\n name=\"iconoirSquareDashed\"\n class=\"shrink-0\"\n size=\"15px\"\n ></ng-icon>\n <span class=\"group-hover:hidden truncate text-sm m-auto\">\n {{ selectionLabelKey | translate: selectionLabelParams }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ selectionDeleteLabelKey | translate: selectionLabelParams }}\n </span>\n <ng-icon\n name=\"iconoirCheckCircle\"\n class=\"group-hover:hidden shrink-0\"\n size=\"14px\"\n ></ng-icon>\n <ng-icon\n name=\"iconoirTrash\"\n class=\"!hidden group-hover:!block shrink-0\"\n size=\"15px\"\n ></ng-icon>\n </gn-ui-button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$7.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$7.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: DragAndDropFileInputComponent, selector: "gn-ui-drag-and-drop-file-input", inputs: ["placeholder", "accept", "maxFileSizeMb", "icon", "dropzoneBackgroundColor", "textClass", "extraClass", "showFileName"], outputs: ["fileChange", "errorChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
26198
25477
  }
26199
25478
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpatialExtentDropdownComponent, decorators: [{
26200
25479
  type: Component,
@@ -26207,14 +25486,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
26207
25486
  ], providers: [
26208
25487
  provideIcons({
26209
25488
  iconoirCheckCircle,
26210
- iconoirImport,
26211
25489
  iconoirSquareDashed,
26212
25490
  iconoirTrash,
25491
+ iconoirUpload,
26213
25492
  matClose,
26214
25493
  matExpandLess,
26215
25494
  matExpandMore,
26216
25495
  }),
26217
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[8px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirImport\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"selectionDeleteLabelKey | translate: selectionLabelParams\"\n (buttonClick)=\"removeSelection($event)\"\n extraClass=\"group gap-x-2 w-full h-[28px] px-[8px] py-[4px] mb-[12px] bg-primary-lighter text-white\"\n data-test=\"spatial-extent-selected-item\"\n >\n <ng-icon\n name=\"iconoirSquareDashed\"\n class=\"shrink-0\"\n size=\"15px\"\n ></ng-icon>\n <span class=\"group-hover:hidden truncate text-sm m-auto\">\n {{ selectionLabelKey | translate: selectionLabelParams }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ selectionDeleteLabelKey | translate: selectionLabelParams }}\n </span>\n <ng-icon\n name=\"iconoirCheckCircle\"\n class=\"group-hover:hidden shrink-0\"\n size=\"14px\"\n ></ng-icon>\n <ng-icon\n name=\"iconoirTrash\"\n class=\"!hidden group-hover:!block shrink-0\"\n size=\"15px\"\n ></ng-icon>\n </gn-ui-button>\n }\n </div>\n</ng-template>\n" }]
25496
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[12px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirUpload\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"selectionDeleteLabelKey | translate: selectionLabelParams\"\n (buttonClick)=\"removeSelection($event)\"\n extraClass=\"group gap-x-2 w-full h-[28px] px-[8px] py-[4px] mb-[12px] bg-primary-lighter text-white\"\n data-test=\"spatial-extent-selected-item\"\n >\n <ng-icon\n name=\"iconoirSquareDashed\"\n class=\"shrink-0\"\n size=\"15px\"\n ></ng-icon>\n <span class=\"group-hover:hidden truncate text-sm m-auto\">\n {{ selectionLabelKey | translate: selectionLabelParams }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ selectionDeleteLabelKey | translate: selectionLabelParams }}\n </span>\n <ng-icon\n name=\"iconoirCheckCircle\"\n class=\"group-hover:hidden shrink-0\"\n size=\"14px\"\n ></ng-icon>\n <ng-icon\n name=\"iconoirTrash\"\n class=\"!hidden group-hover:!block shrink-0\"\n size=\"15px\"\n ></ng-icon>\n </gn-ui-button>\n }\n </div>\n</ng-template>\n" }]
26218
25497
  }], propDecorators: { title: [{
26219
25498
  type: Input
26220
25499
  }], maxFileSizeMb: [{
@@ -26740,11 +26019,11 @@ class BlockListComponent {
26740
26019
  this.goToPage(this.currentPage + 1);
26741
26020
  }
26742
26021
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BlockListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
26743
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: BlockListComponent, isStandalone: true, selector: "gn-ui-block-list", inputs: { containerClass: "containerClass", paginationContainerClass: "paginationContainerClass" }, outputs: { listChanges: "listChanges" }, host: { listeners: { "window:resize": "onResize()" } }, queries: [{ propertyName: "blocks", predicate: ["block"], read: ElementRef }], viewQueries: [{ propertyName: "blockContainer", first: true, predicate: ["blockContainer"], descendants: true }], ngImport: i0, template: "<div\n class=\"grid gap-4 w-full sm:grid-cols-2\"\n #blockContainer\n [ngClass]=\"[containerClass, 'size-' + subComponentSize]\"\n>\n <ng-content></ng-content>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + paginationContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host .block-list-container ::ng-deep>*{flex-shrink:0}:host{position:relative}@media screen and (min-width: 769px){.size-L{grid-template-columns:repeat(1,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-M{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-S{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-XS{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PaginationDotsComponent, selector: "gn-ui-pagination-dots", inputs: ["listComponent", "containerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
26022
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: BlockListComponent, isStandalone: true, selector: "gn-ui-block-list", inputs: { containerClass: "containerClass", paginationContainerClass: "paginationContainerClass" }, outputs: { listChanges: "listChanges" }, host: { listeners: { "window:resize": "onResize()" } }, queries: [{ propertyName: "blocks", predicate: ["block"], read: ElementRef }], viewQueries: [{ propertyName: "blockContainer", first: true, predicate: ["blockContainer"], descendants: true }], ngImport: i0, template: "<div\n class=\"grid gap-4 w-full sm:grid-cols-2\"\n #blockContainer\n [ngClass]=\"[containerClass, 'size-' + subComponentSize]\"\n>\n <ng-content></ng-content>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + paginationContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host .block-list-container ::ng-deep>*{flex-shrink:0}:host{display:block;position:relative}@media screen and (min-width: 769px){.size-L{grid-template-columns:repeat(1,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-M{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-S{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-XS{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PaginationDotsComponent, selector: "gn-ui-pagination-dots", inputs: ["listComponent", "containerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
26744
26023
  }
26745
26024
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BlockListComponent, decorators: [{
26746
26025
  type: Component,
26747
- args: [{ selector: 'gn-ui-block-list', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PaginationDotsComponent], template: "<div\n class=\"grid gap-4 w-full sm:grid-cols-2\"\n #blockContainer\n [ngClass]=\"[containerClass, 'size-' + subComponentSize]\"\n>\n <ng-content></ng-content>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + paginationContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host .block-list-container ::ng-deep>*{flex-shrink:0}:host{position:relative}@media screen and (min-width: 769px){.size-L{grid-template-columns:repeat(1,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-M{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-S{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-XS{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}}\n"] }]
26026
+ args: [{ selector: 'gn-ui-block-list', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PaginationDotsComponent], template: "<div\n class=\"grid gap-4 w-full sm:grid-cols-2\"\n #blockContainer\n [ngClass]=\"[containerClass, 'size-' + subComponentSize]\"\n>\n <ng-content></ng-content>\n</div>\n<gn-ui-pagination-dots\n [containerClass]=\"'absolute ' + paginationContainerClass\"\n [listComponent]=\"this\"\n></gn-ui-pagination-dots>\n", styles: [":host .block-list-container ::ng-deep>*{flex-shrink:0}:host{display:block;position:relative}@media screen and (min-width: 769px){.size-L{grid-template-columns:repeat(1,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-M{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-S{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}.size-XS{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,min-content)}}\n"] }]
26748
26027
  }], propDecorators: { containerClass: [{
26749
26028
  type: Input
26750
26029
  }], paginationContainerClass: [{
@@ -27483,9 +26762,7 @@ const initSearch = () => {
27483
26762
  },
27484
26763
  params: {
27485
26764
  filters: {},
27486
- pageSize: getOptionalSearchConfig()?.LIMIT
27487
- ? getOptionalSearchConfig().LIMIT
27488
- : DEFAULT_PAGE_SIZE,
26765
+ pageSize: DEFAULT_PAGE_SIZE,
27489
26766
  currentPage: 0,
27490
26767
  favoritesOnly: false,
27491
26768
  useSpatialFilter: true,
@@ -27934,6 +27211,70 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
27934
27211
  }]
27935
27212
  }] });
27936
27213
 
27214
+ const DEFAULT_GEOCODING_PROVIDER = [
27215
+ 'geonames',
27216
+ { maxRows: 5 },
27217
+ ];
27218
+ const GEOCODING_PROVIDER = new InjectionToken('geocoding-provider', {
27219
+ providedIn: 'root',
27220
+ factory: () => DEFAULT_GEOCODING_PROVIDER,
27221
+ });
27222
+ class GeocodingService {
27223
+ constructor() {
27224
+ this.provider = inject(GEOCODING_PROVIDER);
27225
+ }
27226
+ query(text) {
27227
+ let queryObservable;
27228
+ switch (this.provider[0]) {
27229
+ case 'geoadmin':
27230
+ queryObservable = from(queryGeoadmin(text, this.provider[1]));
27231
+ break;
27232
+ case 'geonames':
27233
+ queryObservable = from(queryGeonames(text, this.provider[1]));
27234
+ break;
27235
+ case 'geoplateforme':
27236
+ queryObservable = from(queryGeoplateforme(text, this.provider[1]));
27237
+ break;
27238
+ default:
27239
+ return throwError(() => new Error(`Unsupported geocoding provider: ${this.provider[0]}`));
27240
+ }
27241
+ return queryObservable.pipe(catchError((error) => throwError(error)));
27242
+ }
27243
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
27244
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, providedIn: 'root' }); }
27245
+ }
27246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, decorators: [{
27247
+ type: Injectable,
27248
+ args: [{
27249
+ providedIn: 'root',
27250
+ }]
27251
+ }] });
27252
+
27253
+ class LocationSearchComponent {
27254
+ constructor() {
27255
+ this.geocodingService = inject(GeocodingService);
27256
+ this.placeholder = '';
27257
+ this.resultSelected = new EventEmitter();
27258
+ this.displayWithFn = (item) => item.label;
27259
+ this.searchAction = (text) => this.geocodingService.query(text);
27260
+ }
27261
+ handleItemSelected(item) {
27262
+ this.resultSelected.emit(item);
27263
+ }
27264
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocationSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
27265
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: LocationSearchComponent, isStandalone: true, selector: "gn-ui-location-search", inputs: { placeholder: "placeholder", displayWithTemplate: "displayWithTemplate" }, outputs: { resultSelected: "resultSelected" }, ngImport: i0, template: "<gn-ui-autocomplete\n [action]=\"searchAction\"\n [displayWithFn]=\"displayWithFn\"\n [placeholder]=\"placeholder\"\n [displayWithTemplate]=\"displayWithTemplate\"\n (itemSelected)=\"handleItemSelected($event)\"\n>\n</gn-ui-autocomplete>\n", dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
27266
+ }
27267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocationSearchComponent, decorators: [{
27268
+ type: Component,
27269
+ args: [{ selector: 'gn-ui-location-search', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [AutocompleteComponent], template: "<gn-ui-autocomplete\n [action]=\"searchAction\"\n [displayWithFn]=\"displayWithFn\"\n [placeholder]=\"placeholder\"\n [displayWithTemplate]=\"displayWithTemplate\"\n (itemSelected)=\"handleItemSelected($event)\"\n>\n</gn-ui-autocomplete>\n" }]
27270
+ }], propDecorators: { placeholder: [{
27271
+ type: Input
27272
+ }], displayWithTemplate: [{
27273
+ type: Input
27274
+ }], resultSelected: [{
27275
+ type: Output
27276
+ }] } });
27277
+
27937
27278
  // expects the replacement key ${uuid}
27938
27279
  const RECORD_DATASET_URL_TOKEN = new InjectionToken('record-dataset-url-token');
27939
27280
  const RECORD_SERVICE_URL_TOKEN = new InjectionToken('record-service-url-token');
@@ -28586,6 +27927,7 @@ marker('search.filters.publisherOrg');
28586
27927
  marker('search.filters.user');
28587
27928
  marker('search.filters.changeDate');
28588
27929
  marker('search.filters.resourceCreationRevisionDate');
27930
+ marker('search.filters.temporalExtent');
28589
27931
  marker('search.filters.spatialExtent');
28590
27932
  class FieldsService {
28591
27933
  constructor() {
@@ -28610,6 +27952,7 @@ class FieldsService {
28610
27952
  user: new UserSearchField(this.injector),
28611
27953
  changeDate: new DateRangeSearchField('changeDate', this.injector, 'desc'),
28612
27954
  resourceCreationRevisionDate: new ResourceCreationRevisionDateSearchField(this.injector, 'desc'),
27955
+ temporalExtent: new DateRangeSearchField('resourceTemporalExtentDateRange', this.injector, 'desc'),
28613
27956
  availableServices: new AvailableServicesField(this.injector),
28614
27957
  spatialExtent: new BoundingBoxSearchField('spatialExtent', this.injector),
28615
27958
  };
@@ -31865,6 +31208,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
31865
31208
  ], template: "<div class=\"flex flex-col gap-6 p-6 items-start pointer-events-none\">\n @for (\n notification of notificationsService.notifications$ | async;\n track trackById($index, notification)\n ) {\n <gn-ui-notification\n class=\"max-w-full pointer-events-auto\"\n [text]=\"notification.text\"\n [type]=\"notification.type\"\n [title]=\"notification.title\"\n [closeMessage]=\"notification.closeMessage\"\n (notificationClose)=\"\n notificationsService.removeNotificationById(notification.id)\n \"\n [@enterExit]\n ></gn-ui-notification>\n }\n</div>\n" }]
31866
31209
  }] });
31867
31210
 
31211
+ // in MB, null means no limit
31212
+ const SPATIAL_EXTENT_MAX_FILE_SIZE = new InjectionToken('spatialExtentMaxFileSize', { factory: () => null });
31868
31213
  class FilterDropdownComponent {
31869
31214
  constructor() {
31870
31215
  this.searchFacade = inject(SearchFacade);
@@ -31872,7 +31217,7 @@ class FilterDropdownComponent {
31872
31217
  this.fieldsService = inject(FieldsService);
31873
31218
  this.notificationsService = inject(NotificationsService);
31874
31219
  this.translateService = inject(TranslateService);
31875
- this.spatialExtentMaxFileSize = getOptionalSearchConfig()?.SPATIAL_EXTENT_MAX_FILE_SIZE;
31220
+ this.spatialExtentMaxFileSize = inject(SPATIAL_EXTENT_MAX_FILE_SIZE);
31876
31221
  this.selected$ = this.searchFacade.searchFilters$.pipe(switchMap((filters) => this.fieldsService.readFieldValuesFromFilters(filters)), map$1((fieldValues) => fieldValues[this.fieldName]), filter$1((selected) => !!selected), startWith$1([]), catchError(() => of([])));
31877
31222
  this.selectedDateRange$ = this.selected$.pipe(map$1((selected) => (Array.isArray(selected) ? {} : selected)));
31878
31223
  this.selectedBoundingBox$ = this.selected$.pipe(map$1((selected) => Array.isArray(selected) && selected.length > 0
@@ -31993,7 +31338,7 @@ class FuzzySearchComponent {
31993
31338
  this.isSearchActive.emit(event);
31994
31339
  }
31995
31340
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FuzzySearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
31996
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FuzzySearchComponent, isStandalone: true, selector: "gn-ui-fuzzy-search", inputs: { autoFocus: "autoFocus", forceTrackPosition: "forceTrackPosition", enterButton: "enterButton", placeholder: "placeholder" }, outputs: { itemSelected: "itemSelected", inputSubmitted: "inputSubmitted", isSearchActive: "isSearchActive" }, viewQueries: [{ propertyName: "autocomplete", first: true, predicate: AutocompleteComponent, descendants: true }], ngImport: i0, template: "<gn-ui-autocomplete\n [placeholder]=\"placeholder ?? ('search.field.any.placeholder' | translate)\"\n [displayWithFn]=\"displayWithFn\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleItemSelection($event)\"\n (inputSubmitted)=\"handleInputSubmission($event)\"\n (inputCleared)=\"handleInputCleared()\"\n (isSearchActive)=\"handleSearchActive($event)\"\n [value]=\"searchInputValue$ | async\"\n [preventCompleteOnSelection]=\"true\"\n [autoFocus]=\"autoFocus\"\n [allowSubmit]=\"true\"\n [forceTrackPosition]=\"forceTrackPosition\"\n [enterButton]=\"enterButton\"\n></gn-ui-autocomplete>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
31341
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FuzzySearchComponent, isStandalone: true, selector: "gn-ui-fuzzy-search", inputs: { autoFocus: "autoFocus", forceTrackPosition: "forceTrackPosition", enterButton: "enterButton", placeholder: "placeholder" }, outputs: { itemSelected: "itemSelected", inputSubmitted: "inputSubmitted", isSearchActive: "isSearchActive" }, viewQueries: [{ propertyName: "autocomplete", first: true, predicate: AutocompleteComponent, descendants: true }], ngImport: i0, template: "<gn-ui-autocomplete\n [placeholder]=\"placeholder ?? ('search.field.any.placeholder' | translate)\"\n [displayWithFn]=\"displayWithFn\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleItemSelection($event)\"\n (inputSubmitted)=\"handleInputSubmission($event)\"\n (inputCleared)=\"handleInputCleared()\"\n (isSearchActive)=\"handleSearchActive($event)\"\n [value]=\"searchInputValue$ | async\"\n [preventCompleteOnSelection]=\"true\"\n [autoFocus]=\"autoFocus\"\n [allowSubmit]=\"true\"\n [forceTrackPosition]=\"forceTrackPosition\"\n [enterButton]=\"enterButton\"\n></gn-ui-autocomplete>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
31997
31342
  }
31998
31343
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FuzzySearchComponent, decorators: [{
31999
31344
  type: Component,
@@ -32553,6 +31898,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
32553
31898
  marker('search.filters.summaryLabel.user');
32554
31899
  marker('search.filters.summaryLabel.changeDate');
32555
31900
  marker('search.filters.summaryLabel.resourceCreationRevisionDate');
31901
+ marker('search.filters.summaryLabel.temporalExtent');
32556
31902
  const OPEN_BOUND = '…';
32557
31903
  class SearchFiltersSummaryItemComponent {
32558
31904
  constructor() {
@@ -32934,95 +32280,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
32934
32280
  ], template: "<div\n class=\"bg-white rounded shadow shadow-lg relative h-full w-[400px] overflow-hidden\"\n>\n <div class=\"p-3 border-b border-gray-300 flex items-center\">\n <ng-icon class=\"mr-2\" name=\"matLayersOutline\"></ng-icon>\n <span translate>map.layers.list</span>\n </div>\n <div class=\"flex flex-col px-4 divide-y divide-y-gray-50\">\n @for (layer of layers$ | async; track layer; let index = $index) {\n <div class=\"flex flex-row py-3\">\n <ng-icon class=\"-ml-2 mr-2 shrink-0\" name=\"matChevronRight\"></ng-icon>\n <span class=\"mr-2 grow\">{{ layer.label }}</span>\n <a\n href\n class=\"underline text-sm text-red-700 hover:text-red-900\"\n (click)=\"deleteLayer(index); $event.preventDefault()\"\n >\n delete\n </a>\n </div>\n }\n </div>\n <gn-ui-expandable-panel-button [titleTemplate]=\"addLayerTitle\">\n <mat-tab-group animationDuration=\"200ms\" class=\"h-full\">\n <mat-tab [label]=\"'map.add.layer.catalog' | translate\">\n <div class=\"p-3\">\n <gn-ui-add-layer-from-catalog></gn-ui-add-layer-from-catalog>\n </div>\n </mat-tab>\n <mat-tab [label]=\"'map.add.layer.wms' | translate\" bodyClass=\"h-full\">\n <div class=\"p-3\">\n <gn-ui-add-layer-from-wms></gn-ui-add-layer-from-wms>\n </div>\n </mat-tab>\n <mat-tab [label]=\"'map.add.layer.wfs' | translate\" bodyClass=\"h-full\">\n <div class=\"p-3\">\n <gn-ui-add-layer-from-wfs></gn-ui-add-layer-from-wfs>\n </div>\n </mat-tab>\n <mat-tab [label]=\"'map.add.layer.ogc.api' | translate\" bodyClass=\"h-full\">\n <div class=\"p-3\">\n <gn-ui-add-layer-from-ogc-api\n [ogcUrl]=\"ogcUrl\"\n (layerAdded)=\"addLayer($event)\"\n ></gn-ui-add-layer-from-ogc-api>\n </div>\n </mat-tab>\n <mat-tab [label]=\"'map.add.layer.file' | translate\" bodyClass=\"h-full\">\n <div class=\"p-3\">\n <gn-ui-add-layer-from-file></gn-ui-add-layer-from-file>\n </div>\n </mat-tab>\n </mat-tab-group>\n </gn-ui-expandable-panel-button>\n</div>\n\n<ng-template #addLayerTitle>\n <ng-icon class=\"mr-4\" name=\"matAddCircleOutlineOutline\"> </ng-icon>\n <span translate>map.add.layer</span>\n</ng-template>\n" }]
32935
32281
  }] });
32936
32282
 
32937
- class GeocodingComponent {
32938
- constructor() {
32939
- this.mapFacade = inject(MapFacade);
32940
- this.geocodingService = inject(GeocodingService);
32941
- this.searchText = '';
32942
- this.results = [];
32943
- this.searchTextChanged = new Subject();
32944
- this.destroy$ = new Subject();
32945
- this.errorMessage = null;
32946
- this.searchTextChanged
32947
- .pipe(debounceTime(300), switchMap$1((searchText) => {
32948
- return from(this.geocodingService.query(searchText)).pipe(catchError$1((error) => {
32949
- this.errorMessage =
32950
- 'An error occurred while searching. Please try again.';
32951
- console.error(error);
32952
- return [];
32953
- }));
32954
- }), takeUntil(this.destroy$))
32955
- .subscribe((results) => {
32956
- this.results = results;
32957
- });
32958
- }
32959
- ngOnDestroy() {
32960
- this.destroy$.next();
32961
- this.destroy$.complete();
32962
- }
32963
- onSearchChange(searchText) {
32964
- if (!searchText) {
32965
- this.clearSearch();
32966
- return;
32967
- }
32968
- else {
32969
- this.searchTextChanged.next(searchText);
32970
- }
32971
- }
32972
- clearSearch() {
32973
- this.searchText = '';
32974
- this.results = [];
32975
- this.errorMessage = null;
32976
- }
32977
- async zoomToLocation(result) {
32978
- const geometry = result.geom;
32979
- if (geometry.type === 'Point') {
32980
- await this.zoomToPoint(geometry.coordinates);
32981
- }
32982
- else if (geometry.type === 'Polygon') {
32983
- await this.zoomToPolygon(geometry.coordinates);
32984
- }
32985
- else {
32986
- console.error(`Unsupported geometry type: ${geometry.type}`);
32987
- }
32988
- }
32989
- async zoomToPoint(pointCoords) {
32990
- const context = await firstValueFrom(this.mapFacade.context$);
32991
- const view = {
32992
- center: pointCoords,
32993
- zoom: 10,
32994
- };
32995
- this.mapFacade.applyContext({
32996
- ...context,
32997
- view,
32998
- });
32999
- }
33000
- async zoomToPolygon(polygonCoords) {
33001
- const context = await firstValueFrom(this.mapFacade.context$);
33002
- const view = {
33003
- geometry: {
33004
- type: 'Polygon',
33005
- coordinates: polygonCoords,
33006
- },
33007
- };
33008
- this.mapFacade.applyContext({
33009
- ...context,
33010
- view,
33011
- });
33012
- }
33013
- onEnterPress() {
33014
- if (this.results && this.results.length > 0) {
33015
- this.zoomToLocation(this.results[0]);
33016
- }
33017
- }
33018
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
33019
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: GeocodingComponent, isStandalone: true, selector: "gn-ui-geocoding", ngImport: i0, template: "<gn-ui-search-input\n [(value)]=\"searchText\"\n (valueChange)=\"onSearchChange($event)\"\n (keyup.enter)=\"onEnterPress()\"\n [placeholder]=\"'map.geocoding.placeholder' | translate\"\n>\n</gn-ui-search-input>\n@if (results && results.length) {\n <ul\n class=\"bg-gray-50 border border-gray-200 w-full mt-2 shadow-sm rounded-lg\"\n >\n @for (result of results; track result) {\n <li\n (click)=\"zoomToLocation(result)\"\n class=\"flex items-center pl-8 pr-4 py-2 border-b border-gray-200 relative cursor-pointer hover:bg-blue-100 hover:text-gray-800 transition duration-300 ease-in-out\"\n >\n <svg\n class=\"stroke-current text-blue-500 absolute w-5 h-5 left-3 top-3\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z\"\n />\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M15 11a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n <span class=\"font-sans font-semibold ml-4\">{{ result.label }}</span>\n </li>\n }\n </ul>\n}\n", styles: [""], dependencies: [{ kind: "component", type: SearchInputComponent, selector: "gn-ui-search-input", inputs: ["value", "placeholder"], outputs: ["valueChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
33020
- }
33021
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingComponent, decorators: [{
33022
- type: Component,
33023
- args: [{ selector: 'gn-ui-geocoding', standalone: true, imports: [SearchInputComponent, TranslatePipe], template: "<gn-ui-search-input\n [(value)]=\"searchText\"\n (valueChange)=\"onSearchChange($event)\"\n (keyup.enter)=\"onEnterPress()\"\n [placeholder]=\"'map.geocoding.placeholder' | translate\"\n>\n</gn-ui-search-input>\n@if (results && results.length) {\n <ul\n class=\"bg-gray-50 border border-gray-200 w-full mt-2 shadow-sm rounded-lg\"\n >\n @for (result of results; track result) {\n <li\n (click)=\"zoomToLocation(result)\"\n class=\"flex items-center pl-8 pr-4 py-2 border-b border-gray-200 relative cursor-pointer hover:bg-blue-100 hover:text-gray-800 transition duration-300 ease-in-out\"\n >\n <svg\n class=\"stroke-current text-blue-500 absolute w-5 h-5 left-3 top-3\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z\"\n />\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M15 11a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n <span class=\"font-sans font-semibold ml-4\">{{ result.label }}</span>\n </li>\n }\n </ul>\n}\n" }]
33024
- }], ctorParameters: () => [] });
33025
-
33026
32283
  /*
33027
32284
  Metadata actions
33028
32285
  */
@@ -38067,7 +37324,7 @@ class GenericKeywordsComponent {
38067
37324
  this.deletedKeyword.emit(keyword);
38068
37325
  }
38069
37326
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GenericKeywordsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38070
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: GenericKeywordsComponent, isStandalone: true, selector: "gn-ui-generic-keywords", inputs: { keywords: "keywords", keywordTypes: "keywordTypes", placeholder: "placeholder", allowSubmit: "allowSubmit" }, outputs: { changedKeywords: "changedKeywords", addedKeyword: "addedKeyword", deletedKeyword: "deletedKeyword" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\n <gn-ui-autocomplete\n [placeholder]=\"placeholder\"\n [displayWithFn]=\"displayWithFn\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleItemSelection($event)\"\n [preventCompleteOnSelection]=\"false\"\n [minCharacterCount]=\"1\"\n [allowSubmit]=\"false\"\n [clearOnSelection]=\"true\"\n ></gn-ui-autocomplete>\n <div class=\"flex gap-2 flex-wrap\">\n @for (keyword of keywords; track keyword) {\n <gn-ui-keyword-badge\n [keyword]=\"keyword\"\n [editable]=\"true\"\n (keywordRemove)=\"removeKeyword($event)\"\n ></gn-ui-keyword-badge>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: KeywordBadgeComponent, selector: "gn-ui-keyword-badge", inputs: ["keyword", "editable"], outputs: ["keywordClick", "keywordRemove"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
37327
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: GenericKeywordsComponent, isStandalone: true, selector: "gn-ui-generic-keywords", inputs: { keywords: "keywords", keywordTypes: "keywordTypes", placeholder: "placeholder", allowSubmit: "allowSubmit" }, outputs: { changedKeywords: "changedKeywords", addedKeyword: "addedKeyword", deletedKeyword: "deletedKeyword" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\n <gn-ui-autocomplete\n [placeholder]=\"placeholder\"\n [displayWithFn]=\"displayWithFn\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleItemSelection($event)\"\n [preventCompleteOnSelection]=\"false\"\n [minCharacterCount]=\"1\"\n [allowSubmit]=\"false\"\n [clearOnSelection]=\"true\"\n ></gn-ui-autocomplete>\n <div class=\"flex gap-2 flex-wrap\">\n @for (keyword of keywords; track keyword) {\n <gn-ui-keyword-badge\n [keyword]=\"keyword\"\n [editable]=\"true\"\n (keywordRemove)=\"removeKeyword($event)\"\n ></gn-ui-keyword-badge>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: KeywordBadgeComponent, selector: "gn-ui-keyword-badge", inputs: ["keyword", "editable"], outputs: ["keywordClick", "keywordRemove"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
38071
37328
  }
38072
37329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GenericKeywordsComponent, decorators: [{
38073
37330
  type: Component,
@@ -38659,7 +37916,7 @@ class FormFieldContactsForResourceComponent {
38659
37916
  provideNgIconsConfig({
38660
37917
  size: '1.5rem',
38661
37918
  }),
38662
- ], usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col gap-3\">\n <div class=\"flex flex-row flex-wrap gap-2\" data-test=\"rolesToPick\">\n @for (role of rolesToPick; track role) {\n <gn-ui-button type=\"gray\" (buttonClick)=\"addRoleToDisplay(role)\">\n <ng-icon name=\"iconoirPlus\" class=\"text-primary\"></ng-icon>\n &nbsp;\n <span translate>{{ roleToLabel(role) }}</span>\n </gn-ui-button>\n }\n </div>\n @if (value.length === 0) {\n <div\n class=\"p-4 border border-primary bg-primary-lightest rounded-lg\"\n translate\n >\n editor.record.form.field.contactsForResource.noContact\n </div>\n }\n @if (roleSectionsToDisplay && roleSectionsToDisplay.length > 0) {\n <div class=\"mt-8\" data-test=\"displayedRoles\">\n @for (\n role of roleSectionsToDisplay;\n track role;\n let index = $index;\n let isLast = $last\n ) {\n <div class=\"flex flex-col gap-4\">\n <div class=\"flex flex-row justify-between\">\n <span class=\"font-bold text-base\" translate>{{\n roleToLabel(role)\n }}</span>\n </div>\n @if (role !== 'unspecified' && role !== 'other') {\n <gn-ui-autocomplete\n [placeholder]=\"\n 'editor.record.form.field.contactsForResource.placeholder'\n | translate\n \"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"addContact($event, role)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"1\"\n [clearOnSelection]=\"true\"\n [allowSubmit]=\"false\"\n >\n </gn-ui-autocomplete>\n }\n @if (contactsForRessourceByRole.get(role); as contacts) {\n <gn-ui-sortable-list\n [items]=\"contacts\"\n (itemsOrderChange)=\"handleContactsChanged($event, role)\"\n [elementTemplate]=\"contactTemplate\"\n ></gn-ui-sortable-list>\n <ng-template #contactTemplate let-contact>\n <gn-ui-contact-card [contact]=\"contact\"></gn-ui-contact-card>\n </ng-template>\n }\n @if (!isLast) {\n <hr class=\"border-t-[#D6D3D1] mt-4 mb-6\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--gn-ui-button-padding: 8px 8px;--gn-ui-button-rounded: 8px}\n"], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: ContactCardComponent, selector: "gn-ui-contact-card", inputs: ["contact"] }, { kind: "component", type: SortableListComponent, selector: "gn-ui-sortable-list", inputs: ["elementTemplate", "items"], outputs: ["itemsOrderChange"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
37919
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col gap-3\">\n <div class=\"flex flex-row flex-wrap gap-2\" data-test=\"rolesToPick\">\n @for (role of rolesToPick; track role) {\n <gn-ui-button type=\"gray\" (buttonClick)=\"addRoleToDisplay(role)\">\n <ng-icon name=\"iconoirPlus\" class=\"text-primary\"></ng-icon>\n &nbsp;\n <span translate>{{ roleToLabel(role) }}</span>\n </gn-ui-button>\n }\n </div>\n @if (value.length === 0) {\n <div\n class=\"p-4 border border-primary bg-primary-lightest rounded-lg\"\n translate\n >\n editor.record.form.field.contactsForResource.noContact\n </div>\n }\n @if (roleSectionsToDisplay && roleSectionsToDisplay.length > 0) {\n <div class=\"mt-8\" data-test=\"displayedRoles\">\n @for (\n role of roleSectionsToDisplay;\n track role;\n let index = $index;\n let isLast = $last\n ) {\n <div class=\"flex flex-col gap-4\">\n <div class=\"flex flex-row justify-between\">\n <span class=\"font-bold text-base\" translate>{{\n roleToLabel(role)\n }}</span>\n </div>\n @if (role !== 'unspecified' && role !== 'other') {\n <gn-ui-autocomplete\n [placeholder]=\"\n 'editor.record.form.field.contactsForResource.placeholder'\n | translate\n \"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"addContact($event, role)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"1\"\n [clearOnSelection]=\"true\"\n [allowSubmit]=\"false\"\n >\n </gn-ui-autocomplete>\n }\n @if (contactsForRessourceByRole.get(role); as contacts) {\n <gn-ui-sortable-list\n [items]=\"contacts\"\n (itemsOrderChange)=\"handleContactsChanged($event, role)\"\n [elementTemplate]=\"contactTemplate\"\n ></gn-ui-sortable-list>\n <ng-template #contactTemplate let-contact>\n <gn-ui-contact-card [contact]=\"contact\"></gn-ui-contact-card>\n </ng-template>\n }\n @if (!isLast) {\n <hr class=\"border-t-[#D6D3D1] mt-4 mb-6\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--gn-ui-button-padding: 8px 8px;--gn-ui-button-rounded: 8px}\n"], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: ContactCardComponent, selector: "gn-ui-contact-card", inputs: ["contact"] }, { kind: "component", type: SortableListComponent, selector: "gn-ui-sortable-list", inputs: ["elementTemplate", "items"], outputs: ["itemsOrderChange"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
38663
37920
  }
38664
37921
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsForResourceComponent, decorators: [{
38665
37922
  type: Component,
@@ -38759,7 +38016,7 @@ class FormFieldContactsComponent {
38759
38016
  this.subscription.unsubscribe();
38760
38017
  }
38761
38018
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38762
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FormFieldContactsComponent, isStandalone: true, selector: "gn-ui-form-field-contacts", inputs: { value: "value", modelSpecifier: "modelSpecifier" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col gap-3\">\n <gn-ui-autocomplete\n [placeholder]=\"'editor.record.form.field.contacts.placeholder' | translate\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"addContact($event)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"1\"\n [clearOnSelection]=\"true\"\n >\n </gn-ui-autocomplete>\n\n @if (contacts.length > 0) {\n <gn-ui-sortable-list\n [items]=\"contacts\"\n (itemsOrderChange)=\"handleContactsChanged($event)\"\n [elementTemplate]=\"contactTemplate\"\n ></gn-ui-sortable-list>\n <ng-template #contactTemplate let-contact let-index=\"index\">\n @if (modelSpecifier === 'contact:editableDetails') {\n <gn-ui-contact-details-form\n [contact]=\"contact\"\n (contactChange)=\"handleContactChanged($event, index)\"\n ></gn-ui-contact-details-form>\n } @else {\n <gn-ui-contact-card [contact]=\"contact\"></gn-ui-contact-card>\n }\n </ng-template>\n } @else {\n <div\n class=\"p-4 text-sm border border-primary bg-primary-lightest rounded-lg\"\n translate\n >\n editor.record.form.field.contacts.noContact\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ContactCardComponent, selector: "gn-ui-contact-card", inputs: ["contact"] }, { kind: "component", type: ContactDetailsFormComponent, selector: "gn-ui-contact-details-form", inputs: ["contact"], outputs: ["contactChange"] }, { kind: "component", type: SortableListComponent, selector: "gn-ui-sortable-list", inputs: ["elementTemplate", "items"], outputs: ["itemsOrderChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
38019
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FormFieldContactsComponent, isStandalone: true, selector: "gn-ui-form-field-contacts", inputs: { value: "value", modelSpecifier: "modelSpecifier" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col gap-3\">\n <gn-ui-autocomplete\n [placeholder]=\"'editor.record.form.field.contacts.placeholder' | translate\"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"addContact($event)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"1\"\n [clearOnSelection]=\"true\"\n >\n </gn-ui-autocomplete>\n\n @if (contacts.length > 0) {\n <gn-ui-sortable-list\n [items]=\"contacts\"\n (itemsOrderChange)=\"handleContactsChanged($event)\"\n [elementTemplate]=\"contactTemplate\"\n ></gn-ui-sortable-list>\n <ng-template #contactTemplate let-contact let-index=\"index\">\n @if (modelSpecifier === 'contact:editableDetails') {\n <gn-ui-contact-details-form\n [contact]=\"contact\"\n (contactChange)=\"handleContactChanged($event, index)\"\n ></gn-ui-contact-details-form>\n } @else {\n <gn-ui-contact-card [contact]=\"contact\"></gn-ui-contact-card>\n }\n </ng-template>\n } @else {\n <div\n class=\"p-4 text-sm border border-primary bg-primary-lightest rounded-lg\"\n translate\n >\n editor.record.form.field.contacts.noContact\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ContactCardComponent, selector: "gn-ui-contact-card", inputs: ["contact"] }, { kind: "component", type: ContactDetailsFormComponent, selector: "gn-ui-contact-details-form", inputs: ["contact"], outputs: ["contactChange"] }, { kind: "component", type: SortableListComponent, selector: "gn-ui-sortable-list", inputs: ["elementTemplate", "items"], outputs: ["itemsOrderChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
38763
38020
  }
38764
38021
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsComponent, decorators: [{
38765
38022
  type: Component,
@@ -39112,7 +38369,7 @@ class OnlineServiceResourceInputComponent {
39112
38369
  provideNgIconsConfig({
39113
38370
  size: '1.5em',
39114
38371
  }),
39115
- ], ngImport: i0, template: "<div class=\"flex flex-row justify-between\">\n <h3 class=\"text-[16px] font-bold text-main mb-[12px]\" translate>\n editor.record.form.field.onlineResource.edit.protocol\n </h3>\n @if (protocolHint) {\n <ng-icon\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"protocolHint\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n }\n</div>\n<div class=\"flex flex-row items-center gap-4 h-[48px]\">\n <mat-radio-group\n aria-labelledby=\"example-radio-group-label\"\n class=\"flex flex-row gap-[8px]\"\n [(ngModel)]=\"_service.accessServiceProtocol\"\n [disabled]=\"disabled\"\n (change)=\"resetAllFormFields()\"\n >\n @for (protocolOption of availableProtocolOptions; track protocolOption) {\n <mat-radio-button [value]=\"protocolOption.value\">\n {{ protocolOption.label | translate }}\n </mat-radio-button>\n }\n </mat-radio-group>\n</div>\n\n<div class=\"flex flex-col gap-4\">\n <gn-ui-url-input\n class=\"w-full\"\n (uploadClick)=\"handleUploadClick($event)\"\n (valueChange)=\"handleUrlValueChange($event)\"\n [disabled]=\"disabled\"\n [value]=\"_service.url?.toString()\"\n [showValidateButton]=\"activeLayerSuggestion\"\n [resetUrlOnChange]=\"resetUrlOnChange\"\n >\n @if (activeLayerSuggestion) {\n <ng-content>\n <ng-icon name=\"iconoirRefresh\"></ng-icon>\n </ng-content>\n }\n </gn-ui-url-input>\n\n @if (loading) {\n <div class=\"flex justify-center w-full py-4\">\n <gn-ui-spinning-loader></gn-ui-spinning-loader>\n </div>\n }\n @if (errorMessage) {\n <p class=\"text-sm text-red-500 pl-4\" translate>\n editor.record.form.field.onlineResource.edit.identifier.error\n </p>\n }\n\n @if (\n !activeLayerSuggestion ||\n (_service.url && errorMessage) ||\n (modifyMode && (layers$ | async).length === 0)\n ) {\n <gn-ui-text-input\n class=\"grow border-b border-gray-300 pb-4\"\n [(value)]=\"_service.identifierInService\"\n [placeholder]=\"getIdentifierPlaceholder() | translate\"\n data-cy=\"identifier-in-service\"\n [disabled]=\"disabled\"\n ></gn-ui-text-input>\n }\n @if (activeLayerSuggestion && (layers$ | async)?.length > 0) {\n <gn-ui-autocomplete\n class=\"border-b border-gray-300 pb-4\"\n [placeholder]=\"\n 'editor.record.form.field.onlineResource.edit.identifier.select.label'\n | translate\n \"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleSelectValue($event)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"0\"\n [clearOnSelection]=\"false\"\n >\n </gn-ui-autocomplete>\n }\n @if (\n !modifyMode &&\n ((activeLayerSuggestion && (layers$ | async)) ||\n !activeLayerSuggestion ||\n (_service.url && errorMessage))\n ) {\n <gn-ui-button\n (buttonClick)=\"submit()\"\n [disabled]=\"disabled || !_service.identifierInService\"\n type=\"primary\"\n >\n <span class=\"text-white font-bold\" translate>\n editor.record.form.field.onlineResource.edit.identifier.submit</span\n >\n </gn-ui-button>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: SpinningLoaderComponent, selector: "gn-ui-spinning-loader" }, { kind: "component", type: TextInputComponent, selector: "gn-ui-text-input", inputs: ["value", "extraClass", "placeholder", "required", "disabled", "type"], outputs: ["valueChange"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: UrlInputComponent, selector: "gn-ui-url-input", inputs: ["value", "extraClass", "placeholder", "disabled", "showValidateButton", "resetUrlOnChange"], outputs: ["valueChange", "uploadClick"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
38372
+ ], ngImport: i0, template: "<div class=\"flex flex-row justify-between\">\n <h3 class=\"text-[16px] font-bold text-main mb-[12px]\" translate>\n editor.record.form.field.onlineResource.edit.protocol\n </h3>\n @if (protocolHint) {\n <ng-icon\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"protocolHint\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n }\n</div>\n<div class=\"flex flex-row items-center gap-4 h-[48px]\">\n <mat-radio-group\n aria-labelledby=\"example-radio-group-label\"\n class=\"flex flex-row gap-[8px]\"\n [(ngModel)]=\"_service.accessServiceProtocol\"\n [disabled]=\"disabled\"\n (change)=\"resetAllFormFields()\"\n >\n @for (protocolOption of availableProtocolOptions; track protocolOption) {\n <mat-radio-button [value]=\"protocolOption.value\">\n {{ protocolOption.label | translate }}\n </mat-radio-button>\n }\n </mat-radio-group>\n</div>\n\n<div class=\"flex flex-col gap-4\">\n <gn-ui-url-input\n class=\"w-full\"\n (uploadClick)=\"handleUploadClick($event)\"\n (valueChange)=\"handleUrlValueChange($event)\"\n [disabled]=\"disabled\"\n [value]=\"_service.url?.toString()\"\n [showValidateButton]=\"activeLayerSuggestion\"\n [resetUrlOnChange]=\"resetUrlOnChange\"\n >\n @if (activeLayerSuggestion) {\n <ng-content>\n <ng-icon name=\"iconoirRefresh\"></ng-icon>\n </ng-content>\n }\n </gn-ui-url-input>\n\n @if (loading) {\n <div class=\"flex justify-center w-full py-4\">\n <gn-ui-spinning-loader></gn-ui-spinning-loader>\n </div>\n }\n @if (errorMessage) {\n <p class=\"text-sm text-red-500 pl-4\" translate>\n editor.record.form.field.onlineResource.edit.identifier.error\n </p>\n }\n\n @if (\n !activeLayerSuggestion ||\n (_service.url && errorMessage) ||\n (modifyMode && (layers$ | async).length === 0)\n ) {\n <gn-ui-text-input\n class=\"grow border-b border-gray-300 pb-4\"\n [(value)]=\"_service.identifierInService\"\n [placeholder]=\"getIdentifierPlaceholder() | translate\"\n data-cy=\"identifier-in-service\"\n [disabled]=\"disabled\"\n ></gn-ui-text-input>\n }\n @if (activeLayerSuggestion && (layers$ | async)?.length > 0) {\n <gn-ui-autocomplete\n class=\"border-b border-gray-300 pb-4\"\n [placeholder]=\"\n 'editor.record.form.field.onlineResource.edit.identifier.select.label'\n | translate\n \"\n [action]=\"autoCompleteAction\"\n (itemSelected)=\"handleSelectValue($event)\"\n [displayWithFn]=\"displayWithFn\"\n [minCharacterCount]=\"0\"\n [clearOnSelection]=\"false\"\n >\n </gn-ui-autocomplete>\n }\n @if (\n !modifyMode &&\n ((activeLayerSuggestion && (layers$ | async)) ||\n !activeLayerSuggestion ||\n (_service.url && errorMessage))\n ) {\n <gn-ui-button\n (buttonClick)=\"submit()\"\n [disabled]=\"disabled || !_service.identifierInService\"\n type=\"primary\"\n >\n <span class=\"text-white font-bold\" translate>\n editor.record.form.field.onlineResource.edit.identifier.submit</span\n >\n </gn-ui-button>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: AutocompleteComponent, selector: "gn-ui-autocomplete", inputs: ["placeholder", "enterButton", "action", "value", "clearOnSelection", "preventCompleteOnSelection", "autoFocus", "minCharacterCount", "allowSubmit", "forceTrackPosition", "displayWithTemplate", "displayWithFn"], outputs: ["itemSelected", "inputSubmitted", "inputCleared", "isSearchActive"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: SpinningLoaderComponent, selector: "gn-ui-spinning-loader" }, { kind: "component", type: TextInputComponent, selector: "gn-ui-text-input", inputs: ["value", "extraClass", "placeholder", "required", "disabled", "type"], outputs: ["valueChange"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: UrlInputComponent, selector: "gn-ui-url-input", inputs: ["value", "extraClass", "placeholder", "disabled", "showValidateButton", "resetUrlOnChange"], outputs: ["valueChange", "uploadClick"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
39116
38373
  }
39117
38374
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OnlineServiceResourceInputComponent, decorators: [{
39118
38375
  type: Component,
@@ -40987,6 +40244,609 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
40987
40244
  args: ['gnUiSearchRouterContainer']
40988
40245
  }] } });
40989
40246
 
40247
+ const flatten = (base, obj, keepLevel = false) => Object.keys(obj).reduce((prev, curr) => {
40248
+ const path = base ? `${base}.${curr}` : curr;
40249
+ const val = obj[curr];
40250
+ if (keepLevel) {
40251
+ return { ...prev, [path]: flatten('', val) };
40252
+ }
40253
+ else if (typeof val === 'object' && !Array.isArray(val)) {
40254
+ return {
40255
+ ...prev,
40256
+ ...flatten(path, val),
40257
+ };
40258
+ }
40259
+ else {
40260
+ return { ...prev, [path]: val };
40261
+ }
40262
+ }, {});
40263
+ const checkKeys = (input, mandatory, optional) => {
40264
+ const keys = Object.keys(input);
40265
+ const missing = mandatory.filter((key) => keys.indexOf(key) === -1);
40266
+ const unrecognized = keys.filter((key) => mandatory.indexOf(key) === -1 && optional.indexOf(key) === -1);
40267
+ return {
40268
+ missing,
40269
+ unrecognized,
40270
+ };
40271
+ };
40272
+ /**
40273
+ * Only keeps recognized keys, flatten nested values (to allow having "." in keys),
40274
+ * pushes warnings and errors to the given arrays; returns null in case of error
40275
+ */
40276
+ function parseConfigSection(fullConfigObj, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors) {
40277
+ if (typeof fullConfigObj[sectionName] !== 'object') {
40278
+ if (mandatoryKeys.length === 0)
40279
+ return null;
40280
+ outErrors.push(`The [${sectionName}] mandatory section is missing.`);
40281
+ return null;
40282
+ }
40283
+ const sectionConf = fullConfigObj[sectionName];
40284
+ const keysCheck = checkKeys(sectionConf, mandatoryKeys, optionalKeys);
40285
+ if (keysCheck.missing.length) {
40286
+ // note: this is not thrown to allow merging several Errors down the line
40287
+ outErrors.push(`In the [${sectionName}] section: ${keysCheck.missing.join(', ')}`);
40288
+ return null;
40289
+ }
40290
+ else if (keysCheck.unrecognized.length) {
40291
+ outWarnings.push(`In the [${sectionName}] section: ${keysCheck.unrecognized.join(', ')}`);
40292
+ keysCheck.unrecognized.forEach((key) => delete sectionConf[key]);
40293
+ }
40294
+ return sectionConf;
40295
+ }
40296
+ /**
40297
+ * Same as parseConfigSection but keeps all keys, recognized or not
40298
+ * Also the first level is the language code (e.g. 'en')
40299
+ * This is optional
40300
+ */
40301
+ function parseTranslationsConfigSection(fullConfigObj, sectionName) {
40302
+ if (typeof fullConfigObj[sectionName] !== 'object') {
40303
+ return {};
40304
+ }
40305
+ return flatten('', fullConfigObj[sectionName], true);
40306
+ }
40307
+ /**
40308
+ * Same as parseConfigSection but handles an array of configs; this is
40309
+ * considered optional; returns null in case of error in at least one of
40310
+ * the sections
40311
+ */
40312
+ function parseMultiConfigSection(fullConfigObj, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors) {
40313
+ const sections = fullConfigObj[sectionName];
40314
+ if (!sections) {
40315
+ return [];
40316
+ }
40317
+ if (!Array.isArray(sections)) {
40318
+ outErrors.push(`Expected [[${sectionName}]] to be an array of sections.`);
40319
+ return null;
40320
+ }
40321
+ const result = sections.map((section) => parseConfigSection({ [sectionName]: section }, sectionName, mandatoryKeys, optionalKeys, outWarnings, outErrors));
40322
+ if (result.some((r) => r === null)) {
40323
+ return null;
40324
+ }
40325
+ return result;
40326
+ }
40327
+ function checkMetadataLanguage(parsedConfigSection, outWarnings) {
40328
+ const lang2 = toLang2(parsedConfigSection.metadata_language.toLowerCase());
40329
+ if (lang2?.length !== 2) {
40330
+ outWarnings.push(`In the [global] section: metadata_language = "${parsedConfigSection.metadata_language}" is not a recognized ISO 639 language code`);
40331
+ }
40332
+ return parsedConfigSection;
40333
+ }
40334
+ function checkNewRecordDefaultLanguage(parsedConfigSection, outWarnings) {
40335
+ const lang2 = toLang2(parsedConfigSection.new_record_default_language.toLowerCase());
40336
+ if (!(lang2 in LANG_2_TO_3_MAPPER)) {
40337
+ outWarnings.push(`In the [editing] section: new_record_default_language = "${parsedConfigSection.new_record_default_language}" is not a recognized ISO 639 language code`);
40338
+ return {
40339
+ ...parsedConfigSection,
40340
+ new_record_default_language: undefined,
40341
+ };
40342
+ }
40343
+ return {
40344
+ ...parsedConfigSection,
40345
+ new_record_default_language: lang2,
40346
+ };
40347
+ }
40348
+ function checkNewRecordStandard(parsedConfigSection, outWarnings) {
40349
+ const standard = parsedConfigSection.new_record_standard;
40350
+ const normalizedStandard = typeof standard === 'string' ? standard.trim().toLowerCase() : null;
40351
+ if (normalizedStandard === 'iso19139' ||
40352
+ normalizedStandard === 'iso19115-3') {
40353
+ return {
40354
+ ...parsedConfigSection,
40355
+ new_record_standard: normalizedStandard,
40356
+ };
40357
+ }
40358
+ outWarnings.push(`In the [editing] section: new_record_standard = "${standard}" is not a supported metadata standard`);
40359
+ return {
40360
+ ...parsedConfigSection,
40361
+ new_record_standard: undefined,
40362
+ };
40363
+ }
40364
+
40365
+ /**
40366
+ * This loader extends the default one based on JSON files but also loads custom translations
40367
+ * defined in the app configuration
40368
+ * Implements a fallback on default lang if translated labels are empty
40369
+ */
40370
+ class FileWithOverridesTranslateLoader extends FileTranslateLoader {
40371
+ getTranslation(lang) {
40372
+ const baseLang = lang.substring(0, 2); // removing the right part of e.g. en_EN
40373
+ return super.getTranslation(baseLang).pipe(map$1((translations) => ({
40374
+ ...translations,
40375
+ ...getCustomTranslations(baseLang),
40376
+ })));
40377
+ }
40378
+ }
40379
+
40380
+ const MISSING_CONFIG_ERROR = `Application configuration was not initialized correctly.
40381
+ This error might show up in case of an invalid/malformed configuration file.
40382
+
40383
+ Note: make sure that you have called \`loadAppConfig\` from '../../../../../libs/util/app-config/src' before starting the Angular application.`;
40384
+ let globalConfig = null;
40385
+ function getGlobalConfig() {
40386
+ if (globalConfig === null)
40387
+ throw new Error(MISSING_CONFIG_ERROR);
40388
+ return globalConfig;
40389
+ }
40390
+ let themeConfig = null;
40391
+ function getThemeConfig() {
40392
+ if (themeConfig === null)
40393
+ throw new Error(MISSING_CONFIG_ERROR);
40394
+ return themeConfig;
40395
+ }
40396
+ let mapConfig = null;
40397
+ function getOptionalMapConfig() {
40398
+ return mapConfig;
40399
+ }
40400
+ let searchConfig = null;
40401
+ function getOptionalSearchConfig() {
40402
+ return searchConfig;
40403
+ }
40404
+ let editorConfig = null;
40405
+ function getOptionalEditorConfig() {
40406
+ return editorConfig;
40407
+ }
40408
+ let metadataQualityConfig = null;
40409
+ function getMetadataQualityConfig() {
40410
+ return (metadataQualityConfig ||
40411
+ {
40412
+ ENABLED: false,
40413
+ });
40414
+ }
40415
+ let customTranslations = null;
40416
+ function getCustomTranslations(langCode) {
40417
+ if (customTranslations === null)
40418
+ throw new Error(MISSING_CONFIG_ERROR);
40419
+ return langCode in customTranslations ? customTranslations[langCode] : {};
40420
+ }
40421
+ let appConfigLoaded = false;
40422
+ function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
40423
+ console.log(`[geonetwork-ui] Loading application configuration from ${configUrl}`);
40424
+ return fetch(configUrl)
40425
+ .then((resp) => {
40426
+ if (!resp.ok)
40427
+ throw new Error('Configuration file could not be loaded');
40428
+ return resp.text();
40429
+ })
40430
+ .then((conf) => {
40431
+ let parsed;
40432
+ try {
40433
+ parsed = TOML.parse(conf, { joiner: '\n', bigint: false });
40434
+ }
40435
+ catch (e) {
40436
+ throw new Error(`An error occurred when parsing the configuration file: ${e.message}`);
40437
+ }
40438
+ const errors = [];
40439
+ const warnings = [];
40440
+ let parsedGlobalSection = parseConfigSection(parsed, 'global', ['geonetwork4_api_url'], [
40441
+ 'datahub_url',
40442
+ 'edit_url_template',
40443
+ 'proxy_path',
40444
+ 'metadata_language',
40445
+ 'login_url',
40446
+ 'logout_url',
40447
+ 'settings_url',
40448
+ 'web_component_embedder_url',
40449
+ 'languages',
40450
+ 'contact_email',
40451
+ 'reuse_form_url',
40452
+ ], warnings, errors);
40453
+ if (parsedGlobalSection?.metadata_language) {
40454
+ parsedGlobalSection = checkMetadataLanguage(parsedGlobalSection, warnings);
40455
+ }
40456
+ globalConfig =
40457
+ parsedGlobalSection === null
40458
+ ? null
40459
+ : {
40460
+ GN4_API_URL: parsedGlobalSection.geonetwork4_api_url,
40461
+ DATAHUB_URL: parsedGlobalSection.datahub_url,
40462
+ EDIT_URL_TEMPLATE: parsedGlobalSection.edit_url_template,
40463
+ PROXY_PATH: parsedGlobalSection.proxy_path,
40464
+ METADATA_LANGUAGE: parsedGlobalSection.metadata_language
40465
+ ? parsedGlobalSection.metadata_language.toLowerCase()
40466
+ : undefined,
40467
+ LOGIN_URL: parsedGlobalSection.login_url,
40468
+ LOGOUT_URL: parsedGlobalSection.logout_url,
40469
+ SETTINGS_URL: parsedGlobalSection.settings_url,
40470
+ WEB_COMPONENT_EMBEDDER_URL: parsedGlobalSection.web_component_embedder_url,
40471
+ LANGUAGES: parsedGlobalSection.languages,
40472
+ CONTACT_EMAIL: parsedGlobalSection.contact_email,
40473
+ REUSE_FORM_URL: parsedGlobalSection.reuse_form_url,
40474
+ };
40475
+ const parsedLayersSections = parseMultiConfigSection(parsed, 'map_layer', ['type'], ['name', 'url', 'data', 'styleUrl', 'accessToken'], warnings, errors);
40476
+ const parsedMapSection = parseConfigSection(parsed, 'map', [], [
40477
+ 'max_zoom',
40478
+ 'do_not_tile_wms',
40479
+ 'max_extent',
40480
+ 'max_feature_count',
40481
+ 'baselayer',
40482
+ 'do_not_use_default_basemap',
40483
+ 'external_viewer_url_template',
40484
+ 'external_viewer_open_new_tab',
40485
+ ], warnings, errors);
40486
+ mapConfig =
40487
+ parsedMapSection === null || parsedLayersSections === null
40488
+ ? null
40489
+ : {
40490
+ MAX_ZOOM: parsedMapSection.max_zoom,
40491
+ DO_NOT_TILE_WMS: parsedMapSection.do_not_tile_wms,
40492
+ MAX_EXTENT: parsedMapSection.max_extent,
40493
+ MAX_FEATURE_COUNT: parsedMapSection.max_feature_count,
40494
+ EXTERNAL_VIEWER_URL_TEMPLATE: parsedMapSection.external_viewer_url_template,
40495
+ EXTERNAL_VIEWER_OPEN_NEW_TAB: parsedMapSection.external_viewer_open_new_tab,
40496
+ DO_NOT_USE_DEFAULT_BASEMAP: !!parsedMapSection.do_not_use_default_basemap,
40497
+ MAP_LAYERS: parsedLayersSections.map((map_layer) => ({
40498
+ TYPE: map_layer.type,
40499
+ URL: map_layer.url,
40500
+ NAME: map_layer.name,
40501
+ DATA: map_layer.data,
40502
+ STYLE_URL: map_layer.styleUrl,
40503
+ ACCESS_TOKEN: map_layer.accessToken,
40504
+ })),
40505
+ };
40506
+ const parsedThemeSection = parseConfigSection(parsed, 'theme', ['primary_color', 'secondary_color', 'main_color', 'background_color'], [
40507
+ 'header_foreground_color',
40508
+ 'main_font',
40509
+ 'title_font',
40510
+ 'fonts_stylesheet_url',
40511
+ 'thumbnail_placeholder',
40512
+ 'header_background',
40513
+ 'favicon',
40514
+ ], warnings, errors);
40515
+ themeConfig =
40516
+ parsedThemeSection === null
40517
+ ? null
40518
+ : {
40519
+ PRIMARY_COLOR: parsedThemeSection.primary_color,
40520
+ SECONDARY_COLOR: parsedThemeSection.secondary_color,
40521
+ MAIN_COLOR: parsedThemeSection.main_color,
40522
+ BACKGROUND_COLOR: parsedThemeSection.background_color,
40523
+ HEADER_FOREGROUND_COLOR: parsedThemeSection.header_foreground_color,
40524
+ THUMBNAIL_PLACEHOLDER: parsedThemeSection.thumbnail_placeholder,
40525
+ HEADER_BACKGROUND: parsedThemeSection.header_background,
40526
+ TITLE_FONT: parsedThemeSection.title_font,
40527
+ MAIN_FONT: parsedThemeSection.main_font,
40528
+ FONTS_STYLESHEET_URL: parsedThemeSection.fonts_stylesheet_url,
40529
+ FAVICON: parsedThemeSection.favicon,
40530
+ };
40531
+ const parsedSearchSection = parseConfigSection(parsed, 'search', [], [
40532
+ 'record_kind_quick_filter',
40533
+ 'filter_geometry_data',
40534
+ 'filter_geometry_url',
40535
+ 'do_not_use_default_search_preset',
40536
+ 'search_preset',
40537
+ 'advanced_filters',
40538
+ 'limit',
40539
+ 'spatial_extent_max_file_size',
40540
+ 'geocoding_provider',
40541
+ 'geocoding_provider_options',
40542
+ ], warnings, errors);
40543
+ const parsedSearchParams = parseMultiConfigSection(parsed, 'search_preset', ['name'], ['sort', 'filters'], warnings, errors);
40544
+ const parsedCustomFilters = parseMultiConfigSection(parsed, 'custom_filter', ['name', 'base_filter'], ['exclude_values', 'include_values', 'label_key'], warnings, errors);
40545
+ searchConfig =
40546
+ parsedSearchSection === null
40547
+ ? null
40548
+ : {
40549
+ RECORD_KIND_QUICK_FILTER: parsedSearchSection.record_kind_quick_filter,
40550
+ FILTER_GEOMETRY_DATA: parsedSearchSection.filter_geometry_data,
40551
+ FILTER_GEOMETRY_URL: parsedSearchSection.filter_geometry_url,
40552
+ DO_NOT_USE_DEFAULT_SEARCH_PRESET: !!parsedSearchSection.do_not_use_default_search_preset,
40553
+ SEARCH_PRESET: parsedSearchParams.map((param) => ({
40554
+ sort: param.sort,
40555
+ name: param.name,
40556
+ filters: param.filters,
40557
+ })),
40558
+ ADVANCED_FILTERS: parsedSearchSection.advanced_filters,
40559
+ CUSTOM_FILTERS: parsedCustomFilters.map((customFilter) => ({
40560
+ name: customFilter.name,
40561
+ baseFilter: customFilter.base_filter,
40562
+ excludeValues: customFilter.exclude_values,
40563
+ includeValues: customFilter.include_values,
40564
+ labelKey: customFilter.label_key,
40565
+ })),
40566
+ LIMIT: parsedSearchSection.limit,
40567
+ SPATIAL_EXTENT_MAX_FILE_SIZE: parsedSearchSection.spatial_extent_max_file_size,
40568
+ GEOCODING_PROVIDER: parsedSearchSection.geocoding_provider,
40569
+ GEOCODING_PROVIDER_OPTIONS: parsedSearchSection.geocoding_provider_options,
40570
+ };
40571
+ const parsedMetadataQualitySection = parseConfigSection(parsed, 'metadata-quality', [], ['enabled'], warnings, errors);
40572
+ metadataQualityConfig =
40573
+ parsedMetadataQualitySection === null
40574
+ ? null
40575
+ : {
40576
+ ENABLED: parsedMetadataQualitySection.enabled,
40577
+ SORTABLE: parsedMetadataQualitySection.sortable,
40578
+ };
40579
+ let parsedEditingSection = parseConfigSection(parsed, 'editing', [], ['new_record_default_language', 'new_record_standard'], warnings, errors);
40580
+ if (parsedEditingSection !== null &&
40581
+ parsedEditingSection.new_record_default_language !== undefined) {
40582
+ parsedEditingSection = checkNewRecordDefaultLanguage(parsedEditingSection, warnings);
40583
+ }
40584
+ if (parsedEditingSection !== null &&
40585
+ parsedEditingSection.new_record_standard !== undefined) {
40586
+ parsedEditingSection = checkNewRecordStandard(parsedEditingSection, warnings);
40587
+ }
40588
+ editorConfig =
40589
+ parsedEditingSection === null
40590
+ ? null
40591
+ : {
40592
+ NEW_RECORD_DEFAULT_LANGUAGE: parsedEditingSection.new_record_default_language,
40593
+ NEW_RECORD_STANDARD: parsedEditingSection.new_record_standard,
40594
+ };
40595
+ customTranslations = parseTranslationsConfigSection(parsed, 'translations');
40596
+ if (errors.length) {
40597
+ throw new Error(`One or more mandatory settings were missing from the configuration file.
40598
+ ${errors.join('\n')}`);
40599
+ }
40600
+ else if (warnings.length) {
40601
+ console.warn(`One or more unexpected settings were encountered in the configuration file.
40602
+ ${warnings.join('\n')}`);
40603
+ }
40604
+ appConfigLoaded = true;
40605
+ });
40606
+ }
40607
+ function isConfigLoaded() {
40608
+ return appConfigLoaded;
40609
+ }
40610
+ function _reset() {
40611
+ globalConfig = null;
40612
+ themeConfig = null;
40613
+ editorConfig = null;
40614
+ customTranslations = null;
40615
+ }
40616
+ const TRANSLATE_WITH_OVERRIDES_CONFIG = {
40617
+ compiler: {
40618
+ provide: TranslateCompiler,
40619
+ useClass: TranslateMessageFormatCompiler,
40620
+ },
40621
+ loader: [
40622
+ {
40623
+ provide: TRANSLATE_HTTP_LOADER_CONFIG,
40624
+ useValue: {
40625
+ prefix: './assets/i18n/',
40626
+ suffix: '.json',
40627
+ },
40628
+ },
40629
+ {
40630
+ provide: TranslateLoader,
40631
+ useClass: FileWithOverridesTranslateLoader,
40632
+ deps: [HttpClient, TRANSLATE_HTTP_LOADER_CONFIG],
40633
+ },
40634
+ ],
40635
+ };
40636
+
40637
+ const okAppConfigFixture = () => `
40638
+ [global]
40639
+ geonetwork4_api_url = "/geonetwork/srv/api"
40640
+ proxy_path = "/proxy/?url="
40641
+ metadata_language = "fre"
40642
+ login_url = "/cas/login?service="
40643
+ logout_url = "/geonetwork/signout"
40644
+ settings_url = "/geonetwork/settings"
40645
+ web_component_embedder_url = "/datahub/wc-embedder.html"
40646
+
40647
+ [map]
40648
+ max_zoom = 10
40649
+ max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855]
40650
+ do_not_use_default_basemap = false
40651
+ external_viewer_url_template = 'https://example.com/myviewer?'
40652
+ external_viewer_open_new_tab = true
40653
+ [[map_layer]]
40654
+ type = "wms"
40655
+ url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
40656
+ name = "masque_hdf_ign_carto_latin1"
40657
+ [[map_layer]]
40658
+ type = "wfs"
40659
+ url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
40660
+ name = "masque_hdf_ign_carto_latin1"
40661
+
40662
+ [theme]
40663
+ primary_color = "#093564"
40664
+ secondary_color = "#c2e9dc"
40665
+ main_color = "#212029" # All-purpose text color
40666
+ background_color = "#fdfbff"
40667
+ thumbnail_placeholder = 'assets/img/placeholder.svg'
40668
+ header_background = 'teal'
40669
+ header_foreground_color = "#872e2e"
40670
+ main_font = 'sans-serif'
40671
+ title_font = 'serif'
40672
+ fonts_stylesheet_url = "https://fonts.googleapis.com/css2?family=Open+Sans"
40673
+
40674
+ [search]
40675
+ record_kind_quick_filter = false
40676
+ filter_geometry_url = 'https://my.domain.org/geom.json'
40677
+ do_not_use_default_search_preset = false
40678
+ geocoding_provider = "geoplateforme"
40679
+ geocoding_provider_options.category = "administratif"
40680
+ geocoding_provider_options.limit = 5
40681
+ advanced_filters = ['publicationYear', 'documentStandard', 'inspireKeyword', 'topic', 'license', 'myOrg:firstCustomFilter', 'myOrg:secondCustomFilter']
40682
+
40683
+ [[custom_filter]]
40684
+ name = 'myOrg:firstCustomFilter'
40685
+ base_filter = 'keyword'
40686
+ exclude_values = ['my keyword 1', 'my keyword 2']
40687
+ label_key = 'myOrg.firstCustomFilter'
40688
+
40689
+ [[custom_filter]]
40690
+ name = 'myOrg:secondCustomFilter'
40691
+ base_filter = 'keyword'
40692
+ include_values = ['my keyword 3', 'my keyword 4']
40693
+ label_key = 'myOrg.secondCustomFilter'
40694
+
40695
+ [[search_preset]]
40696
+ sort = "-createDate"
40697
+ name = 'filterByOrgs'
40698
+ filters.q = 'Carto'
40699
+ filters.organisation = ['Org1', 'Org2']
40700
+ filters.format = ['ESRI Shapefile']
40701
+ filters.topic = ['boundaries']
40702
+ filters.publicationYear = ['2023', '2022']
40703
+ filters.spatial = ['yes']
40704
+
40705
+ [translations.en]
40706
+ "my.first.key" = 'First label.'
40707
+ "my.second.key" = """
40708
+ Second label,
40709
+ on two lines."""
40710
+
40711
+ [translations.de]
40712
+ my.first.key = 'Erste Etikett.'
40713
+
40714
+ [translations.fr]
40715
+ my.sample.text = "Un bon exemple de texte."
40716
+ "my.quoted.text" = 'du texte entre guillements.'
40717
+ `;
40718
+ const appConfigWithTranslationFixture = () => okAppConfigFixture();
40719
+ const minimalAppConfigFixture = () => `
40720
+ [global]
40721
+ geonetwork4_api_url = "/geonetwork/srv/api"
40722
+ proxy_path = "/proxy/?url="
40723
+
40724
+ [theme]
40725
+ primary_color = "#093564"
40726
+ secondary_color = "#c2e9dc"
40727
+ main_color = "#212029" # All-purpose text color
40728
+ background_color = "#fdfbff"
40729
+ `;
40730
+ const mapConfigFixture = () => ({
40731
+ MAX_ZOOM: 10,
40732
+ MAX_EXTENT: [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855],
40733
+ DO_NOT_USE_DEFAULT_BASEMAP: false,
40734
+ DO_NOT_TILE_WMS: false,
40735
+ EXTERNAL_VIEWER_URL_TEMPLATE: 'https://example.com/myviewer/#/?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["${layer_name}"],"sources":[{"url":"${service_url}","type":"${service_type}"}]}]',
40736
+ EXTERNAL_VIEWER_OPEN_NEW_TAB: true,
40737
+ MAP_LAYERS: [
40738
+ {
40739
+ TYPE: 'xyz',
40740
+ URL: 'https://some-basemap-server',
40741
+ },
40742
+ {
40743
+ TYPE: 'wms',
40744
+ URL: 'https://some-wms-server',
40745
+ NAME: 'some_layername',
40746
+ },
40747
+ {
40748
+ TYPE: 'wfs',
40749
+ URL: 'https://some-wfs-server',
40750
+ NAME: 'some_layername',
40751
+ },
40752
+ ],
40753
+ });
40754
+ const malformedConfigFixture = () => `
40755
+ {
40756
+ "I thought": "we were still doing json"
40757
+ }
40758
+ `;
40759
+ const missingMandatoryConfigFixture = () => `
40760
+ [theme]
40761
+ primary_color = "#093564"
40762
+ secondary_color = "#c2e9dc"
40763
+ background_color = "#fdfbff"
40764
+ main_font = 'sans-serif'
40765
+ `;
40766
+ const wrongLanguageCodeConfigFixture = () => `
40767
+ [global]
40768
+ geonetwork4_api_url = "/geonetwork/srv/api"
40769
+ proxy_path = "/proxy/?url="
40770
+ metadata_language = "abc"
40771
+
40772
+ [map]
40773
+
40774
+ [theme]
40775
+ primary_color = "#093564"
40776
+ secondary_color = "#c2e9dc"
40777
+ main_color = "#212029" # All-purpose text color
40778
+ background_color = "#fdfbff"
40779
+ `;
40780
+ const unrecognizedKeysConfigFixture = () => `
40781
+ [global]
40782
+ geonetwork4_api_url = "/geonetwork/srv/api"
40783
+ proxy_path = "/proxy/?url="
40784
+ metadata_language = "fre"
40785
+ another_path = '/whatever'
40786
+
40787
+ [map]
40788
+ max_zoom = 10
40789
+ max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855]
40790
+ do_not_use_default_basemap = false
40791
+ external_viewer_url_template = 'https://example.com/myviewer?'
40792
+ external_viewer_open_new_tab = true
40793
+ another_zoom = 15
40794
+ [[map_layer]]
40795
+ type = "wms"
40796
+ url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
40797
+ name = "masque_hdf_ign_carto_latin1"
40798
+ [[map_layer]]
40799
+ type = "wfs"
40800
+ url = "https://www.geo2france.fr/geoserver/cr_hdf/ows"
40801
+ name = "masque_hdf_ign_carto_latin1"
40802
+ another_layer = "wrong layer definition"
40803
+
40804
+ [theme]
40805
+ primary_color = "#093564"
40806
+ secondary_color = "#c2e9dc"
40807
+ main_color = "#212029" # All-purpose text color
40808
+ background_color = "#fdfbff"
40809
+ thumbnail_placeholder = 'assets/img/placeholder.svg'
40810
+ header_background = 'teal'
40811
+ header_foreground_color = "#872e2e"
40812
+ main_font = 'sans-serif'
40813
+ title_font = 'serif'
40814
+ another_color = 'red'
40815
+ `;
40816
+
40817
+ function getMapContextLayerFromConfig(config) {
40818
+ switch (config.TYPE) {
40819
+ case 'wms':
40820
+ return {
40821
+ type: 'wms',
40822
+ url: config.URL,
40823
+ name: config.NAME,
40824
+ };
40825
+ case 'wfs':
40826
+ return {
40827
+ type: 'wfs',
40828
+ url: config.URL,
40829
+ featureType: config.NAME,
40830
+ };
40831
+ case 'xyz':
40832
+ return {
40833
+ type: config.TYPE,
40834
+ url: config.URL,
40835
+ };
40836
+ case 'geojson':
40837
+ return {
40838
+ type: config.TYPE,
40839
+ ...(config.DATA ? { data: config.DATA } : { url: config.URL }),
40840
+ };
40841
+ case 'maplibre-style':
40842
+ return {
40843
+ type: config.TYPE,
40844
+ styleUrl: config.STYLE_URL,
40845
+ accessToken: config.ACCESS_TOKEN,
40846
+ };
40847
+ }
40848
+ }
40849
+
40990
40850
  const CHART_TYPE_VALUES = [
40991
40851
  'bar',
40992
40852
  'bar-horizontal',
@@ -41002,5 +40862,5 @@ const CHART_TYPE_VALUES = [
41002
40862
  * Generated bundle index. Do not edit.
41003
40863
  */
41004
40864
 
41005
- export { ADD_RESULTS, ADD_SEARCH, AVAILABLE_LICENSES, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AutofocusDirective, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, BoundingBoxSearchField, ButtonComponent, CHART_TYPE_VALUES, CLEAR_ERROR, CLEAR_RESULTS, CarouselComponent, CatalogTitleComponent, CellPopinComponent, ChartComponent, ChartViewComponent, CheckToggleComponent, CheckboxComponent, ClearError, ClearResults, ColorScaleComponent, ConfirmationDialogComponent, ContactDetailsComponent, ContactDetailsFormComponent, ContactPillComponent, ContentGhostComponent, CopyTextButtonComponent, DEFAULT_BASEMAP_LAYER, DEFAULT_CONFIGURATION, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RECORD_CONVERTER, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DEFAULT_SPATIAL_EXTENT_STYLE, DISABLE_AUTH, DISABLE_DRAFT, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldFocusDirective, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingComponent, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, I18nInterceptor, ISO_TOPICS, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KeywordBadgeComponent, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, MAX_UPLOAD_SIZE_MB, METADATA_LANGUAGE, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapStyleService, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, OPEN_DATA_LICENSE, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OnlineResourceCardComponent, OnlineServiceResourceInputComponent, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_DATASET_URL_TOKEN, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESULTS_LAYOUT_CONFIG, REUSE_LIGHT_CONFIGURATION, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordStatusValues, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, ResourceCreationRevisionDateSearchField, ResourceTypeLegacyField, ResultsHitsContainerComponent, ResultsHitsNumberComponent, ResultsHitsSearchKindComponent, ResultsLayoutComponent, ResultsLayoutConfigItem, ResultsListComponent, ResultsListContainerComponent, ResultsListItemComponent, ResultsTableComponent, ResultsTableContainerComponent, ReusePresentationForms, RoleLabels, RoleValues, RouterEffects, RouterFacade, RouterService, SEARCH_FEATURE_KEY, SETTINGS_URL, SET_CONFIG_AGGREGATIONS, SET_CONFIG_FILTERS, SET_CONFIG_REQUEST_FIELDS, SET_ERROR, SET_FAVORITES_ONLY, SET_FILTERS, SET_INCLUDE_ON_AGGREGATION, SET_PAGE_SIZE, SET_RESULTS_AGGREGATIONS, SET_RESULTS_HITS, SET_RESULTS_LAYOUT, SET_SEARCH, SET_SORT_BY, SET_SPATIAL_FILTER_ENABLED, SPATIAL_SCOPES, SearchEffects, SearchFacade, SearchFeatureCatalogComponent, SearchFiltersSummaryComponent, SearchFiltersSummaryItemComponent, SearchInputComponent, SearchRouterContainerDirective, SearchService, SearchStateContainerDirective, SelectionService, ServiceCapabilitiesComponent, SetConfigAggregations, SetConfigFilters, SetConfigRequestFields, SetError, SetFavoritesOnly, SetFilters, SetIncludeOnAggregation, SetPageSize, SetResultsAggregations, SetResultsHits, SetResultsLayout, SetSearch, SetSortBy, SetSpatialFilterEnabled, SimpleSearchField, SiteTitleComponent, SortByComponent, SortByEnum, SortableListComponent, SourceLabelComponent, SourcesService, SpatialExtentComponent, SpatialExtentDropdownComponent, SpinningLoaderComponent, StacItemsResultGridComponent, StacViewComponent, StarToggleComponent, StickyHeaderComponent, SupportedTypes, SwitchToggleComponent, THUMBNAIL_PLACEHOLDER, TRANSLATE_DEBUG_CONFIG, TRANSLATE_DEFAULT_CONFIG, TRANSLATE_WITH_OVERRIDES_CONFIG, TableViewComponent, TextAreaComponent, TextInputComponent, ThemeService, ThumbnailComponent, TranslatedSearchField, TruncatedTextComponent, UPDATE_CONFIG_AGGREGATIONS, UPDATE_FILTERS, UPDATE_REQUEST_AGGREGATION_TERM, UpdateConfigAggregations, UpdateFilters, UrlInputComponent, UserFeedbackItemComponent, UserPreviewComponent, UserSearchField, VECTOR_STYLE_DEFAULT, ViewportIntersectorComponent, WEB_COMPONENT_EMBEDDER_URL, XmlParseError, _reset, allChildrenElement, appConfigWithTranslationFixture, appendChildTree, appendChildren, assertValidXml, associationTypeValues, bboxToPolygon, blockModelFixture, bytesToMegabytes, canEditRecord, checkFileFormat, clearSelectedFeatures, createChild, createDocument, createElement, createFuzzyFilter, createNestedChild, createNestedElement, createSpatialExtentLayer, currentPage, defaultMapStyleFixture, defaultMapStyleHlFixture, downgradeImage, downsizeImage, draftSaveSuccess, dragPanCondition, dropEmptyTranslations, editorReducer, emptyBlockModelFixture, findChildElement, findChildOrCreate, findChildrenElement, findConverterForDocument, findNestedChildOrCreate, findNestedElement, findNestedElements, findParent, firstChildElement, formatDate, formatUserInfo, getAddressLines, getAllKeysValidator, getArrayItem, getAsArray, getAsUrl, getBadgeColor, getCustomTranslations, getError, getFavoritesOnly, getFileFormat, getFileFormatFromServiceOutput, getFirstValue, getFormatPriority, getGeometryBoundingBox, getGeometryFromGeoJSON, getGlobalConfig, getIndividualDisplayName, getIsMobile, getJsonDataItemsProxy, getKeywordHierarchyPath, getLayers, getLinkId, getLinkLabel, getLinkPriority, getMapContext, getMapContextLayerFromConfig, getMapState, getMetadataQualityConfig, getMimeTypeForFormat, getNamespace, getOptionalEditorConfig, getOptionalMapConfig, getOptionalSearchConfig, getPageSize, getQualityValidators, getResourceType, getReusePresentationForm, getReuseType, getRootElement, getSearchConfigAggregations, getSearchFilters, getSearchResults, getSearchResultsAggregations, getSearchResultsHits, getSearchResultsLayout, getSearchResultsLoading, getSearchSortBy, getSearchState, getSearchStateSearch, getSelectedFeatures, getSpatialFilterEnabled, getTemporalRangeUnion, getThemeConfig, handleScrollOnNavigation, hasRecordChangedSinceDraft, hasRecordChangedSinceDraftSuccess, initSearch, initialEditorState, initialMapState, initialState, isBoundingBox, isConfigLoaded, isDateRange, isFileExtensionValid, isFormatInQueryParam, isPublished, itemModelFixture, kindToCodeListValue, loadAppConfig, malformedConfigFixture, mapConfigFixture, mapContact, mapKeywords, mapLogo, mapOrganization, mapReducer, markRecordAsChanged, matchesNoApplicableConstraint, matchesNoKnownConstraint, megabytesToBytes, mimeTypeToFormat, minimalAppConfigFixture, missingMandatoryConfigFixture, mouseWheelZoomCondition, noDuplicateFileName, okAppConfigFixture, openDataset, openRecord, organizationsServiceFactory, parse, parseXmlString, placeholder, prioritizePageScroll, propagateToDocumentOnly, provideGn4, provideI18n, provideLocalizedDateAdapter, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, readFileAsText, readText, reducer$2 as reducer, reducerSearch, removeAllChildren, removeChildren, removeChildrenByName, removeSearchParams, removeWhitespace, renameElements, saveRecord, saveRecordFailure, saveRecordSuccess, selectCanEditRecord, selectCurrentPage, selectEditorConfig, selectEditorState, selectFallback, selectFallbackFields, selectField, selectHasRecordChanged, selectIsPublished, selectRecord, selectRecordChangedSinceSave, selectRecordSaveError, selectRecordSaving, selectRecordSections, selectRecordSource, selectTranslatedField, selectTranslatedValue, setContext, setCurrentPage, setEditorConfiguration, setFieldVisibility, setFocusedField, setSelectedFeatures, setTextContent, sortByFromString, sortByToString, sortByToStrings, spatialExtentToGeometry, spatialExtentsToFeatureCollection, stripHtml, stripNamespace, toDate, toIndividual, toLang2, toLang3, totalPages, undoRecordDraft, unrecognizedKeysConfigFixture, updateFrequencyCodeValues, updateLanguages, updateRecordField, updateRecordLanguages, wmsLayerFlatten, writeAttribute, wrongLanguageCodeConfigFixture, xmlToString };
40865
+ export { ADD_RESULTS, ADD_SEARCH, AVAILABLE_LICENSES, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AutofocusDirective, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, BoundingBoxSearchField, ButtonComponent, CHART_TYPE_VALUES, CLEAR_ERROR, CLEAR_RESULTS, CarouselComponent, CatalogTitleComponent, CellPopinComponent, ChartComponent, ChartViewComponent, CheckToggleComponent, CheckboxComponent, ClearError, ClearResults, ColorScaleComponent, ConfirmationDialogComponent, ContactDetailsComponent, ContactDetailsFormComponent, ContactPillComponent, ContentGhostComponent, CopyTextButtonComponent, DEFAULT_BASEMAP_LAYER, DEFAULT_CONFIGURATION, DEFAULT_GEOCODING_PROVIDER, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RECORD_CONVERTER, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DEFAULT_SPATIAL_EXTENT_STYLE, DISABLE_AUTH, DISABLE_DRAFT, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldFocusDirective, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEOCODING_PROVIDER, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingService, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, I18nInterceptor, ISO_TOPICS, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KeywordBadgeComponent, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LocationSearchComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, MAX_UPLOAD_SIZE_MB, METADATA_LANGUAGE, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, OPEN_DATA_LICENSE, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OnlineResourceCardComponent, OnlineServiceResourceInputComponent, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_DATASET_URL_TOKEN, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESULTS_LAYOUT_CONFIG, REUSE_LIGHT_CONFIGURATION, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordStatusValues, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, ResourceCreationRevisionDateSearchField, ResourceTypeLegacyField, ResultsHitsContainerComponent, ResultsHitsNumberComponent, ResultsHitsSearchKindComponent, ResultsLayoutComponent, ResultsLayoutConfigItem, ResultsListComponent, ResultsListContainerComponent, ResultsListItemComponent, ResultsTableComponent, ResultsTableContainerComponent, ReusePresentationForms, RoleLabels, RoleValues, RouterEffects, RouterFacade, RouterService, SEARCH_FEATURE_KEY, SETTINGS_URL, SET_CONFIG_AGGREGATIONS, SET_CONFIG_FILTERS, SET_CONFIG_REQUEST_FIELDS, SET_ERROR, SET_FAVORITES_ONLY, SET_FILTERS, SET_INCLUDE_ON_AGGREGATION, SET_PAGE_SIZE, SET_RESULTS_AGGREGATIONS, SET_RESULTS_HITS, SET_RESULTS_LAYOUT, SET_SEARCH, SET_SORT_BY, SET_SPATIAL_FILTER_ENABLED, SPATIAL_EXTENT_MAX_FILE_SIZE, SPATIAL_SCOPES, SearchEffects, SearchFacade, SearchFeatureCatalogComponent, SearchFiltersSummaryComponent, SearchFiltersSummaryItemComponent, SearchInputComponent, SearchRouterContainerDirective, SearchService, SearchStateContainerDirective, SelectionService, ServiceCapabilitiesComponent, SetConfigAggregations, SetConfigFilters, SetConfigRequestFields, SetError, SetFavoritesOnly, SetFilters, SetIncludeOnAggregation, SetPageSize, SetResultsAggregations, SetResultsHits, SetResultsLayout, SetSearch, SetSortBy, SetSpatialFilterEnabled, SimpleSearchField, SiteTitleComponent, SortByComponent, SortByEnum, SortableListComponent, SourceLabelComponent, SourcesService, SpatialExtentComponent, SpatialExtentDropdownComponent, SpinningLoaderComponent, StacItemsResultGridComponent, StacViewComponent, StarToggleComponent, StickyHeaderComponent, SupportedTypes, SwitchToggleComponent, THUMBNAIL_PLACEHOLDER, TRANSLATE_DEBUG_CONFIG, TRANSLATE_DEFAULT_CONFIG, TRANSLATE_WITH_OVERRIDES_CONFIG, TableViewComponent, TextAreaComponent, TextInputComponent, ThemeService, ThumbnailComponent, TranslatedSearchField, TruncatedTextComponent, UPDATE_CONFIG_AGGREGATIONS, UPDATE_FILTERS, UPDATE_REQUEST_AGGREGATION_TERM, UpdateConfigAggregations, UpdateFilters, UrlInputComponent, UserFeedbackItemComponent, UserPreviewComponent, UserSearchField, VECTOR_STYLE_DEFAULT, ViewportIntersectorComponent, WEB_COMPONENT_EMBEDDER_URL, XmlParseError, _reset, allChildrenElement, appConfigWithTranslationFixture, appendChildTree, appendChildren, assertValidXml, associationTypeValues, bboxToPolygon, blockModelFixture, bytesToMegabytes, canEditRecord, checkFileFormat, clearSelectedFeatures, createChild, createDocument, createElement, createFuzzyFilter, createNestedChild, createNestedElement, createSpatialExtentLayer, currentPage, downgradeImage, downsizeImage, draftSaveSuccess, dragPanCondition, dropEmptyTranslations, editorReducer, emptyBlockModelFixture, findChildElement, findChildOrCreate, findChildrenElement, findConverterForDocument, findNestedChildOrCreate, findNestedElement, findNestedElements, findParent, firstChildElement, formatDate, formatUserInfo, getAddressLines, getAllKeysValidator, getArrayItem, getAsArray, getAsUrl, getBadgeColor, getCustomTranslations, getError, getFavoritesOnly, getFileFormat, getFileFormatFromServiceOutput, getFirstValue, getFormatPriority, getGeometryBoundingBox, getGeometryFromGeoJSON, getGlobalConfig, getIndividualDisplayName, getIsMobile, getJsonDataItemsProxy, getKeywordHierarchyPath, getLayers, getLinkId, getLinkLabel, getLinkPriority, getMapContext, getMapContextLayerFromConfig, getMapState, getMetadataQualityConfig, getMimeTypeForFormat, getNamespace, getOptionalEditorConfig, getOptionalMapConfig, getOptionalSearchConfig, getPageSize, getQualityValidators, getResourceType, getReusePresentationForm, getReuseType, getRootElement, getSearchConfigAggregations, getSearchFilters, getSearchResults, getSearchResultsAggregations, getSearchResultsHits, getSearchResultsLayout, getSearchResultsLoading, getSearchSortBy, getSearchState, getSearchStateSearch, getSelectedFeatures, getSpatialFilterEnabled, getTemporalRangeUnion, getThemeConfig, handleScrollOnNavigation, hasRecordChangedSinceDraft, hasRecordChangedSinceDraftSuccess, initSearch, initialEditorState, initialMapState, initialState, isBoundingBox, isBoundingBoxWithinWorldExtent, isConfigLoaded, isDateRange, isFileExtensionValid, isFormatInQueryParam, isPublished, itemModelFixture, kindToCodeListValue, loadAppConfig, malformedConfigFixture, mapConfigFixture, mapContact, mapKeywords, mapLogo, mapOrganization, mapReducer, markRecordAsChanged, matchesNoApplicableConstraint, matchesNoKnownConstraint, megabytesToBytes, mimeTypeToFormat, minimalAppConfigFixture, missingMandatoryConfigFixture, mouseWheelZoomCondition, noDuplicateFileName, okAppConfigFixture, openDataset, openRecord, organizationsServiceFactory, parse, parseXmlString, placeholder, prioritizePageScroll, propagateToDocumentOnly, provideGn4, provideI18n, provideLocalizedDateAdapter, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, readFileAsText, readText, reducer$2 as reducer, reducerSearch, removeAllChildren, removeChildren, removeChildrenByName, removeSearchParams, removeWhitespace, renameElements, saveRecord, saveRecordFailure, saveRecordSuccess, selectCanEditRecord, selectCurrentPage, selectEditorConfig, selectEditorState, selectFallback, selectFallbackFields, selectField, selectHasRecordChanged, selectIsPublished, selectRecord, selectRecordChangedSinceSave, selectRecordSaveError, selectRecordSaving, selectRecordSections, selectRecordSource, selectTranslatedField, selectTranslatedValue, setContext, setCurrentPage, setEditorConfiguration, setFieldVisibility, setFocusedField, setSelectedFeatures, setTextContent, sortByFromString, sortByToString, sortByToStrings, spatialExtentToGeometry, spatialExtentsToFeatureCollection, stripHtml, stripNamespace, toDate, toIndividual, toLang2, toLang3, totalPages, undoRecordDraft, unrecognizedKeysConfigFixture, updateFrequencyCodeValues, updateLanguages, updateRecordField, updateRecordLanguages, wmsLayerFlatten, writeAttribute, wrongLanguageCodeConfigFixture, xmlToString };
41006
40866
  //# sourceMappingURL=geonetwork-ui.mjs.map