geonetwork-ui 2.11.0-dev.8442dae6e → 2.11.0-dev.8aa6985e0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/geonetwork-ui.mjs +1572 -869
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +314 -128
- package/index.d.ts.map +1 -1
- package/package.json +12 -11
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -13
- package/src/libs/api/metadata-converter/src/lib/gn4/types/elasticsearch.model.ts +13 -1
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +130 -37
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +40 -16
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +22 -0
- package/src/libs/common/domain/src/lib/model/search/filter.model.ts +20 -1
- package/src/libs/common/domain/src/lib/model/search/sort-by.model.ts +1 -5
- package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +2 -2
- package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +3 -2
- package/src/libs/feature/dataviz/src/lib/geo-table-view/geo-table-view.component.ts +2 -1
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +22 -22
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.html +33 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.ts +94 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.html +16 -12
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +6 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +6 -0
- package/src/libs/feature/editor/src/lib/fields.config.ts +5 -0
- package/src/libs/feature/map/src/index.ts +0 -1
- package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.html +1 -0
- package/src/libs/feature/map/src/lib/feature-map.module.ts +1 -8
- package/src/libs/feature/notifications/src/lib/notifications.service.ts +6 -4
- package/src/libs/feature/record/src/lib/state/mdview.actions.ts +4 -8
- package/src/libs/feature/record/src/lib/state/mdview.effects.ts +7 -16
- package/src/libs/feature/record/src/lib/state/mdview.facade.ts +1 -3
- package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +4 -9
- package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +2 -7
- package/src/libs/feature/router/src/lib/default/router.service.ts +1 -1
- package/src/libs/feature/router/src/lib/default/state/query-params.utils.ts +1 -1
- package/src/libs/feature/search/src/index.ts +2 -0
- package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.html +12 -4
- package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.ts +58 -19
- package/src/libs/feature/{map/src/lib → search/src/lib/geocoding}/geocoding.service.ts +16 -7
- package/src/libs/feature/search/src/lib/location-search/location-search.component.html +8 -0
- package/src/libs/feature/search/src/lib/location-search/location-search.component.ts +40 -0
- package/src/libs/feature/search/src/lib/search-filters-summary-item/search-filters-summary-item.component.ts +18 -8
- package/src/libs/feature/search/src/lib/sort-by/sort-by.component.ts +1 -1
- package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +9 -1
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +61 -2
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.html +6 -7
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.ts +31 -19
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.fixtures.ts +2 -2
- package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.ts +2 -1
- package/src/libs/ui/inputs/src/index.ts +2 -0
- package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.html +10 -1
- package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +8 -0
- package/src/libs/ui/inputs/src/lib/date-adapter.providers.ts +30 -0
- package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +3 -24
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.css +37 -3
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.html +135 -16
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.ts +166 -29
- package/src/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.ts +3 -7
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.css +1 -0
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.html +20 -7
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.ts +46 -5
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +7 -4
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.ts +12 -9
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.model.ts +2 -2
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.css +0 -0
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.html +111 -0
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.ts +221 -0
- package/src/libs/ui/layout/src/lib/block-list/block-list.component.css +1 -0
- package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +6 -5
- package/src/libs/util/app-config/src/lib/app-config.ts +23 -0
- package/src/libs/util/app-config/src/lib/fixtures.ts +16 -1
- package/src/libs/util/app-config/src/lib/model.ts +15 -1
- package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +19 -22
- package/src/libs/util/data-fetcher/src/lib/engine/duckdb.ts +185 -0
- package/src/libs/util/data-fetcher/src/lib/engine/results.ts +63 -0
- package/src/libs/util/data-fetcher/src/lib/{sql-utils.ts → engine/sql-utils.ts} +28 -13
- package/src/libs/util/data-fetcher/src/lib/model.ts +2 -1
- package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +53 -38
- package/src/libs/util/data-fetcher/src/lib/readers/base.ts +11 -0
- package/src/libs/util/data-fetcher/src/lib/readers/csv.ts +9 -47
- package/src/libs/util/data-fetcher/src/lib/readers/excel.ts +27 -27
- package/src/libs/util/data-fetcher/src/lib/readers/geojson.ts +5 -24
- package/src/libs/util/data-fetcher/src/lib/readers/gml.ts +5 -49
- package/src/libs/util/data-fetcher/src/lib/readers/json.ts +5 -23
- package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +184 -128
- package/src/libs/util/data-fetcher/src/lib/utils.ts +0 -143
- package/src/libs/util/shared/src/index.ts +1 -0
- package/src/libs/util/shared/src/lib/autofocus.directive.ts +26 -0
- package/src/libs/util/shared/src/lib/links/link-utils.ts +19 -10
- package/src/libs/util/shared/src/lib/services/date.service.ts +3 -3
- package/src/libs/util/shared/src/lib/utils/file.ts +15 -0
- package/src/libs/util/shared/src/lib/utils/geojson.ts +24 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/tailwind.base.css +5 -0
- package/translations/de.json +31 -4
- package/translations/en.json +30 -3
- package/translations/es.json +28 -1
- package/translations/fr.json +31 -4
- package/translations/it.json +29 -2
- package/translations/nl.json +28 -1
- package/translations/pt.json +28 -1
- package/translations/sk.json +29 -2
- package/src/libs/feature/map/src/lib/geocoding/geocoding.component.html +0 -41
- package/src/libs/feature/map/src/lib/geocoding/geocoding.component.ts +0 -112
- package/src/libs/util/data-fetcher/src/lib/readers/base-cache.ts +0 -14
- /package/src/libs/feature/{map/src/lib/geocoding/geocoding.component.css → editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.css} +0 -0
|
@@ -6,9 +6,9 @@ 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, combineLatest, from, exhaustMap, throwError,
|
|
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
|
-
import { InjectionToken, inject, Injectable, NgModule, Injector, provideAppInitializer, makeEnvironmentProviders, ElementRef,
|
|
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';
|
|
13
13
|
import * as i4 from '@ngx-translate/core';
|
|
14
14
|
import { TranslateLoader, TranslateCompiler, TranslateDefaultParser, TranslateParser, TranslateService, provideTranslateService, TranslateDirective, TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
|
@@ -18,7 +18,7 @@ import { map as map$1, shareReplay as shareReplay$1, catchError, tap as tap$1, f
|
|
|
18
18
|
import { lt, valid, coerce, satisfies, ltr } from 'semver';
|
|
19
19
|
import chroma from 'chroma-js';
|
|
20
20
|
import * as i1$1 from '@angular/common';
|
|
21
|
-
import { Location, CommonModule,
|
|
21
|
+
import { Location, CommonModule, NgTemplateOutlet, NgClass, AsyncPipe } from '@angular/common';
|
|
22
22
|
import { formatDistance } from 'date-fns/formatDistance';
|
|
23
23
|
import { Scroll, NavigationEnd, Router, RouteReuseStrategy } from '@angular/router';
|
|
24
24
|
import { WmtsEndpoint, WmsEndpoint, WfsEndpoint, OgcApiEndpoint, sharedFetch, useCache, StacEndpoint, TmsEndpoint } from '@camptocamp/ogc-client';
|
|
@@ -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';
|
|
@@ -41,10 +40,10 @@ import * as TOML from '@ltd/j-toml';
|
|
|
41
40
|
import { Style, Stroke, Fill, Circle } from 'ol/style.js';
|
|
42
41
|
import CircleStyle from 'ol/style/Circle.js';
|
|
43
42
|
import EmblaCarousel from 'embla-carousel';
|
|
44
|
-
import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, 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,
|
|
43
|
+
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
44
|
import { MatButtonModule } from '@angular/material/button';
|
|
46
|
-
import * as i1$
|
|
47
|
-
import {
|
|
45
|
+
import * as i1$7 from '@angular/cdk/overlay';
|
|
46
|
+
import { ScrollStrategyOptions, OverlayModule, CdkConnectedOverlay, ScrollDispatcher, Overlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
|
48
47
|
import * as i1$3 from '@angular/forms';
|
|
49
48
|
import { UntypedFormControl, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
50
49
|
import * as i1$2 from '@angular/material/autocomplete';
|
|
@@ -52,16 +51,18 @@ import { MatAutocompleteModule, MatAutocompleteTrigger, MatAutocomplete } from '
|
|
|
52
51
|
import tippy from 'tippy.js';
|
|
53
52
|
import * as i2 from '@angular/material/progress-spinner';
|
|
54
53
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
55
|
-
import { matClose, matContentCopy,
|
|
54
|
+
import { matClose, matContentCopy, matExpandMore, matExpandLess, matSearch, matStarBorder, matStar, matRemove, matAdd, matChevronRight, matChevronLeft, matArrowForwardIos, matArrowBackIos, matMoodBad, matQuestionMark, matFace, matZoomOutMap, matOpenInNew, matPersonOutline, matMailOutline, matWarningAmber, matCheck, matCheckCircleOutline, matWarning, matMoreVert } from '@ng-icons/material-icons/baseline';
|
|
56
55
|
import * as i1$4 from '@angular/material/checkbox';
|
|
57
56
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
58
57
|
import * as i1$5 from '@angular/material/tooltip';
|
|
59
58
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
60
|
-
import {
|
|
59
|
+
import { MAT_DATE_LOCALE, MAT_DATE_FORMATS, DateAdapter } from '@angular/material/core';
|
|
60
|
+
import { MAT_DATE_FNS_FORMATS, DateFnsAdapter } from '@angular/material-date-fns-adapter';
|
|
61
|
+
import { enUS } from 'date-fns/locale/en-US';
|
|
61
62
|
import * as i1$6 from '@angular/material/datepicker';
|
|
62
63
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
63
|
-
import * as i1$
|
|
64
|
-
import { NgxDropzoneModule } from 'ngx-dropzone';
|
|
64
|
+
import * as i1$8 from 'ngx-dropzone';
|
|
65
|
+
import { NgxDropzoneModule, NgxDropzoneComponent } from 'ngx-dropzone';
|
|
65
66
|
import * as i1$9 from '@angular/material/button-toggle';
|
|
66
67
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
67
68
|
import { moveItemInArray, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
|
@@ -72,6 +73,7 @@ import { MatTabsModule } from '@angular/material/tabs';
|
|
|
72
73
|
import * as i2$2 from '@ngrx/effects';
|
|
73
74
|
import { Actions, createEffect, ofType, EffectsModule } from '@ngrx/effects';
|
|
74
75
|
import { valid as valid$1 } from 'geojson-validation';
|
|
76
|
+
import { queryGeoplateforme, queryGeonames, queryGeoadmin } from '@geospatial-sdk/geocoding';
|
|
75
77
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
76
78
|
import { parse as parse$3 } from 'marked';
|
|
77
79
|
import * as i2$3 from '@angular/cdk/scrolling';
|
|
@@ -79,10 +81,10 @@ import { ScrollingModule, CdkScrollable } from '@angular/cdk/scrolling';
|
|
|
79
81
|
import Duration from 'duration-relativetimeformat';
|
|
80
82
|
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
|
81
83
|
import { trigger, transition, animate, keyframes, style } from '@angular/animations';
|
|
82
|
-
import * as
|
|
83
|
-
import {
|
|
84
|
-
import
|
|
85
|
-
import
|
|
84
|
+
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
85
|
+
import { Vector, DataType } from 'apache-arrow';
|
|
86
|
+
import WFS from 'ol/format/WFS';
|
|
87
|
+
import GeoJSON$1 from 'ol/format/GeoJSON';
|
|
86
88
|
import { Chart, BarController, BarElement, CategoryScale, LinearScale, LineController, LineElement, PointElement, PieController, ArcElement, ScatterController, Tooltip, Colors, Legend } from 'chart.js';
|
|
87
89
|
import * as i2$4 from '@angular/material/sort';
|
|
88
90
|
import { MatSortModule, MatSort } from '@angular/material/sort';
|
|
@@ -90,7 +92,6 @@ import * as i1$b from '@angular/material/table';
|
|
|
90
92
|
import { MatTableModule } from '@angular/material/table';
|
|
91
93
|
import * as i3 from '@angular/material/paginator';
|
|
92
94
|
import { MatPaginatorIntl, MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
|
|
93
|
-
import { LetDirective } from '@ngrx/component';
|
|
94
95
|
import { Meta } from '@angular/platform-browser';
|
|
95
96
|
import { tablerFolderOpen } from '@ng-icons/tabler-icons';
|
|
96
97
|
import * as i3$1 from '@angular/material/radio';
|
|
@@ -788,6 +789,15 @@ marker('record.metadata.api.accessServiceProtocol.maplibre-style');
|
|
|
788
789
|
marker('record.metadata.api.accessServiceProtocol.postgis');
|
|
789
790
|
marker('record.metadata.api.accessServiceProtocol.stac');
|
|
790
791
|
marker('record.metadata.api.accessServiceProtocol.other');
|
|
792
|
+
marker('domain.record.associationType.crossReference');
|
|
793
|
+
marker('domain.record.associationType.largerWorkCitation');
|
|
794
|
+
marker('domain.record.associationType.partOfSeamlessDatabase');
|
|
795
|
+
marker('domain.record.associationType.stereoMate');
|
|
796
|
+
marker('domain.record.associationType.isComposedOf');
|
|
797
|
+
marker('domain.record.associationType.collectiveTitle');
|
|
798
|
+
marker('domain.record.associationType.series');
|
|
799
|
+
marker('domain.record.associationType.dependency');
|
|
800
|
+
marker('domain.record.associationType.revisionOf');
|
|
791
801
|
// DS_AssociationTypeCode values of the ISO19115-3 codelist, any unrecognized value
|
|
792
802
|
// being mapped to 'crossReference'
|
|
793
803
|
const associationTypeValues = [
|
|
@@ -18898,14 +18908,29 @@ class Gn4FieldMapper {
|
|
|
18898
18908
|
featureTypes: selectField(source, 'featureTypes'),
|
|
18899
18909
|
}, output),
|
|
18900
18910
|
related: (output, source) => {
|
|
18901
|
-
const
|
|
18911
|
+
const related = selectField(source, 'related');
|
|
18912
|
+
const fcatSource = selectField(getFirstValue(selectField(related, 'fcats')) ?? {}, '_source');
|
|
18902
18913
|
const featureCatalogIdentifier = selectField(fcatSource, 'uuid');
|
|
18903
|
-
const sourceOfLinks = getAsArray(selectField(
|
|
18914
|
+
const sourceOfLinks = getAsArray(selectField(related, 'hassources'));
|
|
18904
18915
|
const sourceOfIdentifiers = sourceOfLinks
|
|
18905
18916
|
.filter((link) => link['origin'] === 'catalog')
|
|
18906
18917
|
.map((link) => {
|
|
18907
18918
|
return selectField(selectField(link, '_source'), 'uuid');
|
|
18908
18919
|
});
|
|
18920
|
+
const siblingLinks = getAsArray(selectField(related, 'siblings'));
|
|
18921
|
+
const siblings = siblingLinks
|
|
18922
|
+
.filter((link) => link['origin'] === 'catalog')
|
|
18923
|
+
.map((link) => ({
|
|
18924
|
+
uniqueIdentifier: selectField(selectField(link, '_source'), 'uuid'),
|
|
18925
|
+
associationType: getAssociationTypeFromCode(selectField(selectField(link, 'properties'), 'associationType')),
|
|
18926
|
+
}));
|
|
18927
|
+
const associatedLinks = getAsArray(selectField(related, 'associated'));
|
|
18928
|
+
const associatedIdentifiers = associatedLinks
|
|
18929
|
+
.filter((link) => link['origin'] === 'catalog')
|
|
18930
|
+
.map((link) => {
|
|
18931
|
+
return selectField(selectField(link, '_source'), 'uuid');
|
|
18932
|
+
})
|
|
18933
|
+
.filter((uuid) => !siblings.some((sibling) => sibling.uniqueIdentifier === uuid));
|
|
18909
18934
|
const extraValues = {};
|
|
18910
18935
|
if (featureCatalogIdentifier) {
|
|
18911
18936
|
extraValues.featureCatalogIdentifier = featureCatalogIdentifier;
|
|
@@ -18913,6 +18938,12 @@ class Gn4FieldMapper {
|
|
|
18913
18938
|
if (sourceOfIdentifiers && sourceOfIdentifiers.length > 0) {
|
|
18914
18939
|
extraValues.sourceOfIdentifiers = sourceOfIdentifiers;
|
|
18915
18940
|
}
|
|
18941
|
+
if (associatedIdentifiers && associatedIdentifiers.length > 0) {
|
|
18942
|
+
extraValues.associatedIdentifiers = associatedIdentifiers;
|
|
18943
|
+
}
|
|
18944
|
+
if (siblings && siblings.length > 0) {
|
|
18945
|
+
extraValues.siblings = siblings;
|
|
18946
|
+
}
|
|
18916
18947
|
return Object.keys(extraValues).length > 0
|
|
18917
18948
|
? this.addExtra(extraValues, output)
|
|
18918
18949
|
: output;
|
|
@@ -19438,10 +19469,10 @@ class DateService {
|
|
|
19438
19469
|
const dateObj = this.getDateObject(date);
|
|
19439
19470
|
return { locale, dateObj };
|
|
19440
19471
|
}
|
|
19441
|
-
async
|
|
19472
|
+
async getDateFnsLocale() {
|
|
19442
19473
|
const lang = this.translateService.getCurrentLang() || DEFAULT_LANGUAGE;
|
|
19443
19474
|
const locales = await this.dateLocales;
|
|
19444
|
-
return locales[lang];
|
|
19475
|
+
return locales[lang] ?? locales[DEFAULT_LANGUAGE];
|
|
19445
19476
|
}
|
|
19446
19477
|
formatDate(date, options) {
|
|
19447
19478
|
const { locale, dateObj } = this.getLocaleAndDate(date);
|
|
@@ -19454,7 +19485,7 @@ class DateService {
|
|
|
19454
19485
|
async formatRelativeDateTime(date) {
|
|
19455
19486
|
const dateObj = this.getDateObject(date);
|
|
19456
19487
|
const now = new Date();
|
|
19457
|
-
const locale = await this.
|
|
19488
|
+
const locale = await this.getDateFnsLocale();
|
|
19458
19489
|
return formatDistance(dateObj, now, {
|
|
19459
19490
|
addSuffix: true,
|
|
19460
19491
|
locale: locale,
|
|
@@ -19489,6 +19520,18 @@ function propagateToDocumentOnly(event) {
|
|
|
19489
19520
|
}, 0);
|
|
19490
19521
|
}
|
|
19491
19522
|
|
|
19523
|
+
function isFileExtensionValid(fileName, acceptedExtensions) {
|
|
19524
|
+
return acceptedExtensions.some((ext) => fileName.toLowerCase().endsWith(ext));
|
|
19525
|
+
}
|
|
19526
|
+
function readFileAsText(file) {
|
|
19527
|
+
return new Promise((resolve, reject) => {
|
|
19528
|
+
const reader = new FileReader();
|
|
19529
|
+
reader.onload = () => resolve(reader.result);
|
|
19530
|
+
reader.onerror = () => reject(reader.error);
|
|
19531
|
+
reader.readAsText(file);
|
|
19532
|
+
});
|
|
19533
|
+
}
|
|
19534
|
+
|
|
19492
19535
|
function formatUserInfo(userInfo, displayCount = false) {
|
|
19493
19536
|
const infos = (typeof userInfo === 'string' ? userInfo : '').split('|');
|
|
19494
19537
|
const count = displayCount ? ` ${infos[3].split(' ')[1]}` : '';
|
|
@@ -19548,6 +19591,24 @@ function getGeometryFromGeoJSON(data) {
|
|
|
19548
19591
|
}
|
|
19549
19592
|
return null;
|
|
19550
19593
|
}
|
|
19594
|
+
function isBoundingBox(value) {
|
|
19595
|
+
return (Array.isArray(value) &&
|
|
19596
|
+
value.length === 4 &&
|
|
19597
|
+
value.every((item) => typeof item === 'number'));
|
|
19598
|
+
}
|
|
19599
|
+
/**
|
|
19600
|
+
* Checks that a bounding box's coordinates stay within the valid
|
|
19601
|
+
* longitude (-180/180) and latitude (-90/90) ranges.
|
|
19602
|
+
*/
|
|
19603
|
+
function isBoundingBoxWithinWorldExtent(bbox) {
|
|
19604
|
+
const [minX, minY, maxX, maxY] = bbox;
|
|
19605
|
+
return (minX >= -180 &&
|
|
19606
|
+
maxX <= 180 &&
|
|
19607
|
+
minY >= -90 &&
|
|
19608
|
+
maxY <= 90 &&
|
|
19609
|
+
minX <= maxX &&
|
|
19610
|
+
minY <= maxY);
|
|
19611
|
+
}
|
|
19551
19612
|
function getGeometryBoundingBox(geometry) {
|
|
19552
19613
|
// use the bounding box if specified in the GeoJSON object
|
|
19553
19614
|
if (geometry.bbox) {
|
|
@@ -20216,7 +20277,7 @@ function getLinkLabel(link) {
|
|
|
20216
20277
|
const label = link.description || ('name' in link ? link.name : '');
|
|
20217
20278
|
return format ? `${label} (${format})` : label;
|
|
20218
20279
|
}
|
|
20219
|
-
async function getLayers(url, serviceProtocol) {
|
|
20280
|
+
async function getLayers(url, serviceProtocol, deep = false) {
|
|
20220
20281
|
switch (serviceProtocol) {
|
|
20221
20282
|
case 'ogcFeatures': {
|
|
20222
20283
|
const layers = await new OgcApiEndpoint(url).allCollections;
|
|
@@ -20224,7 +20285,10 @@ async function getLayers(url, serviceProtocol) {
|
|
|
20224
20285
|
}
|
|
20225
20286
|
case 'wfs': {
|
|
20226
20287
|
const endpointWfs = await new WfsEndpoint(url).isReady();
|
|
20227
|
-
const featureTypes =
|
|
20288
|
+
const featureTypes = endpointWfs.getFeatureTypes();
|
|
20289
|
+
if (!deep) {
|
|
20290
|
+
return featureTypes;
|
|
20291
|
+
}
|
|
20228
20292
|
const layers = (await Promise.allSettled(featureTypes.map((collection) => {
|
|
20229
20293
|
return endpointWfs.getFeatureTypeFull(collection.name);
|
|
20230
20294
|
})))
|
|
@@ -20234,12 +20298,14 @@ async function getLayers(url, serviceProtocol) {
|
|
|
20234
20298
|
}
|
|
20235
20299
|
case 'wms': {
|
|
20236
20300
|
const endpointWms = await new WmsEndpoint(url).isReady();
|
|
20237
|
-
const
|
|
20301
|
+
const layersSummary = endpointWms
|
|
20238
20302
|
.getLayers()
|
|
20239
20303
|
.flatMap(wmsLayerFlatten)
|
|
20240
|
-
.filter((l) => l.name)
|
|
20241
|
-
|
|
20242
|
-
|
|
20304
|
+
.filter((l) => l.name);
|
|
20305
|
+
if (!deep) {
|
|
20306
|
+
return layersSummary;
|
|
20307
|
+
}
|
|
20308
|
+
const layers = layersSummary.map((collection) => endpointWms.getLayerByName(collection.name));
|
|
20243
20309
|
return layers;
|
|
20244
20310
|
}
|
|
20245
20311
|
case 'wmts': {
|
|
@@ -20333,6 +20399,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
20333
20399
|
}]
|
|
20334
20400
|
}] });
|
|
20335
20401
|
|
|
20402
|
+
class AutofocusDirective {
|
|
20403
|
+
constructor() {
|
|
20404
|
+
this.el = inject(ElementRef);
|
|
20405
|
+
this.injector = inject(Injector);
|
|
20406
|
+
}
|
|
20407
|
+
set autofocus(active) {
|
|
20408
|
+
if (!active)
|
|
20409
|
+
return;
|
|
20410
|
+
afterNextRender(() => this.el.nativeElement.focus(), {
|
|
20411
|
+
injector: this.injector,
|
|
20412
|
+
});
|
|
20413
|
+
}
|
|
20414
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutofocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
20415
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.19", type: AutofocusDirective, isStandalone: true, selector: "[gnUiAutofocus]", inputs: { autofocus: ["gnUiAutofocus", "autofocus", booleanAttribute] }, ngImport: i0 }); }
|
|
20416
|
+
}
|
|
20417
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutofocusDirective, decorators: [{
|
|
20418
|
+
type: Directive,
|
|
20419
|
+
args: [{
|
|
20420
|
+
selector: '[gnUiAutofocus]',
|
|
20421
|
+
standalone: true,
|
|
20422
|
+
}]
|
|
20423
|
+
}], propDecorators: { autofocus: [{
|
|
20424
|
+
type: Input,
|
|
20425
|
+
args: [{ alias: 'gnUiAutofocus', transform: booleanAttribute }]
|
|
20426
|
+
}] } });
|
|
20427
|
+
|
|
20336
20428
|
class ImageFallbackDirective {
|
|
20337
20429
|
constructor() {
|
|
20338
20430
|
this.el = inject(ElementRef);
|
|
@@ -20360,7 +20452,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
20360
20452
|
}] } });
|
|
20361
20453
|
|
|
20362
20454
|
var name = "geonetwork-ui";
|
|
20363
|
-
var version = "2.11.0-dev.
|
|
20455
|
+
var version = "2.11.0-dev.8aa6985e0";
|
|
20364
20456
|
var engines = {
|
|
20365
20457
|
node: ">=24"
|
|
20366
20458
|
};
|
|
@@ -20381,6 +20473,7 @@ var peerDependencies = {
|
|
|
20381
20473
|
"@angular/core": "19.x || 20.x || 21.x",
|
|
20382
20474
|
"@angular/forms": "19.x || 20.x || 21.x",
|
|
20383
20475
|
"@angular/material": "19.x || 20.x || 21.x",
|
|
20476
|
+
"@angular/material-date-fns-adapter": "19.x || 20.x",
|
|
20384
20477
|
"@angular/platform-browser": "19.x || 20.x || 21.x",
|
|
20385
20478
|
"@angular/platform-browser-dynamic": "19.x || 20.x || 21.x",
|
|
20386
20479
|
"@angular/router": "19.x || 20.x || 21.x",
|
|
@@ -20390,20 +20483,21 @@ var peerDependencies = {
|
|
|
20390
20483
|
"@ngrx/store": "19.x || 20.x || 21.x",
|
|
20391
20484
|
"@ngrx/store-devtools": "19.x || 20.x || 21.x",
|
|
20392
20485
|
"@ngrx/operators": "19.x || 20.x || 21.x",
|
|
20393
|
-
"@ngx-translate/core": "
|
|
20394
|
-
"@ngx-translate/http-loader": "
|
|
20395
|
-
"flag-icons": "
|
|
20486
|
+
"@ngx-translate/core": "17.x",
|
|
20487
|
+
"@ngx-translate/http-loader": "17.x",
|
|
20488
|
+
"flag-icons": "~7.5.0",
|
|
20396
20489
|
rxjs: "7.x",
|
|
20397
20490
|
"zone.js": "*",
|
|
20398
20491
|
tailwindcss: "3.x"
|
|
20399
20492
|
};
|
|
20400
20493
|
var dependencies = {
|
|
20401
20494
|
"@biesbjerg/ngx-translate-extract-marker": "~1.0.0",
|
|
20402
|
-
"@camptocamp/ogc-client": "1.3.1-dev.
|
|
20403
|
-
"@
|
|
20404
|
-
"@geospatial-sdk/
|
|
20405
|
-
"@geospatial-sdk/
|
|
20406
|
-
"@geospatial-sdk/
|
|
20495
|
+
"@camptocamp/ogc-client": "1.3.1-dev.200c02a",
|
|
20496
|
+
"@duckdb/duckdb-wasm": "~1.32.0",
|
|
20497
|
+
"@geospatial-sdk/core": "0.0.5-dev.78",
|
|
20498
|
+
"@geospatial-sdk/geocoding": "0.0.5-dev.78",
|
|
20499
|
+
"@geospatial-sdk/legend": "0.0.5-dev.78",
|
|
20500
|
+
"@geospatial-sdk/openlayers": "0.0.5-dev.78",
|
|
20407
20501
|
"@ltd/j-toml": "~1.38.0",
|
|
20408
20502
|
"@messageformat/core": "~3.4.0",
|
|
20409
20503
|
"@ng-icons/core": "~32.5.0",
|
|
@@ -20411,7 +20505,7 @@ var dependencies = {
|
|
|
20411
20505
|
"@ng-icons/material-icons": "~32.5.0",
|
|
20412
20506
|
"@ng-icons/tabler-icons": "~32.4.0",
|
|
20413
20507
|
"@rgrove/parse-xml": "4.2.0",
|
|
20414
|
-
|
|
20508
|
+
"apache-arrow": "~17.0.0",
|
|
20415
20509
|
"chart.js": "~4.5.1",
|
|
20416
20510
|
"chroma-js": "~3.2.0",
|
|
20417
20511
|
"date-fns": "4.1.0",
|
|
@@ -20424,7 +20518,6 @@ var dependencies = {
|
|
|
20424
20518
|
"ngx-dropzone": "~3.1.0",
|
|
20425
20519
|
"ngx-translate-messageformat-compiler": "~7.2.0",
|
|
20426
20520
|
ol: "~10.8.0",
|
|
20427
|
-
papaparse: "~5.5.3",
|
|
20428
20521
|
proj4: "~2.20.4",
|
|
20429
20522
|
rdflib: "~2.3.5",
|
|
20430
20523
|
semver: "~7.7.4",
|
|
@@ -20622,8 +20715,8 @@ class ElasticsearchService {
|
|
|
20622
20715
|
if (!payload.runtime_mappings)
|
|
20623
20716
|
payload.runtime_mappings = {};
|
|
20624
20717
|
payload.runtime_mappings[fieldName] = {
|
|
20625
|
-
type:
|
|
20626
|
-
script: this.runtimeFields[fieldName],
|
|
20718
|
+
type: this.runtimeFields[fieldName].type,
|
|
20719
|
+
script: this.runtimeFields[fieldName].script,
|
|
20627
20720
|
};
|
|
20628
20721
|
};
|
|
20629
20722
|
const lookForField = (node) => {
|
|
@@ -20643,6 +20736,12 @@ class ElasticsearchService {
|
|
|
20643
20736
|
(node[runtimeField] === 'asc' || node[runtimeField] === 'desc')) {
|
|
20644
20737
|
addMapping(runtimeField);
|
|
20645
20738
|
}
|
|
20739
|
+
if (runtimeField in node &&
|
|
20740
|
+
typeof node[runtimeField] === 'object' &&
|
|
20741
|
+
node[runtimeField] !== null &&
|
|
20742
|
+
('gte' in node[runtimeField] || 'lte' in node[runtimeField])) {
|
|
20743
|
+
addMapping(runtimeField);
|
|
20744
|
+
}
|
|
20646
20745
|
if ('query' in node &&
|
|
20647
20746
|
typeof node.query === 'string' &&
|
|
20648
20747
|
node.query.indexOf(runtimeField + ':') > -1) {
|
|
@@ -20659,8 +20758,8 @@ class ElasticsearchService {
|
|
|
20659
20758
|
lookForField(payload.query);
|
|
20660
20759
|
return payload;
|
|
20661
20760
|
}
|
|
20662
|
-
registerRuntimeField(fieldName, expression) {
|
|
20663
|
-
this.runtimeFields[fieldName] = expression;
|
|
20761
|
+
registerRuntimeField(fieldName, expression, type = 'keyword') {
|
|
20762
|
+
this.runtimeFields[fieldName] = { script: expression, type };
|
|
20664
20763
|
}
|
|
20665
20764
|
getMetadataByIdsPayload(uuids) {
|
|
20666
20765
|
return {
|
|
@@ -20669,6 +20768,7 @@ class ElasticsearchService {
|
|
|
20669
20768
|
values: uuids,
|
|
20670
20769
|
},
|
|
20671
20770
|
},
|
|
20771
|
+
size: uuids.length,
|
|
20672
20772
|
};
|
|
20673
20773
|
}
|
|
20674
20774
|
getRelatedRecordPayload(record, size = 6, _source = [...ES_SOURCE_SUMMARY, 'createDate']) {
|
|
@@ -20719,10 +20819,28 @@ class ElasticsearchService {
|
|
|
20719
20819
|
};
|
|
20720
20820
|
}
|
|
20721
20821
|
buildPayloadSort(sortBy) {
|
|
20722
|
-
if (sortBy ===
|
|
20822
|
+
if (!sortBy || sortBy.length === 0)
|
|
20723
20823
|
return undefined;
|
|
20724
|
-
const fields = Array.isArray(sortBy[0])
|
|
20725
|
-
|
|
20824
|
+
const fields = Array.isArray(sortBy[0])
|
|
20825
|
+
? sortBy
|
|
20826
|
+
: [sortBy];
|
|
20827
|
+
return fields.map((field) => {
|
|
20828
|
+
// Sort by nested array of dates only works with the explicit syntax
|
|
20829
|
+
if (field[1].endsWith('.date')) {
|
|
20830
|
+
const nestedPath = field[1].slice(0, field[1].lastIndexOf('.date'));
|
|
20831
|
+
return {
|
|
20832
|
+
[field[1]]: {
|
|
20833
|
+
order: field[0],
|
|
20834
|
+
mode: field[0] === 'desc' ? 'max' : 'min',
|
|
20835
|
+
missing: '_last',
|
|
20836
|
+
nested: {
|
|
20837
|
+
path: nestedPath,
|
|
20838
|
+
},
|
|
20839
|
+
},
|
|
20840
|
+
};
|
|
20841
|
+
}
|
|
20842
|
+
return { [field[1]]: field[0] };
|
|
20843
|
+
});
|
|
20726
20844
|
}
|
|
20727
20845
|
injectLangInQueryStringFields(queryFieldsPriority) {
|
|
20728
20846
|
const queryLang = this.getQueryLang();
|
|
@@ -20758,7 +20876,49 @@ class ElasticsearchService {
|
|
|
20758
20876
|
isCurrentSearchLang() {
|
|
20759
20877
|
return this.metadataLang === 'current';
|
|
20760
20878
|
}
|
|
20761
|
-
|
|
20879
|
+
findSpatialFilterExtent(filters) {
|
|
20880
|
+
if (typeof filters === 'string') {
|
|
20881
|
+
return undefined;
|
|
20882
|
+
}
|
|
20883
|
+
return Object.values(filters).find(isBoundingBox);
|
|
20884
|
+
}
|
|
20885
|
+
// if a field registered min/max runtime fields, its dates form an interval
|
|
20886
|
+
// the record matches if that interval intersects the filter range
|
|
20887
|
+
buildDateRangeQuery(searchField, dateRange) {
|
|
20888
|
+
const minField = `${searchField}Min`;
|
|
20889
|
+
const maxField = `${searchField}Max`;
|
|
20890
|
+
if (minField in this.runtimeFields && maxField in this.runtimeFields) {
|
|
20891
|
+
const filter = [
|
|
20892
|
+
dateRange.start && {
|
|
20893
|
+
range: {
|
|
20894
|
+
[maxField]: {
|
|
20895
|
+
gte: formatDate(dateRange.start),
|
|
20896
|
+
format: 'yyyy-MM-dd',
|
|
20897
|
+
},
|
|
20898
|
+
},
|
|
20899
|
+
},
|
|
20900
|
+
dateRange.end && {
|
|
20901
|
+
range: {
|
|
20902
|
+
[minField]: {
|
|
20903
|
+
lte: formatDate(dateRange.end),
|
|
20904
|
+
format: 'yyyy-MM-dd',
|
|
20905
|
+
},
|
|
20906
|
+
},
|
|
20907
|
+
},
|
|
20908
|
+
].filter(Boolean);
|
|
20909
|
+
return { bool: { filter } };
|
|
20910
|
+
}
|
|
20911
|
+
return {
|
|
20912
|
+
range: {
|
|
20913
|
+
[searchField]: {
|
|
20914
|
+
...(dateRange.start && { gte: formatDate(dateRange.start) }),
|
|
20915
|
+
...(dateRange.end && { lte: formatDate(dateRange.end) }),
|
|
20916
|
+
format: 'yyyy-MM-dd',
|
|
20917
|
+
},
|
|
20918
|
+
},
|
|
20919
|
+
};
|
|
20920
|
+
}
|
|
20921
|
+
filtersToQuery(filters, spatialFilterExtent = this.findSpatialFilterExtent(filters)) {
|
|
20762
20922
|
const addQuote = (key) => (/^\/.+\/$/.test(key) ? key : `"${key}"`);
|
|
20763
20923
|
const makeQuery = (filter) => {
|
|
20764
20924
|
if (typeof filter === 'string') {
|
|
@@ -20777,7 +20937,9 @@ class ElasticsearchService {
|
|
|
20777
20937
|
? filters
|
|
20778
20938
|
: Object.keys(filters)
|
|
20779
20939
|
.filter((fieldname) => fieldname !== 'gn-ui-crossFieldFilter')
|
|
20940
|
+
.filter((fieldname) => !isBoundingBox(filters[fieldname]))
|
|
20780
20941
|
.filter((fieldname) => !isDateRange(filters[fieldname]))
|
|
20942
|
+
.filter((fieldname) => !Array.isArray(filters[fieldname]))
|
|
20781
20943
|
.filter((fieldname) => filters[fieldname] &&
|
|
20782
20944
|
JSON.stringify(filters[fieldname]) !== '{}')
|
|
20783
20945
|
.map((fieldname) => `${fieldname}:(${makeQuery(filters[fieldname])})`)
|
|
@@ -20785,31 +20947,26 @@ class ElasticsearchService {
|
|
|
20785
20947
|
if (filters['gn-ui-crossFieldFilter']) {
|
|
20786
20948
|
queryString = `${queryString} AND (${filters['gn-ui-crossFieldFilter']})`;
|
|
20787
20949
|
}
|
|
20788
|
-
const
|
|
20789
|
-
.filter(([, value]) => isDateRange(value))
|
|
20790
|
-
.map(([searchField, dateRange]) => {
|
|
20791
|
-
return {
|
|
20792
|
-
searchField,
|
|
20793
|
-
dateRange,
|
|
20794
|
-
};
|
|
20795
|
-
})[0];
|
|
20950
|
+
const queryRanges = Object.entries(filters).filter(([, value]) => isDateRange(value));
|
|
20796
20951
|
const queryParts = [
|
|
20797
20952
|
queryString && {
|
|
20798
20953
|
query_string: {
|
|
20799
20954
|
query: queryString,
|
|
20800
20955
|
},
|
|
20801
20956
|
},
|
|
20802
|
-
|
|
20803
|
-
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20810
|
-
|
|
20811
|
-
|
|
20812
|
-
|
|
20957
|
+
...queryRanges.map(([searchField, dateRange]) => this.buildDateRangeQuery(searchField, dateRange)),
|
|
20958
|
+
spatialFilterExtent && {
|
|
20959
|
+
geo_shape: {
|
|
20960
|
+
geom: {
|
|
20961
|
+
shape: {
|
|
20962
|
+
type: 'envelope',
|
|
20963
|
+
// spatialFilterExtent is [minX, minY, maxX, maxY]; envelope coordinates are [top-left, bottom-right]
|
|
20964
|
+
coordinates: [
|
|
20965
|
+
[spatialFilterExtent[0], spatialFilterExtent[3]],
|
|
20966
|
+
[spatialFilterExtent[2], spatialFilterExtent[1]],
|
|
20967
|
+
],
|
|
20968
|
+
},
|
|
20969
|
+
relation: 'intersects',
|
|
20813
20970
|
},
|
|
20814
20971
|
},
|
|
20815
20972
|
},
|
|
@@ -20839,7 +20996,9 @@ class ElasticsearchService {
|
|
|
20839
20996
|
},
|
|
20840
20997
|
});
|
|
20841
20998
|
}
|
|
20842
|
-
|
|
20999
|
+
// a spatial extent filter takes precedence over the preference geometry for boosting
|
|
21000
|
+
const spatialFilterExtent = this.findSpatialFilterExtent(fieldSearchFilters);
|
|
21001
|
+
const queryFilters = this.filtersToQuery(fieldSearchFilters, spatialFilterExtent);
|
|
20843
21002
|
if (queryFilters) {
|
|
20844
21003
|
filter.push(...queryFilters);
|
|
20845
21004
|
}
|
|
@@ -20850,7 +21009,10 @@ class ElasticsearchService {
|
|
|
20850
21009
|
},
|
|
20851
21010
|
});
|
|
20852
21011
|
}
|
|
20853
|
-
|
|
21012
|
+
const boostGeometry = spatialFilterExtent
|
|
21013
|
+
? bboxToPolygon(spatialFilterExtent)
|
|
21014
|
+
: geometry;
|
|
21015
|
+
if (boostGeometry) {
|
|
20854
21016
|
// boosts applied using the filter geometry:
|
|
20855
21017
|
// * records completely within the geometry receive a boost of 5
|
|
20856
21018
|
// * records intersecting the geometry receive a boost of 2
|
|
@@ -20859,7 +21021,7 @@ class ElasticsearchService {
|
|
|
20859
21021
|
should.push({
|
|
20860
21022
|
geo_shape: {
|
|
20861
21023
|
geom: {
|
|
20862
|
-
shape:
|
|
21024
|
+
shape: boostGeometry,
|
|
20863
21025
|
relation: 'within',
|
|
20864
21026
|
},
|
|
20865
21027
|
boost: 5.0,
|
|
@@ -20867,7 +21029,7 @@ class ElasticsearchService {
|
|
|
20867
21029
|
}, {
|
|
20868
21030
|
geo_shape: {
|
|
20869
21031
|
geom: {
|
|
20870
|
-
shape:
|
|
21032
|
+
shape: boostGeometry,
|
|
20871
21033
|
relation: 'intersects',
|
|
20872
21034
|
},
|
|
20873
21035
|
boost: 2.0,
|
|
@@ -20876,7 +21038,7 @@ class ElasticsearchService {
|
|
|
20876
21038
|
// this will boost the results variably depending on their distance from the given geometry
|
|
20877
21039
|
// note: this takes into account the `location` field of a record; this is generally the center of all spatial extents
|
|
20878
21040
|
// combined, and thus the actual size/coverage of the record spatial extent isn't relevant here
|
|
20879
|
-
const bbox = getGeometryBoundingBox(
|
|
21041
|
+
const bbox = getGeometryBoundingBox(boostGeometry);
|
|
20880
21042
|
const center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
|
|
20881
21043
|
const northToCenter = new LineString([
|
|
20882
21044
|
[center[0], bbox[3]],
|
|
@@ -21202,7 +21364,7 @@ class Gn4Repository {
|
|
|
21202
21364
|
}
|
|
21203
21365
|
getRecord(uniqueIdentifier) {
|
|
21204
21366
|
return this.gn4SearchApi
|
|
21205
|
-
.search('bucket', ['fcats', 'hassources'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21367
|
+
.search('bucket', ['fcats', 'hassources', 'siblings', 'associated'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21206
21368
|
.pipe(map$1((results) => results.hits.hits[0]), switchMap((record) => record ? this.gn4Mapper.readRecord(record) : of(null)));
|
|
21207
21369
|
}
|
|
21208
21370
|
getMultipleRecords(uniqueIdentifiers) {
|
|
@@ -21256,19 +21418,28 @@ class Gn4Repository {
|
|
|
21256
21418
|
.search('bucket', null, JSON.stringify(this.gn4SearchHelper.getRelatedRecordPayload(similarTo, 3)))
|
|
21257
21419
|
.pipe(switchMap((results) => this.gn4Mapper.readRecords(results.hits.hits)));
|
|
21258
21420
|
}
|
|
21259
|
-
|
|
21260
|
-
const
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
|
|
21265
|
-
|
|
21266
|
-
|
|
21267
|
-
|
|
21268
|
-
|
|
21269
|
-
|
|
21421
|
+
getLinkedRecords(record) {
|
|
21422
|
+
const siblings = (record.extras?.['siblings'] ?? []);
|
|
21423
|
+
const relations = [
|
|
21424
|
+
['source', (record.extras?.['sourcesIdentifiers'] ?? [])],
|
|
21425
|
+
['sourceOf', (record.extras?.['sourceOfIdentifiers'] ?? [])],
|
|
21426
|
+
['sibling', siblings.map(({ uniqueIdentifier }) => uniqueIdentifier)],
|
|
21427
|
+
[
|
|
21428
|
+
'associated',
|
|
21429
|
+
(record.extras?.['associatedIdentifiers'] ?? []),
|
|
21430
|
+
],
|
|
21431
|
+
];
|
|
21432
|
+
const requested = relations.filter(([, identifiers]) => identifiers.length > 0);
|
|
21433
|
+
if (requested.length === 0) {
|
|
21434
|
+
return of([]);
|
|
21270
21435
|
}
|
|
21271
|
-
return
|
|
21436
|
+
return forkJoin(requested.map(([relation, identifiers]) => this.getMultipleRecords(identifiers).pipe(map$1((records) => (records ?? []).map((record) => ({
|
|
21437
|
+
record,
|
|
21438
|
+
relation,
|
|
21439
|
+
associationType: relation === 'sibling'
|
|
21440
|
+
? siblings.find(({ uniqueIdentifier }) => uniqueIdentifier === record.uniqueIdentifier)?.associationType
|
|
21441
|
+
: undefined,
|
|
21442
|
+
}))), catchError(() => of([]))))).pipe(map$1((groups) => groups.flat()));
|
|
21272
21443
|
}
|
|
21273
21444
|
aggregate(params) {
|
|
21274
21445
|
// if aggregations are empty, return an empty object right away
|
|
@@ -22457,48 +22628,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
22457
22628
|
type: Injectable
|
|
22458
22629
|
}] });
|
|
22459
22630
|
|
|
22460
|
-
const GEOCODING_PROVIDER = new InjectionToken('geocoding-provider');
|
|
22461
|
-
class GeocodingService {
|
|
22462
|
-
constructor() {
|
|
22463
|
-
this.provider = inject(GEOCODING_PROVIDER);
|
|
22464
|
-
}
|
|
22465
|
-
query(text) {
|
|
22466
|
-
let queryObservable;
|
|
22467
|
-
switch (this.provider[0]) {
|
|
22468
|
-
case 'geoadmin':
|
|
22469
|
-
queryObservable = from(queryGeoadmin(text, this.provider[1]));
|
|
22470
|
-
break;
|
|
22471
|
-
case 'geonames':
|
|
22472
|
-
queryObservable = from(queryGeonames(text, this.provider[1]));
|
|
22473
|
-
break;
|
|
22474
|
-
case 'data-gouv-fr':
|
|
22475
|
-
queryObservable = from(queryDataGouvFr(text, this.provider[1]));
|
|
22476
|
-
break;
|
|
22477
|
-
default:
|
|
22478
|
-
return throwError(() => new Error(`Unsupported geocoding provider: ${this.provider[0]}`));
|
|
22479
|
-
}
|
|
22480
|
-
return queryObservable.pipe(catchError((error) => throwError(error)));
|
|
22481
|
-
}
|
|
22482
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
22483
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, providedIn: 'root' }); }
|
|
22484
|
-
}
|
|
22485
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, decorators: [{
|
|
22486
|
-
type: Injectable,
|
|
22487
|
-
args: [{
|
|
22488
|
-
providedIn: 'root',
|
|
22489
|
-
}]
|
|
22490
|
-
}] });
|
|
22491
|
-
|
|
22492
22631
|
class FeatureMapModule {
|
|
22493
22632
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
22494
22633
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, imports: [i1.StoreFeatureModule] }); }
|
|
22495
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, providers: [
|
|
22496
|
-
MapFacade,
|
|
22497
|
-
{
|
|
22498
|
-
provide: GEOCODING_PROVIDER,
|
|
22499
|
-
useValue: ['geonames', { maxRows: 5 }],
|
|
22500
|
-
},
|
|
22501
|
-
], imports: [StoreModule.forFeature(MAP_FEATURE_KEY, mapReducer)] }); }
|
|
22634
|
+
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)] }); }
|
|
22502
22635
|
}
|
|
22503
22636
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FeatureMapModule, decorators: [{
|
|
22504
22637
|
type: NgModule,
|
|
@@ -22506,13 +22639,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
22506
22639
|
imports: [
|
|
22507
22640
|
StoreModule.forFeature(MAP_FEATURE_KEY, mapReducer),
|
|
22508
22641
|
],
|
|
22509
|
-
providers: [
|
|
22510
|
-
MapFacade,
|
|
22511
|
-
{
|
|
22512
|
-
provide: GEOCODING_PROVIDER,
|
|
22513
|
-
useValue: ['geonames', { maxRows: 5 }],
|
|
22514
|
-
},
|
|
22515
|
-
],
|
|
22642
|
+
providers: [MapFacade],
|
|
22516
22643
|
}]
|
|
22517
22644
|
}] });
|
|
22518
22645
|
|
|
@@ -22529,9 +22656,10 @@ const VECTOR_STYLE_DEFAULT = new InjectionToken('vectorStyleDefault', {
|
|
|
22529
22656
|
});
|
|
22530
22657
|
|
|
22531
22658
|
const DEFAULT_BASEMAP_LAYER = {
|
|
22532
|
-
type: '
|
|
22533
|
-
|
|
22534
|
-
|
|
22659
|
+
type: 'maplibre-style',
|
|
22660
|
+
styleUrl: `https://basemaps.cartocdn.com/gl/positron-gl-style/style.json`,
|
|
22661
|
+
clickable: false,
|
|
22662
|
+
hoverable: false,
|
|
22535
22663
|
};
|
|
22536
22664
|
const DEFAULT_VIEW = {
|
|
22537
22665
|
center: [0, 15],
|
|
@@ -23246,8 +23374,12 @@ function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
|
|
|
23246
23374
|
'search_preset',
|
|
23247
23375
|
'advanced_filters',
|
|
23248
23376
|
'limit',
|
|
23377
|
+
'spatial_extent_max_file_size',
|
|
23378
|
+
'geocoding_provider',
|
|
23379
|
+
'geocoding_provider_options',
|
|
23249
23380
|
], warnings, errors);
|
|
23250
23381
|
const parsedSearchParams = parseMultiConfigSection(parsed, 'search_preset', ['name'], ['sort', 'filters'], warnings, errors);
|
|
23382
|
+
const parsedCustomFilters = parseMultiConfigSection(parsed, 'custom_filter', ['name', 'base_filter'], ['exclude_values', 'include_values', 'label_key'], warnings, errors);
|
|
23251
23383
|
searchConfig =
|
|
23252
23384
|
parsedSearchSection === null
|
|
23253
23385
|
? null
|
|
@@ -23262,7 +23394,17 @@ function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
|
|
|
23262
23394
|
filters: param.filters,
|
|
23263
23395
|
})),
|
|
23264
23396
|
ADVANCED_FILTERS: parsedSearchSection.advanced_filters,
|
|
23397
|
+
CUSTOM_FILTERS: parsedCustomFilters.map((customFilter) => ({
|
|
23398
|
+
name: customFilter.name,
|
|
23399
|
+
baseFilter: customFilter.base_filter,
|
|
23400
|
+
excludeValues: customFilter.exclude_values,
|
|
23401
|
+
includeValues: customFilter.include_values,
|
|
23402
|
+
labelKey: customFilter.label_key,
|
|
23403
|
+
})),
|
|
23265
23404
|
LIMIT: parsedSearchSection.limit,
|
|
23405
|
+
SPATIAL_EXTENT_MAX_FILE_SIZE: parsedSearchSection.spatial_extent_max_file_size,
|
|
23406
|
+
GEOCODING_PROVIDER: parsedSearchSection.geocoding_provider,
|
|
23407
|
+
GEOCODING_PROVIDER_OPTIONS: parsedSearchSection.geocoding_provider_options,
|
|
23266
23408
|
};
|
|
23267
23409
|
const parsedMetadataQualitySection = parseConfigSection(parsed, 'metadata-quality', [], ['enabled'], warnings, errors);
|
|
23268
23410
|
metadataQualityConfig =
|
|
@@ -23371,7 +23513,22 @@ fonts_stylesheet_url = "https://fonts.googleapis.com/css2?family=Open+Sans"
|
|
|
23371
23513
|
record_kind_quick_filter = false
|
|
23372
23514
|
filter_geometry_url = 'https://my.domain.org/geom.json'
|
|
23373
23515
|
do_not_use_default_search_preset = false
|
|
23374
|
-
|
|
23516
|
+
geocoding_provider = "geoplateforme"
|
|
23517
|
+
geocoding_provider_options.category = "administratif"
|
|
23518
|
+
geocoding_provider_options.limit = 5
|
|
23519
|
+
advanced_filters = ['publicationYear', 'documentStandard', 'inspireKeyword', 'topic', 'license', 'myOrg:firstCustomFilter', 'myOrg:secondCustomFilter']
|
|
23520
|
+
|
|
23521
|
+
[[custom_filter]]
|
|
23522
|
+
name = 'myOrg:firstCustomFilter'
|
|
23523
|
+
base_filter = 'keyword'
|
|
23524
|
+
exclude_values = ['my keyword 1', 'my keyword 2']
|
|
23525
|
+
label_key = 'myOrg.firstCustomFilter'
|
|
23526
|
+
|
|
23527
|
+
[[custom_filter]]
|
|
23528
|
+
name = 'myOrg:secondCustomFilter'
|
|
23529
|
+
base_filter = 'keyword'
|
|
23530
|
+
include_values = ['my keyword 3', 'my keyword 4']
|
|
23531
|
+
label_key = 'myOrg.secondCustomFilter'
|
|
23375
23532
|
|
|
23376
23533
|
[[search_preset]]
|
|
23377
23534
|
sort = "-createDate"
|
|
@@ -24320,7 +24477,7 @@ class AutocompleteComponent {
|
|
|
24320
24477
|
this.enterBtnPosition = event.target['value'].length * 8 + 80;
|
|
24321
24478
|
}
|
|
24322
24479
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
24323
|
-
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: [
|
|
24480
|
+
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: [
|
|
24324
24481
|
provideIcons({
|
|
24325
24482
|
iconoirSearch,
|
|
24326
24483
|
matClose,
|
|
@@ -24329,7 +24486,7 @@ class AutocompleteComponent {
|
|
|
24329
24486
|
provideNgIconsConfig({
|
|
24330
24487
|
size: '1.75rem',
|
|
24331
24488
|
}),
|
|
24332
|
-
], 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 }); }
|
|
24489
|
+
], 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 }); }
|
|
24333
24490
|
}
|
|
24334
24491
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AutocompleteComponent, decorators: [{
|
|
24335
24492
|
type: Component,
|
|
@@ -24350,7 +24507,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
24350
24507
|
provideNgIconsConfig({
|
|
24351
24508
|
size: '1.75rem',
|
|
24352
24509
|
}),
|
|
24353
|
-
], 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"] }]
|
|
24510
|
+
], 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"] }]
|
|
24354
24511
|
}], propDecorators: { placeholder: [{
|
|
24355
24512
|
type: Input
|
|
24356
24513
|
}], enterButton: [{
|
|
@@ -24388,6 +24545,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
24388
24545
|
}], inputRef: [{
|
|
24389
24546
|
type: ViewChild,
|
|
24390
24547
|
args: ['searchInput']
|
|
24548
|
+
}], displayWithTemplate: [{
|
|
24549
|
+
type: Input
|
|
24391
24550
|
}], displayWithFn: [{
|
|
24392
24551
|
type: Input
|
|
24393
24552
|
}] } });
|
|
@@ -24520,12 +24679,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
24520
24679
|
type: Input
|
|
24521
24680
|
}] } });
|
|
24522
24681
|
|
|
24682
|
+
function provideLocalizedDateAdapter() {
|
|
24683
|
+
return [
|
|
24684
|
+
{ provide: MAT_DATE_LOCALE, useValue: enUS },
|
|
24685
|
+
{ provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS },
|
|
24686
|
+
{
|
|
24687
|
+
provide: DateAdapter,
|
|
24688
|
+
useFactory: () => {
|
|
24689
|
+
const dateService = inject(DateService);
|
|
24690
|
+
const adapter = new DateFnsAdapter();
|
|
24691
|
+
dateService
|
|
24692
|
+
.getDateFnsLocale()
|
|
24693
|
+
.then((locale) => adapter.setLocale(locale));
|
|
24694
|
+
return adapter;
|
|
24695
|
+
},
|
|
24696
|
+
},
|
|
24697
|
+
];
|
|
24698
|
+
}
|
|
24699
|
+
|
|
24523
24700
|
class DatePickerComponent {
|
|
24524
24701
|
constructor() {
|
|
24525
|
-
this.dateAdapter = inject(DateAdapter);
|
|
24526
|
-
this.translate = inject(TranslateService);
|
|
24527
24702
|
this.dateChange = new EventEmitter();
|
|
24528
|
-
this.dateAdapter.setLocale(this.translate.getCurrentLang());
|
|
24529
24703
|
}
|
|
24530
24704
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
24531
24705
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: DatePickerComponent, isStandalone: true, selector: "gn-ui-date-picker", inputs: { date: "date" }, outputs: { dateChange: "dateChange" }, providers: [
|
|
@@ -24533,30 +24707,19 @@ class DatePickerComponent {
|
|
|
24533
24707
|
provideNgIconsConfig({
|
|
24534
24708
|
size: '1.5rem',
|
|
24535
24709
|
}),
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
useFactory: (locale) => locale,
|
|
24539
|
-
},
|
|
24540
|
-
], ngImport: i0, template: "<span class=\"w-full inline-block relative\">\n <input\n class=\"gn-ui-text-input pr-[var(--text-padding)]\"\n [matDatepicker]=\"picker\"\n [value]=\"date\"\n (dateChange)=\"dateChange.emit($event.value)\"\n />\n <gn-ui-button\n type=\"light\"\n class=\"absolute inset-y-[var(--side-padding)] right-[var(--side-padding)] z-10\"\n (buttonClick)=\"picker.open()\"\n data-cy=\"date-picker-button\"\n extraClass=\"h-full\"\n >\n <ng-icon name=\"iconoirCalendar\" class=\"text-primary\"></ng-icon>\n </gn-ui-button>\n</span>\n<mat-datepicker #picker></mat-datepicker>\n", styles: [":host{--gn-ui-button-rounded: 8px;--gn-ui-button-width: 32px;--gn-ui-button-padding: 0;--side-padding: calc(var(--gn-ui-text-input-padding, .6em) - 6px);--text-padding: calc(var(--side-padding) + 40px)}\n"], dependencies: [{ kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i1$6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
24710
|
+
provideLocalizedDateAdapter(),
|
|
24711
|
+
], ngImport: i0, template: "<span class=\"w-full inline-block relative\">\n <input\n class=\"gn-ui-text-input pr-[var(--text-padding)]\"\n [matDatepicker]=\"picker\"\n [value]=\"date\"\n (dateChange)=\"dateChange.emit($event.value)\"\n />\n <gn-ui-button\n type=\"light\"\n class=\"absolute inset-y-[var(--side-padding)] right-[var(--side-padding)] z-10\"\n (buttonClick)=\"picker.open()\"\n data-cy=\"date-picker-button\"\n extraClass=\"h-full\"\n >\n <ng-icon name=\"iconoirCalendar\" class=\"text-primary\"></ng-icon>\n </gn-ui-button>\n</span>\n<mat-datepicker #picker></mat-datepicker>\n", styles: [":host{--gn-ui-button-rounded: 8px;--gn-ui-button-width: 32px;--gn-ui-button-padding: 0;--side-padding: calc(var(--gn-ui-text-input-padding, .6em) - 6px);--text-padding: calc(var(--side-padding) + 40px)}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i1$6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
24541
24712
|
}
|
|
24542
24713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DatePickerComponent, decorators: [{
|
|
24543
24714
|
type: Component,
|
|
24544
|
-
args: [{ selector: 'gn-ui-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
24545
|
-
MatNativeDateModule,
|
|
24546
|
-
MatDatepickerModule,
|
|
24547
|
-
ButtonComponent,
|
|
24548
|
-
NgIconComponent,
|
|
24549
|
-
], providers: [
|
|
24715
|
+
args: [{ selector: 'gn-ui-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [MatDatepickerModule, ButtonComponent, NgIconComponent], providers: [
|
|
24550
24716
|
provideIcons({ iconoirCalendar }),
|
|
24551
24717
|
provideNgIconsConfig({
|
|
24552
24718
|
size: '1.5rem',
|
|
24553
24719
|
}),
|
|
24554
|
-
|
|
24555
|
-
provide: MAT_DATE_LOCALE,
|
|
24556
|
-
useFactory: (locale) => locale,
|
|
24557
|
-
},
|
|
24720
|
+
provideLocalizedDateAdapter(),
|
|
24558
24721
|
], template: "<span class=\"w-full inline-block relative\">\n <input\n class=\"gn-ui-text-input pr-[var(--text-padding)]\"\n [matDatepicker]=\"picker\"\n [value]=\"date\"\n (dateChange)=\"dateChange.emit($event.value)\"\n />\n <gn-ui-button\n type=\"light\"\n class=\"absolute inset-y-[var(--side-padding)] right-[var(--side-padding)] z-10\"\n (buttonClick)=\"picker.open()\"\n data-cy=\"date-picker-button\"\n extraClass=\"h-full\"\n >\n <ng-icon name=\"iconoirCalendar\" class=\"text-primary\"></ng-icon>\n </gn-ui-button>\n</span>\n<mat-datepicker #picker></mat-datepicker>\n", styles: [":host{--gn-ui-button-rounded: 8px;--gn-ui-button-width: 32px;--gn-ui-button-padding: 0;--side-padding: calc(var(--gn-ui-text-input-padding, .6em) - 6px);--text-padding: calc(var(--side-padding) + 40px)}\n"] }]
|
|
24559
|
-
}],
|
|
24722
|
+
}], propDecorators: { date: [{
|
|
24560
24723
|
type: Input
|
|
24561
24724
|
}], dateChange: [{
|
|
24562
24725
|
type: Output
|
|
@@ -24564,58 +24727,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
24564
24727
|
|
|
24565
24728
|
class DateRangeDropdownComponent {
|
|
24566
24729
|
constructor() {
|
|
24567
|
-
this.
|
|
24730
|
+
this.scrollStrategies = inject(ScrollStrategyOptions);
|
|
24731
|
+
this.dateAdapter = inject(DateAdapter);
|
|
24732
|
+
this.dateFormats = inject(MAT_DATE_FORMATS);
|
|
24568
24733
|
this.cdr = inject(ChangeDetectorRef);
|
|
24569
|
-
this.
|
|
24570
|
-
this.
|
|
24571
|
-
this.
|
|
24734
|
+
this.dateRange = {};
|
|
24735
|
+
this.dateRangeChange = new EventEmitter();
|
|
24736
|
+
this.overlayPositions = [
|
|
24737
|
+
{
|
|
24738
|
+
originX: 'start',
|
|
24739
|
+
originY: 'bottom',
|
|
24740
|
+
overlayX: 'start',
|
|
24741
|
+
overlayY: 'top',
|
|
24742
|
+
offsetY: 8,
|
|
24743
|
+
},
|
|
24744
|
+
{
|
|
24745
|
+
originX: 'start',
|
|
24746
|
+
originY: 'top',
|
|
24747
|
+
overlayX: 'start',
|
|
24748
|
+
overlayY: 'bottom',
|
|
24749
|
+
offsetY: -8,
|
|
24750
|
+
},
|
|
24751
|
+
];
|
|
24752
|
+
this.scrollStrategy = this.scrollStrategies.reposition();
|
|
24753
|
+
this.overlayOpen = false;
|
|
24754
|
+
this.expandedBound = 'start';
|
|
24755
|
+
this.invalidBounds = { start: false, end: false };
|
|
24756
|
+
// redraw when the lazily loaded UI locale reaches the adapter
|
|
24757
|
+
this.dateAdapter.localeChanges
|
|
24758
|
+
.pipe(takeUntilDestroyed())
|
|
24759
|
+
.subscribe(() => this.cdr.markForCheck());
|
|
24572
24760
|
}
|
|
24573
|
-
|
|
24574
|
-
this.
|
|
24761
|
+
get startDate() {
|
|
24762
|
+
return this.dateRange.start;
|
|
24575
24763
|
}
|
|
24576
|
-
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
24581
|
-
|
|
24582
|
-
|
|
24583
|
-
|
|
24764
|
+
get endDate() {
|
|
24765
|
+
return this.dateRange.end;
|
|
24766
|
+
}
|
|
24767
|
+
get selectedDatesCount() {
|
|
24768
|
+
return (this.startDate ? 1 : 0) + (this.endDate ? 1 : 0);
|
|
24769
|
+
}
|
|
24770
|
+
openOverlay() {
|
|
24771
|
+
this.expandedBound = 'start';
|
|
24772
|
+
this.overlayOpen = true;
|
|
24773
|
+
}
|
|
24774
|
+
closeOverlay() {
|
|
24775
|
+
this.overlayOpen = false;
|
|
24776
|
+
}
|
|
24777
|
+
toggleBound(bound) {
|
|
24778
|
+
this.expandedBound = this.expandedBound === bound ? null : bound;
|
|
24779
|
+
}
|
|
24780
|
+
formatDate(date) {
|
|
24781
|
+
return this.dateAdapter.format(date, this.dateFormats.display.dateInput);
|
|
24782
|
+
}
|
|
24783
|
+
onDateInput(bound, event) {
|
|
24784
|
+
const typedText = event.target.value.trim();
|
|
24785
|
+
const date = typedText
|
|
24786
|
+
? this.dateAdapter.parse(typedText, this.dateFormats.parse.dateInput)
|
|
24787
|
+
: null;
|
|
24788
|
+
if (!this.isAcceptable(bound, typedText, date)) {
|
|
24789
|
+
// keep the text as typed and flag it; the filter stays on its last value
|
|
24790
|
+
this.invalidBounds = { ...this.invalidBounds, [bound]: true };
|
|
24791
|
+
return;
|
|
24792
|
+
}
|
|
24793
|
+
if (bound === 'start')
|
|
24794
|
+
this.setStartDate(date);
|
|
24795
|
+
else
|
|
24796
|
+
this.setEndDate(date);
|
|
24797
|
+
}
|
|
24798
|
+
normalizeDateInput(bound, event) {
|
|
24799
|
+
if (this.invalidBounds[bound])
|
|
24800
|
+
return;
|
|
24801
|
+
const date = bound === 'start' ? this.startDate : this.endDate;
|
|
24802
|
+
const input = event.target;
|
|
24803
|
+
input.value = date ? this.formatDate(date) : '';
|
|
24804
|
+
}
|
|
24805
|
+
isAcceptable(bound, typedText, date) {
|
|
24806
|
+
if (!typedText)
|
|
24807
|
+
return true;
|
|
24808
|
+
if (!date || !this.dateAdapter.isValid(date))
|
|
24809
|
+
return false;
|
|
24810
|
+
return bound === 'start'
|
|
24811
|
+
? !this.endDate || date <= this.endDate
|
|
24812
|
+
: !this.startDate || date >= this.startDate;
|
|
24813
|
+
}
|
|
24814
|
+
setStartDate(date) {
|
|
24815
|
+
this.invalidBounds = { ...this.invalidBounds, start: false };
|
|
24816
|
+
this.applyDateRange({ ...this.dateRange, start: date });
|
|
24817
|
+
this.expandedBound = 'end';
|
|
24818
|
+
}
|
|
24819
|
+
setEndDate(date) {
|
|
24820
|
+
this.invalidBounds = { ...this.invalidBounds, end: false };
|
|
24821
|
+
this.applyDateRange({ ...this.dateRange, end: date });
|
|
24822
|
+
this.expandedBound = null;
|
|
24823
|
+
}
|
|
24824
|
+
clearDates(event) {
|
|
24825
|
+
this.invalidBounds = { start: false, end: false };
|
|
24826
|
+
this.expandedBound = 'start';
|
|
24827
|
+
this.applyDateRange({});
|
|
24828
|
+
propagateToDocumentOnly(event);
|
|
24829
|
+
}
|
|
24830
|
+
applyDateRange(dateRange) {
|
|
24831
|
+
this.dateRange = {
|
|
24832
|
+
...(dateRange.start && { start: dateRange.start }),
|
|
24833
|
+
...(dateRange.end && { end: dateRange.end }),
|
|
24834
|
+
};
|
|
24835
|
+
this.dateRangeChange.emit(this.dateRange);
|
|
24584
24836
|
}
|
|
24585
24837
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateRangeDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
24586
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
24838
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DateRangeDropdownComponent, isStandalone: true, selector: "gn-ui-date-range-dropdown", inputs: { title: "title", dateRange: "dateRange" }, outputs: { dateRangeChange: "dateRangeChange" }, providers: [
|
|
24587
24839
|
provideIcons({
|
|
24588
|
-
|
|
24840
|
+
iconoirCalendar,
|
|
24841
|
+
matClose,
|
|
24589
24842
|
matExpandLess,
|
|
24843
|
+
matExpandMore,
|
|
24844
|
+
}),
|
|
24845
|
+
provideNgIconsConfig({
|
|
24846
|
+
size: '1.5rem',
|
|
24590
24847
|
}),
|
|
24591
|
-
|
|
24848
|
+
provideLocalizedDateAdapter(),
|
|
24849
|
+
], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], 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)=\"openOverlay()\"\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 (selectedDatesCount) {\n <div\n class=\"gn-ui-multiselect-counter shrink-0 rounded-full font-bold text-[12px] w-5 h-5 flex items-center justify-center mr-1 selected-count\"\n >\n {{ selectedDatesCount }}\n </div>\n }\n </div>\n <button\n class=\"h-6 w-6 flex items-center justify-center\"\n data-test=\"dropdown-clear\"\n >\n @if (selectedDatesCount && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"clearDates($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n data-test=\"dropdown-toggle\"\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 (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"w-[296px] flex flex-col gap-2 bg-white border border-gray-400 rounded px-4 py-3 shadow-lg text-main text-[16px] leading-[24px]\"\n data-test=\"date-range-panel\"\n >\n <div class=\"flex flex-col justify-center border-b border-gray-300 pb-1\">\n <ng-container\n [ngTemplateOutlet]=\"boundRow\"\n [ngTemplateOutletContext]=\"{\n bound: 'start',\n label: 'daterange.filter.from',\n date: startDate,\n }\"\n ></ng-container>\n @if (expandedBound === 'start') {\n <div class=\"calendar\" animate.enter=\"expand\" animate.leave=\"collapse\">\n <mat-calendar\n data-test=\"start-date-calendar\"\n [selected]=\"startDate\"\n [startAt]=\"startDate ?? endDate\"\n [maxDate]=\"endDate\"\n (selectedChange)=\"setStartDate($event)\"\n ></mat-calendar>\n </div>\n }\n </div>\n <div class=\"flex flex-col justify-center\">\n <ng-container\n [ngTemplateOutlet]=\"boundRow\"\n [ngTemplateOutletContext]=\"{\n bound: 'end',\n label: 'daterange.filter.to',\n date: endDate,\n }\"\n ></ng-container>\n @if (expandedBound === 'end') {\n <div class=\"calendar\" animate.enter=\"expand\" animate.leave=\"collapse\">\n <mat-calendar\n data-test=\"end-date-calendar\"\n [selected]=\"endDate\"\n [startAt]=\"endDate ?? startDate\"\n [minDate]=\"startDate\"\n (selectedChange)=\"setEndDate($event)\"\n ></mat-calendar>\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #boundRow let-bound=\"bound\" let-label=\"label\" let-date=\"date\">\n <div class=\"flex items-center gap-1 w-full\">\n <span class=\"w-[80px] shrink-0\" [translate]=\"label\"></span>\n <div\n class=\"flex-1 min-w-0 flex items-center gap-1 border rounded-lg px-2 py-1 transition-colors\"\n [class]=\"\n invalidBounds[bound]\n ? 'border-red-400 text-red-800 focus-within:border-red-800 hover:border-red-800'\n : 'border-gray-400 focus-within:border-main hover:border-main'\n \"\n >\n <ng-icon\n name=\"iconoirCalendar\"\n class=\"shrink-0\"\n aria-hidden=\"true\"\n ></ng-icon>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [gnUiAutofocus]=\"bound === expandedBound\"\n class=\"min-w-0 grow bg-transparent focus:outline-none\"\n [value]=\"date ? formatDate(date) : ''\"\n [placeholder]=\"'daterange.filter.datePlaceholder' | translate\"\n [attr.aria-label]=\"label | translate\"\n [attr.aria-invalid]=\"invalidBounds[bound] || null\"\n [attr.data-test]=\"bound + '-date-input'\"\n (change)=\"onDateInput(bound, $event)\"\n (blur)=\"normalizeDateInput(bound, $event)\"\n (click)=\"expandedBound !== bound && toggleBound(bound)\"\n />\n </div>\n <div class=\"shrink-0 flex items-center justify-end\">\n <gn-ui-button\n type=\"light\"\n [style.--gn-ui-button-padding]=\"0\"\n [style.--gn-ui-button-width]=\"'24px'\"\n [style.--gn-ui-button-height]=\"'24px'\"\n [attr.aria-expanded]=\"expandedBound === bound\"\n [attr.data-test]=\"bound + '-date-toggle'\"\n (buttonClick)=\"toggleBound(bound)\"\n >\n <ng-icon\n [name]=\"expandedBound === bound ? 'matExpandLess' : 'matExpandMore'\"\n ></ng-icon>\n </gn-ui-button>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-calendar{width:100%}.calendar{display:grid;grid-template-rows:1fr}.calendar>mat-calendar{min-height:0;overflow:hidden}.calendar.expand{animation:open .2s ease-out}.calendar.collapse{animation:open .2s ease-in reverse}@keyframes open{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@media (prefers-reduced-motion: reduce){.calendar.expand,.calendar.collapse{animation-duration:1ms}}\n"], dependencies: [{ kind: "directive", type: AutofocusDirective, selector: "[gnUiAutofocus]", inputs: ["gnUiAutofocus"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$6.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
24592
24850
|
}
|
|
24593
24851
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateRangeDropdownComponent, decorators: [{
|
|
24594
24852
|
type: Component,
|
|
24595
24853
|
args: [{ selector: 'gn-ui-date-range-dropdown', standalone: true, imports: [
|
|
24596
|
-
|
|
24597
|
-
MatNativeDateModule,
|
|
24598
|
-
MatDatepickerModule,
|
|
24854
|
+
AutofocusDirective,
|
|
24599
24855
|
ButtonComponent,
|
|
24856
|
+
MatDatepickerModule,
|
|
24857
|
+
NgIcon,
|
|
24858
|
+
NgTemplateOutlet,
|
|
24859
|
+
OverlayModule,
|
|
24860
|
+
TranslateDirective,
|
|
24861
|
+
TranslatePipe,
|
|
24600
24862
|
], providers: [
|
|
24601
24863
|
provideIcons({
|
|
24602
|
-
|
|
24864
|
+
iconoirCalendar,
|
|
24865
|
+
matClose,
|
|
24603
24866
|
matExpandLess,
|
|
24867
|
+
matExpandMore,
|
|
24604
24868
|
}),
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
|
|
24608
|
-
|
|
24869
|
+
provideNgIconsConfig({
|
|
24870
|
+
size: '1.5rem',
|
|
24871
|
+
}),
|
|
24872
|
+
provideLocalizedDateAdapter(),
|
|
24873
|
+
], 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)=\"openOverlay()\"\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 (selectedDatesCount) {\n <div\n class=\"gn-ui-multiselect-counter shrink-0 rounded-full font-bold text-[12px] w-5 h-5 flex items-center justify-center mr-1 selected-count\"\n >\n {{ selectedDatesCount }}\n </div>\n }\n </div>\n <button\n class=\"h-6 w-6 flex items-center justify-center\"\n data-test=\"dropdown-clear\"\n >\n @if (selectedDatesCount && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"clearDates($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n data-test=\"dropdown-toggle\"\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 (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"w-[296px] flex flex-col gap-2 bg-white border border-gray-400 rounded px-4 py-3 shadow-lg text-main text-[16px] leading-[24px]\"\n data-test=\"date-range-panel\"\n >\n <div class=\"flex flex-col justify-center border-b border-gray-300 pb-1\">\n <ng-container\n [ngTemplateOutlet]=\"boundRow\"\n [ngTemplateOutletContext]=\"{\n bound: 'start',\n label: 'daterange.filter.from',\n date: startDate,\n }\"\n ></ng-container>\n @if (expandedBound === 'start') {\n <div class=\"calendar\" animate.enter=\"expand\" animate.leave=\"collapse\">\n <mat-calendar\n data-test=\"start-date-calendar\"\n [selected]=\"startDate\"\n [startAt]=\"startDate ?? endDate\"\n [maxDate]=\"endDate\"\n (selectedChange)=\"setStartDate($event)\"\n ></mat-calendar>\n </div>\n }\n </div>\n <div class=\"flex flex-col justify-center\">\n <ng-container\n [ngTemplateOutlet]=\"boundRow\"\n [ngTemplateOutletContext]=\"{\n bound: 'end',\n label: 'daterange.filter.to',\n date: endDate,\n }\"\n ></ng-container>\n @if (expandedBound === 'end') {\n <div class=\"calendar\" animate.enter=\"expand\" animate.leave=\"collapse\">\n <mat-calendar\n data-test=\"end-date-calendar\"\n [selected]=\"endDate\"\n [startAt]=\"endDate ?? startDate\"\n [minDate]=\"startDate\"\n (selectedChange)=\"setEndDate($event)\"\n ></mat-calendar>\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #boundRow let-bound=\"bound\" let-label=\"label\" let-date=\"date\">\n <div class=\"flex items-center gap-1 w-full\">\n <span class=\"w-[80px] shrink-0\" [translate]=\"label\"></span>\n <div\n class=\"flex-1 min-w-0 flex items-center gap-1 border rounded-lg px-2 py-1 transition-colors\"\n [class]=\"\n invalidBounds[bound]\n ? 'border-red-400 text-red-800 focus-within:border-red-800 hover:border-red-800'\n : 'border-gray-400 focus-within:border-main hover:border-main'\n \"\n >\n <ng-icon\n name=\"iconoirCalendar\"\n class=\"shrink-0\"\n aria-hidden=\"true\"\n ></ng-icon>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [gnUiAutofocus]=\"bound === expandedBound\"\n class=\"min-w-0 grow bg-transparent focus:outline-none\"\n [value]=\"date ? formatDate(date) : ''\"\n [placeholder]=\"'daterange.filter.datePlaceholder' | translate\"\n [attr.aria-label]=\"label | translate\"\n [attr.aria-invalid]=\"invalidBounds[bound] || null\"\n [attr.data-test]=\"bound + '-date-input'\"\n (change)=\"onDateInput(bound, $event)\"\n (blur)=\"normalizeDateInput(bound, $event)\"\n (click)=\"expandedBound !== bound && toggleBound(bound)\"\n />\n </div>\n <div class=\"shrink-0 flex items-center justify-end\">\n <gn-ui-button\n type=\"light\"\n [style.--gn-ui-button-padding]=\"0\"\n [style.--gn-ui-button-width]=\"'24px'\"\n [style.--gn-ui-button-height]=\"'24px'\"\n [attr.aria-expanded]=\"expandedBound === bound\"\n [attr.data-test]=\"bound + '-date-toggle'\"\n (buttonClick)=\"toggleBound(bound)\"\n >\n <ng-icon\n [name]=\"expandedBound === bound ? 'matExpandLess' : 'matExpandMore'\"\n ></ng-icon>\n </gn-ui-button>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-calendar{width:100%}.calendar{display:grid;grid-template-rows:1fr}.calendar>mat-calendar{min-height:0;overflow:hidden}.calendar.expand{animation:open .2s ease-out}.calendar.collapse{animation:open .2s ease-in reverse}@keyframes open{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@media (prefers-reduced-motion: reduce){.calendar.expand,.calendar.collapse{animation-duration:1ms}}\n"] }]
|
|
24874
|
+
}], ctorParameters: () => [], propDecorators: { title: [{
|
|
24609
24875
|
type: Input
|
|
24610
|
-
}],
|
|
24876
|
+
}], dateRange: [{
|
|
24611
24877
|
type: Input
|
|
24612
|
-
}],
|
|
24878
|
+
}], dateRangeChange: [{
|
|
24613
24879
|
type: Output
|
|
24614
|
-
}],
|
|
24615
|
-
type: Output
|
|
24616
|
-
}], picker: [{
|
|
24880
|
+
}], overlayOrigin: [{
|
|
24617
24881
|
type: ViewChild,
|
|
24618
|
-
args: ['
|
|
24882
|
+
args: ['overlayOrigin']
|
|
24619
24883
|
}] } });
|
|
24620
24884
|
|
|
24621
24885
|
class DateRangePickerComponent {
|
|
@@ -24629,20 +24893,17 @@ class DateRangePickerComponent {
|
|
|
24629
24893
|
provideNgIconsConfig({
|
|
24630
24894
|
size: '1.5rem',
|
|
24631
24895
|
}),
|
|
24632
|
-
|
|
24896
|
+
provideLocalizedDateAdapter(),
|
|
24897
|
+
], ngImport: i0, template: "<span class=\"w-full inline-block relative\">\n <mat-date-range-input [rangePicker]=\"picker\" class=\"gn-ui-text-input\">\n <input\n matStartDate\n placeholder=\"Start date\"\n [value]=\"startDate\"\n (dateInput)=\"startDateChange.emit($event.value)\"\n />\n <input\n matEndDate\n placeholder=\"End date\"\n [value]=\"endDate\"\n (dateInput)=\"endDateChange.emit($event.value)\"\n />\n </mat-date-range-input>\n\n <gn-ui-button\n type=\"light\"\n class=\"absolute inset-y-[var(--side-padding)] right-[var(--side-padding)] z-10\"\n (buttonClick)=\"picker.open()\"\n extraClass=\"h-full\"\n data-cy=\"date-picker-button\"\n >\n <ng-icon name=\"iconoirCalendar\" class=\"text-primary\"></ng-icon>\n </gn-ui-button>\n</span>\n<mat-date-range-picker #picker></mat-date-range-picker>\n", styles: [":host{--gn-ui-button-rounded: 8px;--gn-ui-button-width: 32px;--gn-ui-button-padding: 0;--side-padding: calc(var(--gn-ui-text-input-padding, .6em) - 6px);--text-padding: calc(var(--side-padding) + 40px)}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$6.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i1$6.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i1$6.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i1$6.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
24633
24898
|
}
|
|
24634
24899
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateRangePickerComponent, decorators: [{
|
|
24635
24900
|
type: Component,
|
|
24636
|
-
args: [{ selector: 'gn-ui-date-range-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
24637
|
-
MatNativeDateModule,
|
|
24638
|
-
MatDatepickerModule,
|
|
24639
|
-
ButtonComponent,
|
|
24640
|
-
NgIconComponent,
|
|
24641
|
-
], providers: [
|
|
24901
|
+
args: [{ selector: 'gn-ui-date-range-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [MatDatepickerModule, ButtonComponent, NgIconComponent], providers: [
|
|
24642
24902
|
provideIcons({ iconoirCalendar }),
|
|
24643
24903
|
provideNgIconsConfig({
|
|
24644
24904
|
size: '1.5rem',
|
|
24645
24905
|
}),
|
|
24906
|
+
provideLocalizedDateAdapter(),
|
|
24646
24907
|
], template: "<span class=\"w-full inline-block relative\">\n <mat-date-range-input [rangePicker]=\"picker\" class=\"gn-ui-text-input\">\n <input\n matStartDate\n placeholder=\"Start date\"\n [value]=\"startDate\"\n (dateInput)=\"startDateChange.emit($event.value)\"\n />\n <input\n matEndDate\n placeholder=\"End date\"\n [value]=\"endDate\"\n (dateInput)=\"endDateChange.emit($event.value)\"\n />\n </mat-date-range-input>\n\n <gn-ui-button\n type=\"light\"\n class=\"absolute inset-y-[var(--side-padding)] right-[var(--side-padding)] z-10\"\n (buttonClick)=\"picker.open()\"\n extraClass=\"h-full\"\n data-cy=\"date-picker-button\"\n >\n <ng-icon name=\"iconoirCalendar\" class=\"text-primary\"></ng-icon>\n </gn-ui-button>\n</span>\n<mat-date-range-picker #picker></mat-date-range-picker>\n", styles: [":host{--gn-ui-button-rounded: 8px;--gn-ui-button-width: 32px;--gn-ui-button-padding: 0;--side-padding: calc(var(--gn-ui-text-input-padding, .6em) - 6px);--text-padding: calc(var(--side-padding) + 40px)}\n"] }]
|
|
24647
24908
|
}], propDecorators: { startDate: [{
|
|
24648
24909
|
type: Input
|
|
@@ -24660,28 +24921,68 @@ class DragAndDropFileInputComponent {
|
|
|
24660
24921
|
constructor() {
|
|
24661
24922
|
this.placeholder = placeholder;
|
|
24662
24923
|
this.accept = '*';
|
|
24924
|
+
this.maxFileSizeMb = null;
|
|
24925
|
+
this.icon = null;
|
|
24926
|
+
this.dropzoneBackgroundColor = null;
|
|
24927
|
+
this.textClass = '';
|
|
24928
|
+
this.extraClass = '';
|
|
24929
|
+
this.showFileName = true;
|
|
24663
24930
|
this.fileChange = new EventEmitter();
|
|
24931
|
+
this.errorChange = new EventEmitter();
|
|
24664
24932
|
this.selectedFile = null;
|
|
24665
24933
|
}
|
|
24666
24934
|
get fileName() {
|
|
24667
24935
|
return this.selectedFile && this.selectedFile.name;
|
|
24668
24936
|
}
|
|
24937
|
+
get maxFileSizeBytes() {
|
|
24938
|
+
return typeof this.maxFileSizeMb === 'number'
|
|
24939
|
+
? megabytesToBytes(this.maxFileSizeMb)
|
|
24940
|
+
: null;
|
|
24941
|
+
}
|
|
24669
24942
|
selectFile(event) {
|
|
24943
|
+
if (event.rejectedFiles?.length) {
|
|
24944
|
+
const reason = event.rejectedFiles[0].reason;
|
|
24945
|
+
this.errorChange.emit(reason === 'size' ? 'file-too-large' : 'invalid-extension');
|
|
24946
|
+
return;
|
|
24947
|
+
}
|
|
24670
24948
|
this.selectedFile = event.addedFiles[0];
|
|
24671
24949
|
this.fileChange.emit(this.selectedFile);
|
|
24672
24950
|
}
|
|
24951
|
+
openFileSelector() {
|
|
24952
|
+
this.dropzone.showFileSelector();
|
|
24953
|
+
}
|
|
24954
|
+
clear() {
|
|
24955
|
+
this.selectedFile = null;
|
|
24956
|
+
}
|
|
24673
24957
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DragAndDropFileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
24674
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DragAndDropFileInputComponent, isStandalone: true, selector: "gn-ui-drag-and-drop-file-input", inputs: { placeholder: "placeholder", accept: "accept" }, outputs: { fileChange: "fileChange" }, ngImport: i0, template: "<div
|
|
24958
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DragAndDropFileInputComponent, isStandalone: true, selector: "gn-ui-drag-and-drop-file-input", inputs: { placeholder: "placeholder", accept: "accept", maxFileSizeMb: "maxFileSizeMb", icon: "icon", dropzoneBackgroundColor: "dropzoneBackgroundColor", textClass: "textClass", extraClass: "extraClass", showFileName: "showFileName" }, outputs: { fileChange: "fileChange", errorChange: "errorChange" }, viewQueries: [{ propertyName: "dropzone", first: true, predicate: NgxDropzoneComponent, descendants: true }], ngImport: i0, template: "<div\n class=\"flex h-full items-center\"\n [class]=\"extraClass\"\n (click)=\"openFileSelector()\"\n>\n <ngx-dropzone\n class=\"flex-1 overflow-hidden\"\n [multiple]=\"false\"\n [disableClick]=\"true\"\n [accept]=\"accept\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [style.background-color]=\"dropzoneBackgroundColor\"\n (change)=\"selectFile($event)\"\n >\n @if (!fileName || !showFileName) {\n <div [class]=\"textClass\">\n {{ placeholder }}\n </div>\n }\n\n @if (fileName && showFileName) {\n <div [class]=\"textClass\">\n {{ fileName }}\n </div>\n }\n </ngx-dropzone>\n\n @if (icon) {\n <ng-icon [name]=\"icon\" class=\"shrink-0 text-gray-950\"></ng-icon>\n }\n</div>\n", styles: ["ngx-dropzone{height:auto;border:none;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: NgxDropzoneModule }, { kind: "component", type: i1$8.NgxDropzoneComponent, selector: "ngx-dropzone, [ngx-dropzone]", inputs: ["accept", "disabled", "multiple", "maxFileSize", "expandable", "disableClick", "processDirectoryDrop", "id", "aria-label", "aria-labelledby", "aria-describedby"], outputs: ["change"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }] }); }
|
|
24675
24959
|
}
|
|
24676
24960
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DragAndDropFileInputComponent, decorators: [{
|
|
24677
24961
|
type: Component,
|
|
24678
|
-
args: [{ selector: 'gn-ui-drag-and-drop-file-input', standalone: true, imports: [NgxDropzoneModule], template: "<div
|
|
24962
|
+
args: [{ selector: 'gn-ui-drag-and-drop-file-input', standalone: true, imports: [NgxDropzoneModule, NgIcon], template: "<div\n class=\"flex h-full items-center\"\n [class]=\"extraClass\"\n (click)=\"openFileSelector()\"\n>\n <ngx-dropzone\n class=\"flex-1 overflow-hidden\"\n [multiple]=\"false\"\n [disableClick]=\"true\"\n [accept]=\"accept\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [style.background-color]=\"dropzoneBackgroundColor\"\n (change)=\"selectFile($event)\"\n >\n @if (!fileName || !showFileName) {\n <div [class]=\"textClass\">\n {{ placeholder }}\n </div>\n }\n\n @if (fileName && showFileName) {\n <div [class]=\"textClass\">\n {{ fileName }}\n </div>\n }\n </ngx-dropzone>\n\n @if (icon) {\n <ng-icon [name]=\"icon\" class=\"shrink-0 text-gray-950\"></ng-icon>\n }\n</div>\n", styles: ["ngx-dropzone{height:auto;border:none;overflow:hidden}\n"] }]
|
|
24679
24963
|
}], propDecorators: { placeholder: [{
|
|
24680
24964
|
type: Input
|
|
24681
24965
|
}], accept: [{
|
|
24682
24966
|
type: Input
|
|
24967
|
+
}], maxFileSizeMb: [{
|
|
24968
|
+
type: Input
|
|
24969
|
+
}], icon: [{
|
|
24970
|
+
type: Input
|
|
24971
|
+
}], dropzoneBackgroundColor: [{
|
|
24972
|
+
type: Input
|
|
24973
|
+
}], textClass: [{
|
|
24974
|
+
type: Input
|
|
24975
|
+
}], extraClass: [{
|
|
24976
|
+
type: Input
|
|
24977
|
+
}], showFileName: [{
|
|
24978
|
+
type: Input
|
|
24683
24979
|
}], fileChange: [{
|
|
24684
24980
|
type: Output
|
|
24981
|
+
}], errorChange: [{
|
|
24982
|
+
type: Output
|
|
24983
|
+
}], dropzone: [{
|
|
24984
|
+
type: ViewChild,
|
|
24985
|
+
args: [NgxDropzoneComponent]
|
|
24685
24986
|
}] } });
|
|
24686
24987
|
|
|
24687
24988
|
class DropdownMultiselectComponent {
|
|
@@ -24730,7 +25031,7 @@ class DropdownMultiselectComponent {
|
|
|
24730
25031
|
}
|
|
24731
25032
|
setFocus() {
|
|
24732
25033
|
setTimeout(() => {
|
|
24733
|
-
this.searchFieldInput
|
|
25034
|
+
this.searchFieldInput?.nativeElement.focus();
|
|
24734
25035
|
}, 0);
|
|
24735
25036
|
}
|
|
24736
25037
|
openOverlay() {
|
|
@@ -24836,7 +25137,10 @@ class DropdownMultiselectComponent {
|
|
|
24836
25137
|
matExpandMore,
|
|
24837
25138
|
matExpandLess,
|
|
24838
25139
|
}),
|
|
24839
|
-
|
|
25140
|
+
provideNgIconsConfig({
|
|
25141
|
+
size: '1.5rem',
|
|
25142
|
+
}),
|
|
25143
|
+
], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "overlayContainer", first: true, predicate: ["overlayContainer"], descendants: true, read: ElementRef }, { propertyName: "searchFieldInput", first: true, predicate: ["searchFieldInput"], descendants: true }, { propertyName: "checkboxes", predicate: ["checkBox"], descendants: true, read: ElementRef }], ngImport: i0, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n [attr.aria-owns]=\"id\"\n (buttonClick)=\"openOverlay()\"\n (keydown)=\"handleTriggerKeydown($event)\"\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 (hasSelectedChoices) {\n <div\n class=\"gn-ui-multiselect-counter shrink-0 rounded-full font-bold text-[12px] w-5 h-5 flex items-center justify-center mr-1 selected-count\"\n >\n {{ selected.length }}\n </div>\n }\n </div>\n <button\n class=\"h-6 w-6 flex items-center justify-center\"\n data-test=\"dropdown-clear\"\n >\n @if (hasSelectedChoices && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"clearSelection($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-300 rounded shadow-lg py-2 w-full overflow-x-hidden overflow-y-auto overlay-container\"\n [style.max-height]=\"overlayMaxHeight\"\n [style.min-width]=\"overlayMinWidth\"\n role=\"listbox\"\n tabindex=\"-1\"\n [attr.id]=\"id\"\n [attr.aria-multiselectable]=\"true\"\n [attr.aria-label]=\"title\"\n (keydown)=\"handleOverlayKeydown($event)\"\n #overlayContainer\n >\n <div\n class=\"border border-gray-300 rounded mb-2 mx-2 min-h-[44px] flex flex-row gap-1 flex-wrap p-2 focus-within:rounded focus-within:border-2 focus-within:border-primary\"\n >\n @for (selected of selectedChoices; track selected) {\n <button\n type=\"button\"\n [title]=\"selected.label\"\n class=\"max-w-full bg-main text-white rounded pr-[7px] flex gap-1 items-center opacity-70 hover:opacity-100 focus:opacity-100 transition-opacity\"\n (click)=\"select(selected, false)\"\n >\n <div class=\"text-sm truncate leading-[26px] px-2\">\n {{ selected.label }}\n </div>\n <div\n class=\"flex items-center justify-center rounded-full bg-white text-main h-[13px] w-[13px] pt-px -mt-px shrink-0\"\n >\n <ng-icon\n name=\"matClose\"\n class=\"!h-[12px] !w-[11px] text-[12px]\"\n ></ng-icon>\n </div>\n </button>\n }\n\n @if (allowSearch) {\n <div class=\"w-[50%] relative grow shrink\">\n <input\n #searchFieldInput\n class=\"w-full px-2 truncate text-[14px] h-full overlaySearchInput focus:outline-none\"\n [(ngModel)]=\"searchInputValue\"\n [placeholder]=\"'multiselect.filter.placeholder' | translate\"\n />\n @if (!!searchInputValue) {\n <button\n class=\"absolute top-1/2 -translate-y-1/2 right-0 px-[7px] leading-tight clear-search-input mr-2\"\n (click)=\"clearSearchInputValue($event)\"\n >\n <ng-icon class=\"!h-[10px] !w-[12px] text-[12px]\" name=\"matClose\">\n </ng-icon>\n </button>\n }\n </div>\n }\n </div>\n\n @for (choice of filteredChoicesByText; track choice) {\n <label\n [title]=\"choice.label\"\n class=\"flex px-5 py-1 w-full text-gray-900 cursor-pointer hover:text-primary-darkest hover:bg-gray-50 focus-within:text-primary-darkest focus-within:bg-gray-50 transition-colors\"\n >\n <input\n class=\"w-[18px] h-[18px] align-text-top shrink-0\"\n type=\"checkbox\"\n #checkBox\n [checked]=\"isSelected(choice)\"\n (change)=\"select(choice, checkBox.checked)\"\n />\n <span class=\"ml-[8px] text-[14px] truncate\">\n {{ choice.label }}\n </span>\n </label>\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: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
24840
25144
|
}
|
|
24841
25145
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DropdownMultiselectComponent, decorators: [{
|
|
24842
25146
|
type: Component,
|
|
@@ -24846,7 +25150,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
24846
25150
|
matExpandMore,
|
|
24847
25151
|
matExpandLess,
|
|
24848
25152
|
}),
|
|
24849
|
-
|
|
25153
|
+
provideNgIconsConfig({
|
|
25154
|
+
size: '1.5rem',
|
|
25155
|
+
}),
|
|
25156
|
+
], standalone: true, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n [attr.aria-owns]=\"id\"\n (buttonClick)=\"openOverlay()\"\n (keydown)=\"handleTriggerKeydown($event)\"\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 (hasSelectedChoices) {\n <div\n class=\"gn-ui-multiselect-counter shrink-0 rounded-full font-bold text-[12px] w-5 h-5 flex items-center justify-center mr-1 selected-count\"\n >\n {{ selected.length }}\n </div>\n }\n </div>\n <button\n class=\"h-6 w-6 flex items-center justify-center\"\n data-test=\"dropdown-clear\"\n >\n @if (hasSelectedChoices && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"clearSelection($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-300 rounded shadow-lg py-2 w-full overflow-x-hidden overflow-y-auto overlay-container\"\n [style.max-height]=\"overlayMaxHeight\"\n [style.min-width]=\"overlayMinWidth\"\n role=\"listbox\"\n tabindex=\"-1\"\n [attr.id]=\"id\"\n [attr.aria-multiselectable]=\"true\"\n [attr.aria-label]=\"title\"\n (keydown)=\"handleOverlayKeydown($event)\"\n #overlayContainer\n >\n <div\n class=\"border border-gray-300 rounded mb-2 mx-2 min-h-[44px] flex flex-row gap-1 flex-wrap p-2 focus-within:rounded focus-within:border-2 focus-within:border-primary\"\n >\n @for (selected of selectedChoices; track selected) {\n <button\n type=\"button\"\n [title]=\"selected.label\"\n class=\"max-w-full bg-main text-white rounded pr-[7px] flex gap-1 items-center opacity-70 hover:opacity-100 focus:opacity-100 transition-opacity\"\n (click)=\"select(selected, false)\"\n >\n <div class=\"text-sm truncate leading-[26px] px-2\">\n {{ selected.label }}\n </div>\n <div\n class=\"flex items-center justify-center rounded-full bg-white text-main h-[13px] w-[13px] pt-px -mt-px shrink-0\"\n >\n <ng-icon\n name=\"matClose\"\n class=\"!h-[12px] !w-[11px] text-[12px]\"\n ></ng-icon>\n </div>\n </button>\n }\n\n @if (allowSearch) {\n <div class=\"w-[50%] relative grow shrink\">\n <input\n #searchFieldInput\n class=\"w-full px-2 truncate text-[14px] h-full overlaySearchInput focus:outline-none\"\n [(ngModel)]=\"searchInputValue\"\n [placeholder]=\"'multiselect.filter.placeholder' | translate\"\n />\n @if (!!searchInputValue) {\n <button\n class=\"absolute top-1/2 -translate-y-1/2 right-0 px-[7px] leading-tight clear-search-input mr-2\"\n (click)=\"clearSearchInputValue($event)\"\n >\n <ng-icon class=\"!h-[10px] !w-[12px] text-[12px]\" name=\"matClose\">\n </ng-icon>\n </button>\n }\n </div>\n }\n </div>\n\n @for (choice of filteredChoicesByText; track choice) {\n <label\n [title]=\"choice.label\"\n class=\"flex px-5 py-1 w-full text-gray-900 cursor-pointer hover:text-primary-darkest hover:bg-gray-50 focus-within:text-primary-darkest focus-within:bg-gray-50 transition-colors\"\n >\n <input\n class=\"w-[18px] h-[18px] align-text-top shrink-0\"\n type=\"checkbox\"\n #checkBox\n [checked]=\"isSelected(choice)\"\n (change)=\"select(choice, checkBox.checked)\"\n />\n <span class=\"ml-[8px] text-[14px] truncate\">\n {{ choice.label }}\n </span>\n </label>\n }\n </div>\n</ng-template>\n" }]
|
|
24850
25157
|
}], propDecorators: { title: [{
|
|
24851
25158
|
type: Input
|
|
24852
25159
|
}], choices: [{
|
|
@@ -25018,7 +25325,7 @@ class DropdownSelectorComponent {
|
|
|
25018
25325
|
provideNgIconsConfig({
|
|
25019
25326
|
size: '1.5em',
|
|
25020
25327
|
}),
|
|
25021
|
-
], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "choiceInputs", predicate: ["choiceInputs"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"flex flex-col sm:flex-row sm:items-center relative w-full\">\n @if (showTitle) {\n <span\n class=\"tracking-wide text-sm mb-2 sm:mb-0 sm:mr-2 whitespace-nowrap\"\n [attr.for]=\"id\"\n >\n {{ title }}\n </span>\n }\n <gn-ui-button\n type=\"outline\"\n class=\"grow min-w-0\"\n [style.--gn-ui-button-padding]=\"'8px 8px 8px 16px'\"\n extraClass=\"bg-background flex flex-row w-full {{ extraBtnClass }}\"\n [title]=\"title\"\n [attr.aria-owns]=\"id\"\n (buttonClick)=\"openOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n (keydown)=\"handleTriggerKeydown($event)\"\n [disabled]=\"disabled\"\n >\n <div class=\"grow truncate py-1 mr-2 text-left\">\n {{ getChoiceLabel() | translate }}\n </div>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n </gn-ui-button>\n</div>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-300 rounded shadow-lg py-2 w-full overflow-x-hidden overflow-y-auto overlay-container\"\n [style.max-height]=\"overlayMaxHeight\"\n [style.min-width]=\"overlayWidth\"\n role=\"listbox\"\n tabindex=\"-1\"\n [attr.id]=\"id\"\n [attr.aria-multiselectable]=\"true\"\n [attr.aria-label]=\"title\"\n (keydown)=\"handleOverlayKeydown($event)\"\n >\n @for (choice of choices; track choice) {\n <button\n #choiceInputs\n type=\"button\"\n [title]=\"choice.label | translate\"\n class=\"flex px-5 py-1 w-full text-start cursor-pointer transition-colors\"\n [ngClass]=\"\n isSelected(choice)\n ? 'text-white bg-primary hover:text-white hover:bg-primary-darker focus:text-white focus:bg-primary-darker'\n : 'text-gray-900 hover:text-primary-darkest hover:bg-gray-50 focus:text-primary-darkest focus:bg-gray-50'\n \"\n (click)=\"onSelectValue(choice)\"\n (keydown)=\"selectIfEnter($event, choice)\"\n [attr.data-cy-value]=\"choice.value.toString()\"\n [attr.data-cy-active]=\"isSelected(choice) ? 'true' : undefined\"\n >\n <span class=\"text-[14px]\">\n {{ choice.label | translate }}\n </span>\n </button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$
|
|
25328
|
+
], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "choiceInputs", predicate: ["choiceInputs"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"flex flex-col sm:flex-row sm:items-center relative w-full\">\n @if (showTitle) {\n <span\n class=\"tracking-wide text-sm mb-2 sm:mb-0 sm:mr-2 whitespace-nowrap\"\n [attr.for]=\"id\"\n >\n {{ title }}\n </span>\n }\n <gn-ui-button\n type=\"outline\"\n class=\"grow min-w-0\"\n [style.--gn-ui-button-padding]=\"'8px 8px 8px 16px'\"\n extraClass=\"bg-background flex flex-row w-full {{ extraBtnClass }}\"\n [title]=\"title\"\n [attr.aria-owns]=\"id\"\n (buttonClick)=\"openOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n (keydown)=\"handleTriggerKeydown($event)\"\n [disabled]=\"disabled\"\n >\n <div class=\"grow truncate py-1 mr-2 text-left\">\n {{ getChoiceLabel() | translate }}\n </div>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n </gn-ui-button>\n</div>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-300 rounded shadow-lg py-2 w-full overflow-x-hidden overflow-y-auto overlay-container\"\n [style.max-height]=\"overlayMaxHeight\"\n [style.min-width]=\"overlayWidth\"\n role=\"listbox\"\n tabindex=\"-1\"\n [attr.id]=\"id\"\n [attr.aria-multiselectable]=\"true\"\n [attr.aria-label]=\"title\"\n (keydown)=\"handleOverlayKeydown($event)\"\n >\n @for (choice of choices; track choice) {\n <button\n #choiceInputs\n type=\"button\"\n [title]=\"choice.label | translate\"\n class=\"flex px-5 py-1 w-full text-start cursor-pointer transition-colors\"\n [ngClass]=\"\n isSelected(choice)\n ? 'text-white bg-primary hover:text-white hover:bg-primary-darker focus:text-white focus:bg-primary-darker'\n : 'text-gray-900 hover:text-primary-darkest hover:bg-gray-50 focus:text-primary-darkest focus:bg-gray-50'\n \"\n (click)=\"onSelectValue(choice)\"\n (keydown)=\"selectIfEnter($event, choice)\"\n [attr.data-cy-value]=\"choice.value.toString()\"\n [attr.data-cy-active]=\"isSelected(choice) ? 'true' : undefined\"\n >\n <span class=\"text-[14px]\">\n {{ choice.label | translate }}\n </span>\n </button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { 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: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
25022
25329
|
}
|
|
25023
25330
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DropdownSelectorComponent, decorators: [{
|
|
25024
25331
|
type: Component,
|
|
@@ -25758,6 +26065,180 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
25758
26065
|
type: Output
|
|
25759
26066
|
}] } });
|
|
25760
26067
|
|
|
26068
|
+
marker('search.filters.spatialExtent.import');
|
|
26069
|
+
marker('search.filters.spatialExtent.helpText');
|
|
26070
|
+
marker('search.filters.spatialExtent.error.title');
|
|
26071
|
+
marker('search.filters.spatialExtent.error.outOfBounds');
|
|
26072
|
+
const LABEL_FROM_FILE = marker('search.filters.spatialExtent.bboxFromFile');
|
|
26073
|
+
const LABEL_FROM_FILE_DELETE = marker('search.filters.spatialExtent.bboxFromFileDelete');
|
|
26074
|
+
const LABEL_INITIAL = marker('search.filters.spatialExtent.bboxInitial');
|
|
26075
|
+
const LABEL_INITIAL_DELETE = marker('search.filters.spatialExtent.bboxInitialDelete');
|
|
26076
|
+
class SpatialExtentDropdownComponent {
|
|
26077
|
+
constructor() {
|
|
26078
|
+
this.cd = inject(ChangeDetectorRef);
|
|
26079
|
+
this.scrollStrategies = inject(ScrollStrategyOptions);
|
|
26080
|
+
this.maxFileSizeMb = null;
|
|
26081
|
+
this.bboxChange = new EventEmitter();
|
|
26082
|
+
this.errorChange = new EventEmitter();
|
|
26083
|
+
this.bbox = null;
|
|
26084
|
+
this.fileName = '';
|
|
26085
|
+
this.overlayPositions = [
|
|
26086
|
+
{
|
|
26087
|
+
originX: 'start',
|
|
26088
|
+
originY: 'bottom',
|
|
26089
|
+
overlayX: 'start',
|
|
26090
|
+
overlayY: 'top',
|
|
26091
|
+
offsetY: 8,
|
|
26092
|
+
},
|
|
26093
|
+
{
|
|
26094
|
+
originX: 'start',
|
|
26095
|
+
originY: 'top',
|
|
26096
|
+
overlayX: 'start',
|
|
26097
|
+
overlayY: 'bottom',
|
|
26098
|
+
offsetY: -8,
|
|
26099
|
+
},
|
|
26100
|
+
];
|
|
26101
|
+
this.scrollStrategy = this.scrollStrategies.reposition();
|
|
26102
|
+
this.overlayOpen = false;
|
|
26103
|
+
this.overlayMinWidth = 'none';
|
|
26104
|
+
this.errorKey = null;
|
|
26105
|
+
}
|
|
26106
|
+
set initialBbox(value) {
|
|
26107
|
+
if (!this.bbox && value) {
|
|
26108
|
+
this.bbox = value;
|
|
26109
|
+
}
|
|
26110
|
+
}
|
|
26111
|
+
get hasSelection() {
|
|
26112
|
+
return !!this.bbox;
|
|
26113
|
+
}
|
|
26114
|
+
get selectionLabelKey() {
|
|
26115
|
+
return this.fileName ? LABEL_FROM_FILE : LABEL_INITIAL;
|
|
26116
|
+
}
|
|
26117
|
+
get selectionDeleteLabelKey() {
|
|
26118
|
+
return this.fileName ? LABEL_FROM_FILE_DELETE : LABEL_INITIAL_DELETE;
|
|
26119
|
+
}
|
|
26120
|
+
get selectionLabelParams() {
|
|
26121
|
+
return { fileName: this.fileName };
|
|
26122
|
+
}
|
|
26123
|
+
openOverlay() {
|
|
26124
|
+
this.overlayMinWidth =
|
|
26125
|
+
this.overlayOrigin.elementRef.nativeElement.getBoundingClientRect()
|
|
26126
|
+
.width + 'px';
|
|
26127
|
+
this.overlayOpen = true;
|
|
26128
|
+
}
|
|
26129
|
+
closeOverlay() {
|
|
26130
|
+
this.overlayOpen = false;
|
|
26131
|
+
}
|
|
26132
|
+
toggleOverlay() {
|
|
26133
|
+
if (this.overlayOpen) {
|
|
26134
|
+
this.closeOverlay();
|
|
26135
|
+
}
|
|
26136
|
+
else {
|
|
26137
|
+
this.openOverlay();
|
|
26138
|
+
}
|
|
26139
|
+
}
|
|
26140
|
+
async handleFileSelected(file) {
|
|
26141
|
+
this.errorKey = null;
|
|
26142
|
+
let content;
|
|
26143
|
+
try {
|
|
26144
|
+
content = await readFileAsText(file);
|
|
26145
|
+
const parsed = JSON.parse(content);
|
|
26146
|
+
const geometry = getGeometryFromGeoJSON(parsed);
|
|
26147
|
+
if (!geometry) {
|
|
26148
|
+
this.setError(marker('search.filters.spatialExtent.error.noGeometry'));
|
|
26149
|
+
return;
|
|
26150
|
+
}
|
|
26151
|
+
const bbox = getGeometryBoundingBox(geometry);
|
|
26152
|
+
if (!isBoundingBoxWithinWorldExtent(bbox)) {
|
|
26153
|
+
this.setError(marker('search.filters.spatialExtent.error.outOfBounds'));
|
|
26154
|
+
return;
|
|
26155
|
+
}
|
|
26156
|
+
this.bbox = bbox;
|
|
26157
|
+
this.fileName = file.name;
|
|
26158
|
+
this.bboxChange.emit(bbox);
|
|
26159
|
+
this.cd.markForCheck();
|
|
26160
|
+
}
|
|
26161
|
+
catch {
|
|
26162
|
+
this.setError(marker('search.filters.spatialExtent.error.invalidFormat'));
|
|
26163
|
+
return;
|
|
26164
|
+
}
|
|
26165
|
+
}
|
|
26166
|
+
handleFileError(error) {
|
|
26167
|
+
if (error === 'file-too-large') {
|
|
26168
|
+
this.setError(marker('search.filters.spatialExtent.error.fileTooLarge'), {
|
|
26169
|
+
maxSize: this.maxFileSizeMb,
|
|
26170
|
+
});
|
|
26171
|
+
}
|
|
26172
|
+
else {
|
|
26173
|
+
this.setError(marker('search.filters.spatialExtent.error.invalidFormat'));
|
|
26174
|
+
}
|
|
26175
|
+
}
|
|
26176
|
+
setError(errorKey, params) {
|
|
26177
|
+
this.errorKey = errorKey;
|
|
26178
|
+
this.errorChange.emit({ key: errorKey, params });
|
|
26179
|
+
this.cd.markForCheck();
|
|
26180
|
+
}
|
|
26181
|
+
removeSelection(event) {
|
|
26182
|
+
this.bbox = null;
|
|
26183
|
+
this.fileName = '';
|
|
26184
|
+
this.errorKey = null;
|
|
26185
|
+
this.fileInput?.clear();
|
|
26186
|
+
this.bboxChange.emit(null);
|
|
26187
|
+
propagateToDocumentOnly(event);
|
|
26188
|
+
}
|
|
26189
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpatialExtentDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
26190
|
+
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: [
|
|
26191
|
+
provideIcons({
|
|
26192
|
+
iconoirCheckCircle,
|
|
26193
|
+
iconoirSquareDashed,
|
|
26194
|
+
iconoirTrash,
|
|
26195
|
+
iconoirUpload,
|
|
26196
|
+
matClose,
|
|
26197
|
+
matExpandLess,
|
|
26198
|
+
matExpandMore,
|
|
26199
|
+
}),
|
|
26200
|
+
], 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 }); }
|
|
26201
|
+
}
|
|
26202
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpatialExtentDropdownComponent, decorators: [{
|
|
26203
|
+
type: Component,
|
|
26204
|
+
args: [{ selector: 'gn-ui-spatial-extent-dropdown', standalone: true, imports: [
|
|
26205
|
+
ButtonComponent,
|
|
26206
|
+
NgIcon,
|
|
26207
|
+
OverlayModule,
|
|
26208
|
+
TranslatePipe,
|
|
26209
|
+
DragAndDropFileInputComponent,
|
|
26210
|
+
], providers: [
|
|
26211
|
+
provideIcons({
|
|
26212
|
+
iconoirCheckCircle,
|
|
26213
|
+
iconoirSquareDashed,
|
|
26214
|
+
iconoirTrash,
|
|
26215
|
+
iconoirUpload,
|
|
26216
|
+
matClose,
|
|
26217
|
+
matExpandLess,
|
|
26218
|
+
matExpandMore,
|
|
26219
|
+
}),
|
|
26220
|
+
], 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" }]
|
|
26221
|
+
}], propDecorators: { title: [{
|
|
26222
|
+
type: Input
|
|
26223
|
+
}], maxFileSizeMb: [{
|
|
26224
|
+
type: Input
|
|
26225
|
+
}], initialBbox: [{
|
|
26226
|
+
type: Input
|
|
26227
|
+
}], bboxChange: [{
|
|
26228
|
+
type: Output
|
|
26229
|
+
}], errorChange: [{
|
|
26230
|
+
type: Output
|
|
26231
|
+
}], overlayOrigin: [{
|
|
26232
|
+
type: ViewChild,
|
|
26233
|
+
args: ['overlayOrigin']
|
|
26234
|
+
}], overlay: [{
|
|
26235
|
+
type: ViewChild,
|
|
26236
|
+
args: [CdkConnectedOverlay]
|
|
26237
|
+
}], fileInput: [{
|
|
26238
|
+
type: ViewChild,
|
|
26239
|
+
args: [DragAndDropFileInputComponent]
|
|
26240
|
+
}] } });
|
|
26241
|
+
|
|
25761
26242
|
class CellPopinComponent {
|
|
25762
26243
|
constructor() {
|
|
25763
26244
|
this.scrollDispatcher = inject(ScrollDispatcher);
|
|
@@ -25834,7 +26315,7 @@ class CellPopinComponent {
|
|
|
25834
26315
|
this.isOpen = false;
|
|
25835
26316
|
}
|
|
25836
26317
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CellPopinComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
25837
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: CellPopinComponent, isStandalone: true, selector: "gn-ui-cell-popin", inputs: { extraClass: "extraClass", cdkScrollContainer: "cdkScrollContainer", scrollContainer: "scrollContainer", activePopin: "activePopin" }, providers: [provideIcons({ iconoirReduce })], viewQueries: [{ propertyName: "anchorRef", first: true, predicate: ["anchorRef"], descendants: true }], ngImport: i0, template: "<div\n class=\"h-full flex items-center justify-center\"\n cdkOverlayOrigin\n #anchorRef\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"extraClass\"\n data-cy=\"cell-popin\"\n>\n <ng-content select=\"[cellContent]\"></ng-content>\n @if (activePopin) {\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayPush]=\"false\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayWidth]=\"'auto'\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayGrowAfterOpen]=\"true\"\n (detach)=\"closeOverlay()\"\n >\n @if (activePopin && isVisible) {\n <div\n class=\"bg-white shadow-lg border border-gray-300 relative\"\n data-cy=\"cell-popin-content\"\n >\n <ng-content select=\"[popinContent]\"></ng-content>\n <gn-ui-button\n data-cy=\"cell-popin-close\"\n [style.--gn-ui-button-background]=\"'bg-transparent'\"\n class=\"absolute top-2 right-2\"\n type=\"light\"\n (buttonClick)=\"closeOverlay()\"\n extraClass=\"w-10 h-8 px-1\"\n >\n <ng-icon name=\"iconoirReduce\" size=\"24\"></ng-icon>\n </gn-ui-button>\n </div>\n }\n </ng-template>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$
|
|
26318
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: CellPopinComponent, isStandalone: true, selector: "gn-ui-cell-popin", inputs: { extraClass: "extraClass", cdkScrollContainer: "cdkScrollContainer", scrollContainer: "scrollContainer", activePopin: "activePopin" }, providers: [provideIcons({ iconoirReduce })], viewQueries: [{ propertyName: "anchorRef", first: true, predicate: ["anchorRef"], descendants: true }], ngImport: i0, template: "<div\n class=\"h-full flex items-center justify-center\"\n cdkOverlayOrigin\n #anchorRef\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"extraClass\"\n data-cy=\"cell-popin\"\n>\n <ng-content select=\"[cellContent]\"></ng-content>\n @if (activePopin) {\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayPush]=\"false\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayWidth]=\"'auto'\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayGrowAfterOpen]=\"true\"\n (detach)=\"closeOverlay()\"\n >\n @if (activePopin && isVisible) {\n <div\n class=\"bg-white shadow-lg border border-gray-300 relative\"\n data-cy=\"cell-popin-content\"\n >\n <ng-content select=\"[popinContent]\"></ng-content>\n <gn-ui-button\n data-cy=\"cell-popin-close\"\n [style.--gn-ui-button-background]=\"'bg-transparent'\"\n class=\"absolute top-2 right-2\"\n type=\"light\"\n (buttonClick)=\"closeOverlay()\"\n extraClass=\"w-10 h-8 px-1\"\n >\n <ng-icon name=\"iconoirReduce\" size=\"24\"></ng-icon>\n </gn-ui-button>\n </div>\n }\n </ng-template>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { 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: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }] }); }
|
|
25838
26319
|
}
|
|
25839
26320
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CellPopinComponent, decorators: [{
|
|
25840
26321
|
type: Component,
|
|
@@ -26262,11 +26743,11 @@ class BlockListComponent {
|
|
|
26262
26743
|
this.goToPage(this.currentPage + 1);
|
|
26263
26744
|
}
|
|
26264
26745
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BlockListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
26265
|
-
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 }); }
|
|
26746
|
+
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 }); }
|
|
26266
26747
|
}
|
|
26267
26748
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BlockListComponent, decorators: [{
|
|
26268
26749
|
type: Component,
|
|
26269
|
-
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"] }]
|
|
26750
|
+
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"] }]
|
|
26270
26751
|
}], propDecorators: { containerClass: [{
|
|
26271
26752
|
type: Input
|
|
26272
26753
|
}], paginationContainerClass: [{
|
|
@@ -27456,6 +27937,70 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
27456
27937
|
}]
|
|
27457
27938
|
}] });
|
|
27458
27939
|
|
|
27940
|
+
const DEFAULT_GEOCODING_PROVIDER = [
|
|
27941
|
+
'geonames',
|
|
27942
|
+
{ maxRows: 5 },
|
|
27943
|
+
];
|
|
27944
|
+
const GEOCODING_PROVIDER = new InjectionToken('geocoding-provider', {
|
|
27945
|
+
providedIn: 'root',
|
|
27946
|
+
factory: () => DEFAULT_GEOCODING_PROVIDER,
|
|
27947
|
+
});
|
|
27948
|
+
class GeocodingService {
|
|
27949
|
+
constructor() {
|
|
27950
|
+
this.provider = inject(GEOCODING_PROVIDER);
|
|
27951
|
+
}
|
|
27952
|
+
query(text) {
|
|
27953
|
+
let queryObservable;
|
|
27954
|
+
switch (this.provider[0]) {
|
|
27955
|
+
case 'geoadmin':
|
|
27956
|
+
queryObservable = from(queryGeoadmin(text, this.provider[1]));
|
|
27957
|
+
break;
|
|
27958
|
+
case 'geonames':
|
|
27959
|
+
queryObservable = from(queryGeonames(text, this.provider[1]));
|
|
27960
|
+
break;
|
|
27961
|
+
case 'geoplateforme':
|
|
27962
|
+
queryObservable = from(queryGeoplateforme(text, this.provider[1]));
|
|
27963
|
+
break;
|
|
27964
|
+
default:
|
|
27965
|
+
return throwError(() => new Error(`Unsupported geocoding provider: ${this.provider[0]}`));
|
|
27966
|
+
}
|
|
27967
|
+
return queryObservable.pipe(catchError((error) => throwError(error)));
|
|
27968
|
+
}
|
|
27969
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
27970
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, providedIn: 'root' }); }
|
|
27971
|
+
}
|
|
27972
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingService, decorators: [{
|
|
27973
|
+
type: Injectable,
|
|
27974
|
+
args: [{
|
|
27975
|
+
providedIn: 'root',
|
|
27976
|
+
}]
|
|
27977
|
+
}] });
|
|
27978
|
+
|
|
27979
|
+
class LocationSearchComponent {
|
|
27980
|
+
constructor() {
|
|
27981
|
+
this.geocodingService = inject(GeocodingService);
|
|
27982
|
+
this.placeholder = '';
|
|
27983
|
+
this.resultSelected = new EventEmitter();
|
|
27984
|
+
this.displayWithFn = (item) => item.label;
|
|
27985
|
+
this.searchAction = (text) => this.geocodingService.query(text);
|
|
27986
|
+
}
|
|
27987
|
+
handleItemSelected(item) {
|
|
27988
|
+
this.resultSelected.emit(item);
|
|
27989
|
+
}
|
|
27990
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocationSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
27991
|
+
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 }); }
|
|
27992
|
+
}
|
|
27993
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocationSearchComponent, decorators: [{
|
|
27994
|
+
type: Component,
|
|
27995
|
+
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" }]
|
|
27996
|
+
}], propDecorators: { placeholder: [{
|
|
27997
|
+
type: Input
|
|
27998
|
+
}], displayWithTemplate: [{
|
|
27999
|
+
type: Input
|
|
28000
|
+
}], resultSelected: [{
|
|
28001
|
+
type: Output
|
|
28002
|
+
}] } });
|
|
28003
|
+
|
|
27459
28004
|
// expects the replacement key ${uuid}
|
|
27460
28005
|
const RECORD_DATASET_URL_TOKEN = new InjectionToken('record-dataset-url-token');
|
|
27461
28006
|
const RECORD_SERVICE_URL_TOKEN = new InjectionToken('record-service-url-token');
|
|
@@ -27924,6 +28469,45 @@ class DateRangeSearchField extends SimpleSearchField {
|
|
|
27924
28469
|
return 'dateRange';
|
|
27925
28470
|
}
|
|
27926
28471
|
}
|
|
28472
|
+
// treats a resource's creation/revision dates as an interval (its min and max), so a record matches
|
|
28473
|
+
// when that interval intersects the filter range, not just when a single date falls inside it
|
|
28474
|
+
class ResourceCreationRevisionDateSearchField extends DateRangeSearchField {
|
|
28475
|
+
constructor(injector, order = 'desc') {
|
|
28476
|
+
super('resourceCreationRevisionDate', injector, order);
|
|
28477
|
+
const dateSourceFields = [
|
|
28478
|
+
'creationDateForResource',
|
|
28479
|
+
'revisionDateForResource',
|
|
28480
|
+
];
|
|
28481
|
+
const collectSortedDates = dateSourceFields
|
|
28482
|
+
.map((field) => `if (doc.containsKey('${field}')) {
|
|
28483
|
+
for (def date : doc['${field}']) { dates.add(date.millis); }
|
|
28484
|
+
}`)
|
|
28485
|
+
.join('\n');
|
|
28486
|
+
this.esService.registerRuntimeField('resourceCreationRevisionDateMin', `def dates = [];
|
|
28487
|
+
${collectSortedDates}
|
|
28488
|
+
if (dates.length > 0) { dates.sort(null); emit(dates[0]); }`, 'date');
|
|
28489
|
+
this.esService.registerRuntimeField('resourceCreationRevisionDateMax', `def dates = [];
|
|
28490
|
+
${collectSortedDates}
|
|
28491
|
+
if (dates.length > 0) { dates.sort(null); emit(dates[dates.length - 1]); }`, 'date');
|
|
28492
|
+
}
|
|
28493
|
+
}
|
|
28494
|
+
class BoundingBoxSearchField extends SimpleSearchField {
|
|
28495
|
+
getAvailableValues() {
|
|
28496
|
+
return of([]);
|
|
28497
|
+
}
|
|
28498
|
+
getFiltersForValues(values) {
|
|
28499
|
+
return of({
|
|
28500
|
+
[this.esFieldName]: values.map(Number),
|
|
28501
|
+
});
|
|
28502
|
+
}
|
|
28503
|
+
getValuesForFilter(filters) {
|
|
28504
|
+
const filter = filters[this.esFieldName];
|
|
28505
|
+
return of(isBoundingBox(filter) ? filter : []);
|
|
28506
|
+
}
|
|
28507
|
+
getType() {
|
|
28508
|
+
return 'spatialExtent';
|
|
28509
|
+
}
|
|
28510
|
+
}
|
|
27927
28511
|
marker('search.filters.availableServices.view');
|
|
27928
28512
|
marker('search.filters.availableServices.download');
|
|
27929
28513
|
class AvailableServicesField extends SimpleSearchField {
|
|
@@ -28068,6 +28652,8 @@ marker('search.filters.producerOrg');
|
|
|
28068
28652
|
marker('search.filters.publisherOrg');
|
|
28069
28653
|
marker('search.filters.user');
|
|
28070
28654
|
marker('search.filters.changeDate');
|
|
28655
|
+
marker('search.filters.resourceCreationRevisionDate');
|
|
28656
|
+
marker('search.filters.spatialExtent');
|
|
28071
28657
|
class FieldsService {
|
|
28072
28658
|
constructor() {
|
|
28073
28659
|
this.injector = inject(Injector);
|
|
@@ -28090,7 +28676,9 @@ class FieldsService {
|
|
|
28090
28676
|
publisherOrg: new MultilingualSearchField('distributorOrgForResourceObject', this.injector, 'asc', 'key'),
|
|
28091
28677
|
user: new UserSearchField(this.injector),
|
|
28092
28678
|
changeDate: new DateRangeSearchField('changeDate', this.injector, 'desc'),
|
|
28679
|
+
resourceCreationRevisionDate: new ResourceCreationRevisionDateSearchField(this.injector, 'desc'),
|
|
28093
28680
|
availableServices: new AvailableServicesField(this.injector),
|
|
28681
|
+
spatialExtent: new BoundingBoxSearchField('spatialExtent', this.injector),
|
|
28094
28682
|
};
|
|
28095
28683
|
}
|
|
28096
28684
|
get supportedFields() {
|
|
@@ -29353,7 +29941,7 @@ class ContactPillComponent {
|
|
|
29353
29941
|
this.overlayOpen = false;
|
|
29354
29942
|
}
|
|
29355
29943
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContactPillComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
29356
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ContactPillComponent, isStandalone: true, selector: "gn-ui-contact-pill", inputs: { contact: "contact" }, ngImport: i0, template: "<gn-ui-button\n [type]=\"overlayOpen ? 'gray-light' : 'primary-light'\"\n extraClass=\"group w-full min-h-12 gap-3 justify-between py-2 pl-5 pr-4 rounded\"\n data-test=\"contact-pill\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <span\n class=\"font-title font-medium text-base leading-tight truncate\"\n [class]=\"!overlayOpen ? 'text-primary-black group-hover:text-white' : ''\"\n [title]=\"displayName\"\n >{{ displayName }}</span\n >\n <div\n class=\"gn-ui-card-icon items-center justify-center w-10 h-8\"\n [class]=\"\n !overlayOpen ? 'group-hover:border-white group-hover:text-white' : ''\n \"\n >\n @if (overlayOpen) {\n <ng-icon class=\"!w-6 !h-6 !text-[24px]\" name=\"matClose\"></ng-icon>\n } @else {\n <ng-icon class=\"!w-6 !h-6 !text-[24px]\" name=\"matInfoOutline\"></ng-icon>\n }\n </div>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayOffsetX]=\"overlayOffsetX\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div [style.width.px]=\"overlayWidth\">\n <gn-ui-contact-details [contact]=\"contact\"></gn-ui-contact-details>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$
|
|
29944
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ContactPillComponent, isStandalone: true, selector: "gn-ui-contact-pill", inputs: { contact: "contact" }, ngImport: i0, template: "<gn-ui-button\n [type]=\"overlayOpen ? 'gray-light' : 'primary-light'\"\n extraClass=\"group w-full min-h-12 gap-3 justify-between py-2 pl-5 pr-4 rounded\"\n data-test=\"contact-pill\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <span\n class=\"font-title font-medium text-base leading-tight truncate\"\n [class]=\"!overlayOpen ? 'text-primary-black group-hover:text-white' : ''\"\n [title]=\"displayName\"\n >{{ displayName }}</span\n >\n <div\n class=\"gn-ui-card-icon items-center justify-center w-10 h-8\"\n [class]=\"\n !overlayOpen ? 'group-hover:border-white group-hover:text-white' : ''\n \"\n >\n @if (overlayOpen) {\n <ng-icon class=\"!w-6 !h-6 !text-[24px]\" name=\"matClose\"></ng-icon>\n } @else {\n <ng-icon class=\"!w-6 !h-6 !text-[24px]\" name=\"matInfoOutline\"></ng-icon>\n }\n </div>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayOffsetX]=\"overlayOffsetX\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div [style.width.px]=\"overlayWidth\">\n <gn-ui-contact-details [contact]=\"contact\"></gn-ui-contact-details>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { 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: ContactDetailsComponent, selector: "gn-ui-contact-details", inputs: ["contact"] }], viewProviders: [provideIcons({ matClose, matInfoOutline })], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
29357
29945
|
}
|
|
29358
29946
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContactPillComponent, decorators: [{
|
|
29359
29947
|
type: Component,
|
|
@@ -30079,7 +30667,7 @@ class ServiceCapabilitiesComponent {
|
|
|
30079
30667
|
if (this.apiLinks.length > 0 &&
|
|
30080
30668
|
this.apiLinks[0].accessServiceProtocol !== 'ogcFeatures') {
|
|
30081
30669
|
this.loading = true;
|
|
30082
|
-
this.availableLayers = await getLayers(this.apiLinks[0].url.href, this.apiLinks[0].accessServiceProtocol);
|
|
30670
|
+
this.availableLayers = await getLayers(this.apiLinks[0].url.href, this.apiLinks[0].accessServiceProtocol, true);
|
|
30083
30671
|
this.loading = false;
|
|
30084
30672
|
this.cdr.detectChanges();
|
|
30085
30673
|
this.filteredLayers = this.availableLayers;
|
|
@@ -31275,19 +31863,118 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31275
31863
|
type: Output
|
|
31276
31864
|
}] } });
|
|
31277
31865
|
|
|
31866
|
+
class NotificationsService {
|
|
31867
|
+
constructor() {
|
|
31868
|
+
this.notifications$ = new BehaviorSubject([]);
|
|
31869
|
+
}
|
|
31870
|
+
showNotification(content, timeoutMs, error) {
|
|
31871
|
+
error && console.error(error);
|
|
31872
|
+
const id = Math.floor(Math.random() * 1000000);
|
|
31873
|
+
this.notifications$.next([...this.notifications$.value, { ...content, id }]);
|
|
31874
|
+
if (typeof timeoutMs !== 'undefined') {
|
|
31875
|
+
setTimeout(() => {
|
|
31876
|
+
this.removeNotificationById(id);
|
|
31877
|
+
}, timeoutMs);
|
|
31878
|
+
}
|
|
31879
|
+
return id;
|
|
31880
|
+
}
|
|
31881
|
+
removeNotificationById(id) {
|
|
31882
|
+
this.notifications$.next(this.notifications$.value.filter((n) => n.id !== id));
|
|
31883
|
+
}
|
|
31884
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
31885
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, providedIn: 'root' }); }
|
|
31886
|
+
}
|
|
31887
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, decorators: [{
|
|
31888
|
+
type: Injectable,
|
|
31889
|
+
args: [{
|
|
31890
|
+
providedIn: 'root',
|
|
31891
|
+
}]
|
|
31892
|
+
}] });
|
|
31893
|
+
|
|
31894
|
+
class NotificationsContainerComponent {
|
|
31895
|
+
constructor() {
|
|
31896
|
+
this.notificationsService = inject(NotificationsService);
|
|
31897
|
+
}
|
|
31898
|
+
trackById(index, notification) {
|
|
31899
|
+
return notification.id;
|
|
31900
|
+
}
|
|
31901
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31902
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NotificationsContainerComponent, isStandalone: true, selector: "gn-ui-notifications-container", ngImport: i0, 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", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NotificationComponent, selector: "gn-ui-notification", inputs: ["type", "title", "text", "closeMessage"], outputs: ["notificationClose"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], animations: [
|
|
31903
|
+
trigger('enterExit', [
|
|
31904
|
+
transition(':enter', [
|
|
31905
|
+
animate('150ms', keyframes([
|
|
31906
|
+
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31907
|
+
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31908
|
+
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31909
|
+
])),
|
|
31910
|
+
]),
|
|
31911
|
+
transition(':leave', [
|
|
31912
|
+
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31913
|
+
]),
|
|
31914
|
+
]),
|
|
31915
|
+
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31916
|
+
}
|
|
31917
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, decorators: [{
|
|
31918
|
+
type: Component,
|
|
31919
|
+
args: [{ selector: 'gn-ui-notifications-container', standalone: true, imports: [CommonModule, NotificationComponent], changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
31920
|
+
trigger('enterExit', [
|
|
31921
|
+
transition(':enter', [
|
|
31922
|
+
animate('150ms', keyframes([
|
|
31923
|
+
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31924
|
+
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31925
|
+
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31926
|
+
])),
|
|
31927
|
+
]),
|
|
31928
|
+
transition(':leave', [
|
|
31929
|
+
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31930
|
+
]),
|
|
31931
|
+
]),
|
|
31932
|
+
], 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" }]
|
|
31933
|
+
}] });
|
|
31934
|
+
|
|
31278
31935
|
class FilterDropdownComponent {
|
|
31279
31936
|
constructor() {
|
|
31280
31937
|
this.searchFacade = inject(SearchFacade);
|
|
31281
31938
|
this.searchService = inject(SearchService);
|
|
31282
31939
|
this.fieldsService = inject(FieldsService);
|
|
31940
|
+
this.notificationsService = inject(NotificationsService);
|
|
31941
|
+
this.translateService = inject(TranslateService);
|
|
31942
|
+
this.spatialExtentMaxFileSize = getOptionalSearchConfig()?.SPATIAL_EXTENT_MAX_FILE_SIZE;
|
|
31283
31943
|
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([])));
|
|
31284
|
-
this.selectedDateRange$ = this.selected$.pipe(map$1((
|
|
31944
|
+
this.selectedDateRange$ = this.selected$.pipe(map$1((selected) => (Array.isArray(selected) ? {} : selected)));
|
|
31945
|
+
this.selectedBoundingBox$ = this.selected$.pipe(map$1((selected) => Array.isArray(selected) && selected.length > 0
|
|
31946
|
+
? selected
|
|
31947
|
+
: null));
|
|
31948
|
+
this.spatialExtentErrorNotificationId = null;
|
|
31285
31949
|
}
|
|
31286
31950
|
onSelectedValues(values) {
|
|
31287
31951
|
this.fieldsService
|
|
31288
31952
|
.buildFiltersFromFieldValues({ [this.fieldName]: values })
|
|
31289
31953
|
.subscribe((filters) => this.searchService.updateFilters(filters));
|
|
31290
31954
|
}
|
|
31955
|
+
onBboxChange(bbox) {
|
|
31956
|
+
this.fieldsService
|
|
31957
|
+
.buildFiltersFromFieldValues({
|
|
31958
|
+
[this.fieldName]: bbox,
|
|
31959
|
+
})
|
|
31960
|
+
.subscribe((filters) => this.searchService.updateFilters(filters));
|
|
31961
|
+
this.clearSpatialExtentErrorNotification();
|
|
31962
|
+
}
|
|
31963
|
+
onSpatialExtentError(error) {
|
|
31964
|
+
this.clearSpatialExtentErrorNotification();
|
|
31965
|
+
this.spatialExtentErrorNotificationId =
|
|
31966
|
+
this.notificationsService.showNotification({
|
|
31967
|
+
type: 'error',
|
|
31968
|
+
title: this.translateService.instant('search.filters.spatialExtent.error.title'),
|
|
31969
|
+
text: this.translateService.instant(error.key, error.params),
|
|
31970
|
+
});
|
|
31971
|
+
}
|
|
31972
|
+
clearSpatialExtentErrorNotification() {
|
|
31973
|
+
if (this.spatialExtentErrorNotificationId === null)
|
|
31974
|
+
return;
|
|
31975
|
+
this.notificationsService.removeNotificationById(this.spatialExtentErrorNotificationId);
|
|
31976
|
+
this.spatialExtentErrorNotificationId = null;
|
|
31977
|
+
}
|
|
31291
31978
|
ngOnInit() {
|
|
31292
31979
|
this.fieldType = this.fieldsService.getFieldType(this.fieldName);
|
|
31293
31980
|
this.choices$ = this.fieldsService.getAvailableValues(this.fieldName).pipe(startWith$1([]), map$1((values) => values.map((v) => ({
|
|
@@ -31295,27 +31982,15 @@ class FilterDropdownComponent {
|
|
|
31295
31982
|
value: v.value.toString(), // converting to string for the dropdown
|
|
31296
31983
|
}))), catchError(() => of([])));
|
|
31297
31984
|
}
|
|
31298
|
-
|
|
31299
|
-
|
|
31300
|
-
|
|
31301
|
-
|
|
31302
|
-
|
|
31303
|
-
|
|
31304
|
-
if (!end)
|
|
31305
|
-
return;
|
|
31306
|
-
this.dateRange = { ...this.dateRange, end };
|
|
31307
|
-
if (this.dateRange.start && this.dateRange.end) {
|
|
31308
|
-
this.fieldsService
|
|
31309
|
-
.buildFiltersFromFieldValues({
|
|
31310
|
-
[this.fieldName]: this.dateRange,
|
|
31311
|
-
})
|
|
31312
|
-
.subscribe((filters) => {
|
|
31313
|
-
return this.searchService.updateFilters(filters);
|
|
31314
|
-
});
|
|
31315
|
-
}
|
|
31985
|
+
onDateRangeChange(dateRange) {
|
|
31986
|
+
this.fieldsService
|
|
31987
|
+
.buildFiltersFromFieldValues({
|
|
31988
|
+
[this.fieldName]: dateRange,
|
|
31989
|
+
})
|
|
31990
|
+
.subscribe((filters) => this.searchService.updateFilters(filters));
|
|
31316
31991
|
}
|
|
31317
31992
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31318
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FilterDropdownComponent, isStandalone: true, selector: "gn-ui-filter-dropdown", inputs: { fieldName: "fieldName", title: "title" }, ngImport: i0, template: "@if (fieldType === 'dateRange') {\n <gn-ui-date-range-dropdown\n [title]=\"title\"\n [
|
|
31993
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FilterDropdownComponent, isStandalone: true, selector: "gn-ui-filter-dropdown", inputs: { fieldName: "fieldName", title: "title" }, ngImport: i0, template: "@if (fieldType === 'dateRange') {\n <gn-ui-date-range-dropdown\n [title]=\"title\"\n [dateRange]=\"(selectedDateRange$ | async) ?? {}\"\n (dateRangeChange)=\"onDateRangeChange($event)\"\n [attr.data-cy-field]=\"fieldName\"\n ></gn-ui-date-range-dropdown>\n} @else if (fieldType === 'spatialExtent') {\n <gn-ui-spatial-extent-dropdown\n [title]=\"title\"\n [initialBbox]=\"(selectedBoundingBox$ | async) ?? null\"\n [maxFileSizeMb]=\"spatialExtentMaxFileSize\"\n (bboxChange)=\"onBboxChange($event)\"\n (errorChange)=\"onSpatialExtentError($event)\"\n [attr.data-cy-field]=\"fieldName\"\n ></gn-ui-spatial-extent-dropdown>\n} @else {\n <gn-ui-dropdown-multiselect\n class=\"w-full\"\n [title]=\"title\"\n [maxRows]=\"6\"\n [choices]=\"(choices$ | async) || []\"\n [selected]=\"selected$ | async\"\n [allowSearch]=\"true\"\n (selectValues)=\"onSelectedValues($event)\"\n [attr.data-cy-field]=\"fieldName\"\n >\n </gn-ui-dropdown-multiselect>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DateRangeDropdownComponent, selector: "gn-ui-date-range-dropdown", inputs: ["title", "dateRange"], outputs: ["dateRangeChange"] }, { kind: "component", type: DropdownMultiselectComponent, selector: "gn-ui-dropdown-multiselect", inputs: ["title", "choices", "selected", "allowSearch", "maxRows", "searchInputValue"], outputs: ["selectValues"] }, { kind: "component", type: SpatialExtentDropdownComponent, selector: "gn-ui-spatial-extent-dropdown", inputs: ["title", "maxFileSizeMb", "initialBbox"], outputs: ["bboxChange", "errorChange"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31319
31994
|
}
|
|
31320
31995
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterDropdownComponent, decorators: [{
|
|
31321
31996
|
type: Component,
|
|
@@ -31323,7 +31998,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31323
31998
|
CommonModule,
|
|
31324
31999
|
DateRangeDropdownComponent,
|
|
31325
32000
|
DropdownMultiselectComponent,
|
|
31326
|
-
|
|
32001
|
+
SpatialExtentDropdownComponent,
|
|
32002
|
+
], template: "@if (fieldType === 'dateRange') {\n <gn-ui-date-range-dropdown\n [title]=\"title\"\n [dateRange]=\"(selectedDateRange$ | async) ?? {}\"\n (dateRangeChange)=\"onDateRangeChange($event)\"\n [attr.data-cy-field]=\"fieldName\"\n ></gn-ui-date-range-dropdown>\n} @else if (fieldType === 'spatialExtent') {\n <gn-ui-spatial-extent-dropdown\n [title]=\"title\"\n [initialBbox]=\"(selectedBoundingBox$ | async) ?? null\"\n [maxFileSizeMb]=\"spatialExtentMaxFileSize\"\n (bboxChange)=\"onBboxChange($event)\"\n (errorChange)=\"onSpatialExtentError($event)\"\n [attr.data-cy-field]=\"fieldName\"\n ></gn-ui-spatial-extent-dropdown>\n} @else {\n <gn-ui-dropdown-multiselect\n class=\"w-full\"\n [title]=\"title\"\n [maxRows]=\"6\"\n [choices]=\"(choices$ | async) || []\"\n [selected]=\"selected$ | async\"\n [allowSearch]=\"true\"\n (selectValues)=\"onSelectedValues($event)\"\n [attr.data-cy-field]=\"fieldName\"\n >\n </gn-ui-dropdown-multiselect>\n}\n" }]
|
|
31327
32003
|
}], propDecorators: { fieldName: [{
|
|
31328
32004
|
type: Input
|
|
31329
32005
|
}], title: [{
|
|
@@ -31384,7 +32060,7 @@ class FuzzySearchComponent {
|
|
|
31384
32060
|
this.isSearchActive.emit(event);
|
|
31385
32061
|
}
|
|
31386
32062
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FuzzySearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31387
|
-
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 }); }
|
|
32063
|
+
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 }); }
|
|
31388
32064
|
}
|
|
31389
32065
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FuzzySearchComponent, decorators: [{
|
|
31390
32066
|
type: Component,
|
|
@@ -31793,11 +32469,7 @@ const SortByEnum = {
|
|
|
31793
32469
|
RELEVANCY: ['desc', '_score'],
|
|
31794
32470
|
QUALITY_SCORE: ['desc', 'qualityScore'],
|
|
31795
32471
|
CHANGE_DATE: ['desc', 'changeDate'],
|
|
31796
|
-
|
|
31797
|
-
['desc', 'revisionDateForResource'],
|
|
31798
|
-
['desc', 'publicationDateForResource'],
|
|
31799
|
-
['desc', 'creationDateForResource'],
|
|
31800
|
-
],
|
|
32472
|
+
RESOURCE_DATE: ['desc', 'resourceDate.date'],
|
|
31801
32473
|
};
|
|
31802
32474
|
|
|
31803
32475
|
class SortByComponent {
|
|
@@ -31811,7 +32483,7 @@ class SortByComponent {
|
|
|
31811
32483
|
},
|
|
31812
32484
|
{
|
|
31813
32485
|
label: marker('results.sortBy.dateStamp'),
|
|
31814
|
-
value: SortByEnum.
|
|
32486
|
+
value: SortByEnum.RESOURCE_DATE,
|
|
31815
32487
|
},
|
|
31816
32488
|
{
|
|
31817
32489
|
label: marker('results.sortBy.popularity'),
|
|
@@ -31863,74 +32535,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31863
32535
|
args: ['gnUiSearchStateContainer']
|
|
31864
32536
|
}] } });
|
|
31865
32537
|
|
|
31866
|
-
class NotificationsService {
|
|
31867
|
-
constructor() {
|
|
31868
|
-
this.notifications$ = new BehaviorSubject([]);
|
|
31869
|
-
}
|
|
31870
|
-
showNotification(content, timeoutMs, error) {
|
|
31871
|
-
error && console.error(error);
|
|
31872
|
-
const id = Math.floor(Math.random() * 1000000);
|
|
31873
|
-
this.notifications$.next([...this.notifications$.value, { ...content, id }]);
|
|
31874
|
-
if (typeof timeoutMs === 'undefined')
|
|
31875
|
-
return;
|
|
31876
|
-
setTimeout(() => {
|
|
31877
|
-
this.removeNotificationById(id);
|
|
31878
|
-
}, timeoutMs);
|
|
31879
|
-
}
|
|
31880
|
-
removeNotificationById(id) {
|
|
31881
|
-
this.notifications$.next(this.notifications$.value.filter((n) => n.id !== id));
|
|
31882
|
-
}
|
|
31883
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
31884
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, providedIn: 'root' }); }
|
|
31885
|
-
}
|
|
31886
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, decorators: [{
|
|
31887
|
-
type: Injectable,
|
|
31888
|
-
args: [{
|
|
31889
|
-
providedIn: 'root',
|
|
31890
|
-
}]
|
|
31891
|
-
}] });
|
|
31892
|
-
|
|
31893
|
-
class NotificationsContainerComponent {
|
|
31894
|
-
constructor() {
|
|
31895
|
-
this.notificationsService = inject(NotificationsService);
|
|
31896
|
-
}
|
|
31897
|
-
trackById(index, notification) {
|
|
31898
|
-
return notification.id;
|
|
31899
|
-
}
|
|
31900
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31901
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NotificationsContainerComponent, isStandalone: true, selector: "gn-ui-notifications-container", ngImport: i0, 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", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NotificationComponent, selector: "gn-ui-notification", inputs: ["type", "title", "text", "closeMessage"], outputs: ["notificationClose"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], animations: [
|
|
31902
|
-
trigger('enterExit', [
|
|
31903
|
-
transition(':enter', [
|
|
31904
|
-
animate('150ms', keyframes([
|
|
31905
|
-
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31906
|
-
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31907
|
-
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31908
|
-
])),
|
|
31909
|
-
]),
|
|
31910
|
-
transition(':leave', [
|
|
31911
|
-
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31912
|
-
]),
|
|
31913
|
-
]),
|
|
31914
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31915
|
-
}
|
|
31916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, decorators: [{
|
|
31917
|
-
type: Component,
|
|
31918
|
-
args: [{ selector: 'gn-ui-notifications-container', standalone: true, imports: [CommonModule, NotificationComponent], changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
31919
|
-
trigger('enterExit', [
|
|
31920
|
-
transition(':enter', [
|
|
31921
|
-
animate('150ms', keyframes([
|
|
31922
|
-
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31923
|
-
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31924
|
-
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31925
|
-
])),
|
|
31926
|
-
]),
|
|
31927
|
-
transition(':leave', [
|
|
31928
|
-
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31929
|
-
]),
|
|
31930
|
-
]),
|
|
31931
|
-
], 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" }]
|
|
31932
|
-
}] });
|
|
31933
|
-
|
|
31934
32538
|
class ResultsTableContainerComponent {
|
|
31935
32539
|
constructor() {
|
|
31936
32540
|
this.searchFacade = inject(SearchFacade);
|
|
@@ -32015,12 +32619,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
32015
32619
|
|
|
32016
32620
|
marker('search.filters.summaryLabel.user');
|
|
32017
32621
|
marker('search.filters.summaryLabel.changeDate');
|
|
32622
|
+
marker('search.filters.summaryLabel.resourceCreationRevisionDate');
|
|
32623
|
+
const OPEN_BOUND = '…';
|
|
32018
32624
|
class SearchFiltersSummaryItemComponent {
|
|
32019
32625
|
constructor() {
|
|
32020
32626
|
this.searchFacade = inject(SearchFacade);
|
|
32021
32627
|
this.searchService = inject(SearchService);
|
|
32022
32628
|
this.fieldsService = inject(FieldsService);
|
|
32023
|
-
this.
|
|
32629
|
+
this.dateService = inject(DateService);
|
|
32024
32630
|
this.translate = inject(TranslateService);
|
|
32025
32631
|
this.fieldValues$ = this.searchFacade.searchFilters$.pipe(switchMap((filters) => this.fieldsService.readFieldValuesFromFilters(filters)), map$2((fieldValues) => Array.isArray(fieldValues[this.fieldName])
|
|
32026
32632
|
? fieldValues[this.fieldName]
|
|
@@ -32047,9 +32653,10 @@ class SearchFiltersSummaryItemComponent {
|
|
|
32047
32653
|
getReadableValues(fieldValues) {
|
|
32048
32654
|
return fieldValues.map((value) => {
|
|
32049
32655
|
if (this.fieldType === 'dateRange') {
|
|
32656
|
+
const { start, end } = value;
|
|
32050
32657
|
return {
|
|
32051
32658
|
value,
|
|
32052
|
-
label: `${this.
|
|
32659
|
+
label: `${this.formatBound(start)} - ${this.formatBound(end)}`,
|
|
32053
32660
|
};
|
|
32054
32661
|
}
|
|
32055
32662
|
else if (this.fieldName === 'user') {
|
|
@@ -32060,6 +32667,15 @@ class SearchFiltersSummaryItemComponent {
|
|
|
32060
32667
|
}
|
|
32061
32668
|
});
|
|
32062
32669
|
}
|
|
32670
|
+
formatBound(date) {
|
|
32671
|
+
return date
|
|
32672
|
+
? this.dateService.formatDate(date, {
|
|
32673
|
+
day: '2-digit',
|
|
32674
|
+
month: '2-digit',
|
|
32675
|
+
year: 'numeric',
|
|
32676
|
+
})
|
|
32677
|
+
: OPEN_BOUND;
|
|
32678
|
+
}
|
|
32063
32679
|
async removeFilterValue(fieldValue) {
|
|
32064
32680
|
const currentFieldValues = await firstValueFrom(this.fieldValues$);
|
|
32065
32681
|
const updatedFieldValues = currentFieldValues
|
|
@@ -32072,11 +32688,11 @@ class SearchFiltersSummaryItemComponent {
|
|
|
32072
32688
|
.subscribe((filters) => this.searchService.updateFilters(filters));
|
|
32073
32689
|
}
|
|
32074
32690
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SearchFiltersSummaryItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32075
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SearchFiltersSummaryItemComponent, isStandalone: true, selector: "gn-ui-search-filters-summary-item", inputs: { fieldName: "fieldName" },
|
|
32691
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SearchFiltersSummaryItemComponent, isStandalone: true, selector: "gn-ui-search-filters-summary-item", inputs: { fieldName: "fieldName" }, ngImport: i0, template: "@if ((fieldValues$ | async)?.length > 0) {\n <div class=\"flex flex-row items-center gap-2\">\n <span class=\"text-gray-800\" data-cy=\"filterSummaryLabel\">{{\n translatedLabel\n }}</span>\n @for (fieldValue of fieldValues$ | async; track fieldValue) {\n <gn-ui-badge\n class=\"gn-ui-badge\"\n [style.--gn-ui-badge-rounded]=\"'8px'\"\n [style.--gn-ui-badge-padding]=\"'3px 4px'\"\n [style.--gn-ui-badge-text-color]=\"'black'\"\n [style.--gn-ui-badge-background-color]=\"'#F2F2F2'\"\n [style.--gn-ui-badge-font-weight]=\"'700'\"\n [removable]=\"true\"\n (badgeRemoveClicked)=\"removeFilterValue(fieldValue.value)\"\n >{{ fieldValue.label }}</gn-ui-badge\n >\n }\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BadgeComponent, selector: "gn-ui-badge", inputs: ["clickable", "removable"], outputs: ["badgeRemoveClicked", "badgeClicked"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
|
|
32076
32692
|
}
|
|
32077
32693
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SearchFiltersSummaryItemComponent, decorators: [{
|
|
32078
32694
|
type: Component,
|
|
32079
|
-
args: [{ selector: 'gn-ui-search-filters-summary-item', standalone: true, imports: [CommonModule, BadgeComponent],
|
|
32695
|
+
args: [{ selector: 'gn-ui-search-filters-summary-item', standalone: true, imports: [CommonModule, BadgeComponent], template: "@if ((fieldValues$ | async)?.length > 0) {\n <div class=\"flex flex-row items-center gap-2\">\n <span class=\"text-gray-800\" data-cy=\"filterSummaryLabel\">{{\n translatedLabel\n }}</span>\n @for (fieldValue of fieldValues$ | async; track fieldValue) {\n <gn-ui-badge\n class=\"gn-ui-badge\"\n [style.--gn-ui-badge-rounded]=\"'8px'\"\n [style.--gn-ui-badge-padding]=\"'3px 4px'\"\n [style.--gn-ui-badge-text-color]=\"'black'\"\n [style.--gn-ui-badge-background-color]=\"'#F2F2F2'\"\n [style.--gn-ui-badge-font-weight]=\"'700'\"\n [removable]=\"true\"\n (badgeRemoveClicked)=\"removeFilterValue(fieldValue.value)\"\n >{{ fieldValue.label }}</gn-ui-badge\n >\n }\n </div>\n}\n" }]
|
|
32080
32696
|
}], propDecorators: { fieldName: [{
|
|
32081
32697
|
type: Input
|
|
32082
32698
|
}] } });
|
|
@@ -32320,11 +32936,11 @@ class AddLayerFromFileComponent {
|
|
|
32320
32936
|
}, 5000);
|
|
32321
32937
|
}
|
|
32322
32938
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AddLayerFromFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32323
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AddLayerFromFileComponent, isStandalone: true, selector: "gn-ui-add-layer-from-file", ngImport: i0, template: "<div class=\"flex flex-col gap-2 my-2\">\n <div class=\"flex items-center gap-4\">\n <div class=\"grow rounded-md border-2 border-gray-200\">\n <gn-ui-drag-and-drop-file-input\n (fileChange)=\"handleFileChange($event)\"\n [accept]=\"acceptedMimeType.join(',')\"\n [placeholder]=\"'map.addFromFile.placeholder' | translate\"\n class=\"placeholder-grey\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n </div>\n <p class=\"text-sm text-gray-600\" translate>map.help.addFromFile</p>\n</div>\n\n@if (errorMessage) {\n <div class=\"text-red-500 mt-2\">\n {{ errorMessage }}\n </div>\n}\n\n@if (successMessage) {\n <div class=\"text-green-500 mt-2\">\n {{ successMessage }}\n </div>\n}\n", styles: [""], dependencies: [{ kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: DragAndDropFileInputComponent, selector: "gn-ui-drag-and-drop-file-input", inputs: ["placeholder", "accept"], outputs: ["fileChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
32939
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AddLayerFromFileComponent, isStandalone: true, selector: "gn-ui-add-layer-from-file", ngImport: i0, template: "<div class=\"flex flex-col gap-2 my-2\">\n <div class=\"flex items-center gap-4\">\n <div class=\"grow rounded-md border-2 border-gray-200\">\n <gn-ui-drag-and-drop-file-input\n (fileChange)=\"handleFileChange($event)\"\n [accept]=\"acceptedMimeType.join(',')\"\n [placeholder]=\"'map.addFromFile.placeholder' | translate\"\n textClass=\"text-gray-900 pl-2 py-2\"\n class=\"placeholder-grey\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n </div>\n <p class=\"text-sm text-gray-600\" translate>map.help.addFromFile</p>\n</div>\n\n@if (errorMessage) {\n <div class=\"text-red-500 mt-2\">\n {{ errorMessage }}\n </div>\n}\n\n@if (successMessage) {\n <div class=\"text-green-500 mt-2\">\n {{ successMessage }}\n </div>\n}\n", styles: [""], dependencies: [{ kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { 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" }] }); }
|
|
32324
32940
|
}
|
|
32325
32941
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AddLayerFromFileComponent, decorators: [{
|
|
32326
32942
|
type: Component,
|
|
32327
|
-
args: [{ selector: 'gn-ui-add-layer-from-file', standalone: true, imports: [TranslateDirective, TranslatePipe, DragAndDropFileInputComponent], template: "<div class=\"flex flex-col gap-2 my-2\">\n <div class=\"flex items-center gap-4\">\n <div class=\"grow rounded-md border-2 border-gray-200\">\n <gn-ui-drag-and-drop-file-input\n (fileChange)=\"handleFileChange($event)\"\n [accept]=\"acceptedMimeType.join(',')\"\n [placeholder]=\"'map.addFromFile.placeholder' | translate\"\n class=\"placeholder-grey\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n </div>\n <p class=\"text-sm text-gray-600\" translate>map.help.addFromFile</p>\n</div>\n\n@if (errorMessage) {\n <div class=\"text-red-500 mt-2\">\n {{ errorMessage }}\n </div>\n}\n\n@if (successMessage) {\n <div class=\"text-green-500 mt-2\">\n {{ successMessage }}\n </div>\n}\n" }]
|
|
32943
|
+
args: [{ selector: 'gn-ui-add-layer-from-file', standalone: true, imports: [TranslateDirective, TranslatePipe, DragAndDropFileInputComponent], template: "<div class=\"flex flex-col gap-2 my-2\">\n <div class=\"flex items-center gap-4\">\n <div class=\"grow rounded-md border-2 border-gray-200\">\n <gn-ui-drag-and-drop-file-input\n (fileChange)=\"handleFileChange($event)\"\n [accept]=\"acceptedMimeType.join(',')\"\n [placeholder]=\"'map.addFromFile.placeholder' | translate\"\n textClass=\"text-gray-900 pl-2 py-2\"\n class=\"placeholder-grey\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n </div>\n <p class=\"text-sm text-gray-600\" translate>map.help.addFromFile</p>\n</div>\n\n@if (errorMessage) {\n <div class=\"text-red-500 mt-2\">\n {{ errorMessage }}\n </div>\n}\n\n@if (successMessage) {\n <div class=\"text-green-500 mt-2\">\n {{ successMessage }}\n </div>\n}\n" }]
|
|
32328
32944
|
}] });
|
|
32329
32945
|
|
|
32330
32946
|
class LayersPanelComponent {
|
|
@@ -32385,95 +33001,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
32385
33001
|
], 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" }]
|
|
32386
33002
|
}] });
|
|
32387
33003
|
|
|
32388
|
-
class GeocodingComponent {
|
|
32389
|
-
constructor() {
|
|
32390
|
-
this.mapFacade = inject(MapFacade);
|
|
32391
|
-
this.geocodingService = inject(GeocodingService);
|
|
32392
|
-
this.searchText = '';
|
|
32393
|
-
this.results = [];
|
|
32394
|
-
this.searchTextChanged = new Subject();
|
|
32395
|
-
this.destroy$ = new Subject();
|
|
32396
|
-
this.errorMessage = null;
|
|
32397
|
-
this.searchTextChanged
|
|
32398
|
-
.pipe(debounceTime(300), switchMap$1((searchText) => {
|
|
32399
|
-
return from(this.geocodingService.query(searchText)).pipe(catchError$1((error) => {
|
|
32400
|
-
this.errorMessage =
|
|
32401
|
-
'An error occurred while searching. Please try again.';
|
|
32402
|
-
console.error(error);
|
|
32403
|
-
return [];
|
|
32404
|
-
}));
|
|
32405
|
-
}), takeUntil(this.destroy$))
|
|
32406
|
-
.subscribe((results) => {
|
|
32407
|
-
this.results = results;
|
|
32408
|
-
});
|
|
32409
|
-
}
|
|
32410
|
-
ngOnDestroy() {
|
|
32411
|
-
this.destroy$.next();
|
|
32412
|
-
this.destroy$.complete();
|
|
32413
|
-
}
|
|
32414
|
-
onSearchChange(searchText) {
|
|
32415
|
-
if (!searchText) {
|
|
32416
|
-
this.clearSearch();
|
|
32417
|
-
return;
|
|
32418
|
-
}
|
|
32419
|
-
else {
|
|
32420
|
-
this.searchTextChanged.next(searchText);
|
|
32421
|
-
}
|
|
32422
|
-
}
|
|
32423
|
-
clearSearch() {
|
|
32424
|
-
this.searchText = '';
|
|
32425
|
-
this.results = [];
|
|
32426
|
-
this.errorMessage = null;
|
|
32427
|
-
}
|
|
32428
|
-
async zoomToLocation(result) {
|
|
32429
|
-
const geometry = result.geom;
|
|
32430
|
-
if (geometry.type === 'Point') {
|
|
32431
|
-
await this.zoomToPoint(geometry.coordinates);
|
|
32432
|
-
}
|
|
32433
|
-
else if (geometry.type === 'Polygon') {
|
|
32434
|
-
await this.zoomToPolygon(geometry.coordinates);
|
|
32435
|
-
}
|
|
32436
|
-
else {
|
|
32437
|
-
console.error(`Unsupported geometry type: ${geometry.type}`);
|
|
32438
|
-
}
|
|
32439
|
-
}
|
|
32440
|
-
async zoomToPoint(pointCoords) {
|
|
32441
|
-
const context = await firstValueFrom(this.mapFacade.context$);
|
|
32442
|
-
const view = {
|
|
32443
|
-
center: pointCoords,
|
|
32444
|
-
zoom: 10,
|
|
32445
|
-
};
|
|
32446
|
-
this.mapFacade.applyContext({
|
|
32447
|
-
...context,
|
|
32448
|
-
view,
|
|
32449
|
-
});
|
|
32450
|
-
}
|
|
32451
|
-
async zoomToPolygon(polygonCoords) {
|
|
32452
|
-
const context = await firstValueFrom(this.mapFacade.context$);
|
|
32453
|
-
const view = {
|
|
32454
|
-
geometry: {
|
|
32455
|
-
type: 'Polygon',
|
|
32456
|
-
coordinates: polygonCoords,
|
|
32457
|
-
},
|
|
32458
|
-
};
|
|
32459
|
-
this.mapFacade.applyContext({
|
|
32460
|
-
...context,
|
|
32461
|
-
view,
|
|
32462
|
-
});
|
|
32463
|
-
}
|
|
32464
|
-
onEnterPress() {
|
|
32465
|
-
if (this.results && this.results.length > 0) {
|
|
32466
|
-
this.zoomToLocation(this.results[0]);
|
|
32467
|
-
}
|
|
32468
|
-
}
|
|
32469
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32470
|
-
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" }] }); }
|
|
32471
|
-
}
|
|
32472
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GeocodingComponent, decorators: [{
|
|
32473
|
-
type: Component,
|
|
32474
|
-
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" }]
|
|
32475
|
-
}], ctorParameters: () => [] });
|
|
32476
|
-
|
|
32477
33004
|
/*
|
|
32478
33005
|
Metadata actions
|
|
32479
33006
|
*/
|
|
@@ -32489,8 +33016,7 @@ const closeMetadata = createAction('[Metadata view] close');
|
|
|
32489
33016
|
Related actions
|
|
32490
33017
|
*/
|
|
32491
33018
|
const setRelated = createAction('[Metadata view] Set related records', props());
|
|
32492
|
-
const
|
|
32493
|
-
const setSourceOf = createAction('[Metadata view] Set has sources', props());
|
|
33019
|
+
const setLinkedRecords = createAction('[Metadata view] Set associated records', props());
|
|
32494
33020
|
/*
|
|
32495
33021
|
ChartConfig actions
|
|
32496
33022
|
*/
|
|
@@ -32522,9 +33048,8 @@ var mdview_actions = /*#__PURE__*/Object.freeze({
|
|
|
32522
33048
|
loadUserFeedbacksSuccess: loadUserFeedbacksSuccess,
|
|
32523
33049
|
setChartConfig: setChartConfig,
|
|
32524
33050
|
setIncompleteMetadata: setIncompleteMetadata,
|
|
32525
|
-
|
|
32526
|
-
|
|
32527
|
-
setSources: setSources
|
|
33051
|
+
setLinkedRecords: setLinkedRecords,
|
|
33052
|
+
setRelated: setRelated
|
|
32528
33053
|
});
|
|
32529
33054
|
|
|
32530
33055
|
const METADATA_VIEW_FEATURE_STATE_KEY = 'metadataView';
|
|
@@ -32567,12 +33092,9 @@ on(loadFullMetadata, (state) => ({
|
|
|
32567
33092
|
on(setRelated, (state, { related }) => ({
|
|
32568
33093
|
...state,
|
|
32569
33094
|
related,
|
|
32570
|
-
})), on(
|
|
32571
|
-
...state,
|
|
32572
|
-
sources,
|
|
32573
|
-
})), on(setSourceOf, (state, { sourceOf }) => ({
|
|
33095
|
+
})), on(setLinkedRecords, (state, { linkedRecords }) => ({
|
|
32574
33096
|
...state,
|
|
32575
|
-
|
|
33097
|
+
linkedRecords,
|
|
32576
33098
|
})),
|
|
32577
33099
|
/*
|
|
32578
33100
|
ChartConfig reducers
|
|
@@ -32634,8 +33156,7 @@ const getMetadataError = createSelector(getMdViewState, (state) => state.error);
|
|
|
32634
33156
|
Related selectors
|
|
32635
33157
|
*/
|
|
32636
33158
|
const getRelated = createSelector(getMdViewState, (state) => state.related);
|
|
32637
|
-
const
|
|
32638
|
-
const getSourceOf = createSelector(getMdViewState, (state) => state.sourceOf);
|
|
33159
|
+
const getLinkedRecords = createSelector(getMdViewState, (state) => state.linkedRecords);
|
|
32639
33160
|
/*
|
|
32640
33161
|
Metadata selectors
|
|
32641
33162
|
*/
|
|
@@ -32736,212 +33257,10 @@ function parseHeaders(httpHeaders) {
|
|
|
32736
33257
|
return result;
|
|
32737
33258
|
}
|
|
32738
33259
|
|
|
32739
|
-
|
|
32740
|
-
|
|
32741
|
-
|
|
32742
|
-
? fileExtensionMatches[1].toLowerCase()
|
|
32743
|
-
: null;
|
|
32744
|
-
// 1. type hint
|
|
32745
|
-
if (typeHint)
|
|
32746
|
-
return Promise.resolve(typeHint);
|
|
32747
|
-
// 2. content-type header
|
|
32748
|
-
const headers = await fetchHeaders(url);
|
|
32749
|
-
if ('supportedType' in headers)
|
|
32750
|
-
return headers.supportedType;
|
|
32751
|
-
// 3. file extension from url
|
|
32752
|
-
else if (SupportedTypes.indexOf(fileExtension) > -1)
|
|
32753
|
-
return fileExtension;
|
|
32754
|
-
// no type inferred or hinted
|
|
32755
|
-
if ('mimeType' in headers)
|
|
32756
|
-
throw FetchError.unsupportedType(headers.mimeType);
|
|
32757
|
-
else
|
|
32758
|
-
throw FetchError.unknownType();
|
|
32759
|
-
}
|
|
32760
|
-
function fetchHeaders(url) {
|
|
32761
|
-
return sharedFetch(url, 'HEAD')
|
|
32762
|
-
.catch((error) => {
|
|
32763
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32764
|
-
})
|
|
32765
|
-
.then((response) => {
|
|
32766
|
-
if (!response.ok) {
|
|
32767
|
-
throw FetchError.http(response.status);
|
|
32768
|
-
}
|
|
32769
|
-
return parseHeaders(response.headers);
|
|
32770
|
-
});
|
|
33260
|
+
const GEOMETRY_COLUMN_ALIAS = '__geometry__';
|
|
33261
|
+
function fieldToSql(name) {
|
|
33262
|
+
return `"${name.replace(/"/g, '""')}"`; // escape double quotes in field names
|
|
32771
33263
|
}
|
|
32772
|
-
function fetchDataAsText(url, cacheActive) {
|
|
32773
|
-
const fetchFactory = () => sharedFetch(url)
|
|
32774
|
-
.catch((error) => {
|
|
32775
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32776
|
-
})
|
|
32777
|
-
.then(async (response) => {
|
|
32778
|
-
if (!response.ok) {
|
|
32779
|
-
const clonedResponse = response.clone();
|
|
32780
|
-
throw FetchError.http(response.status, await clonedResponse.text());
|
|
32781
|
-
}
|
|
32782
|
-
const clonedResponse = response.clone();
|
|
32783
|
-
return clonedResponse.text();
|
|
32784
|
-
});
|
|
32785
|
-
return cacheActive ? useCache(fetchFactory, url, 'asText') : fetchFactory();
|
|
32786
|
-
}
|
|
32787
|
-
function fetchDataAsArrayBuffer(url, cacheActive) {
|
|
32788
|
-
const fetchFactory = () => sharedFetch(url)
|
|
32789
|
-
.catch((error) => {
|
|
32790
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32791
|
-
})
|
|
32792
|
-
.then(async (response) => {
|
|
32793
|
-
if (!response.ok) {
|
|
32794
|
-
throw FetchError.http(response.status, await response.text());
|
|
32795
|
-
}
|
|
32796
|
-
// convert to a numeric array so that we can store the response in cache
|
|
32797
|
-
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
|
32798
|
-
});
|
|
32799
|
-
return (cacheActive ? useCache(fetchFactory, url, 'asArrayBuffer') : fetchFactory()).then((array) => {
|
|
32800
|
-
return new Uint8Array(array).buffer;
|
|
32801
|
-
});
|
|
32802
|
-
}
|
|
32803
|
-
function tryParseDate(input) {
|
|
32804
|
-
if (typeof input !== 'string')
|
|
32805
|
-
return null;
|
|
32806
|
-
function tryIso(value) {
|
|
32807
|
-
const parsed = parseISO(value);
|
|
32808
|
-
return isNaN(parsed.getDate()) ? null : parsed;
|
|
32809
|
-
}
|
|
32810
|
-
function tryFormat(value, format) {
|
|
32811
|
-
const parsed = parse$4(value, format, new Date());
|
|
32812
|
-
return isNaN(parsed.getDate()) ? null : parsed;
|
|
32813
|
-
}
|
|
32814
|
-
return (tryIso(input) ||
|
|
32815
|
-
tryFormat(input, 'dd/MM/yyyy') ||
|
|
32816
|
-
tryFormat(input, 'dd.MM.yyyy') ||
|
|
32817
|
-
tryFormat(input, 'MM/dd/yyyy') ||
|
|
32818
|
-
null);
|
|
32819
|
-
}
|
|
32820
|
-
function tryParseNumber(input) {
|
|
32821
|
-
if (isNaN(input))
|
|
32822
|
-
return null;
|
|
32823
|
-
const parsed = parseFloat(input);
|
|
32824
|
-
return isNaN(parsed) ? null : parsed;
|
|
32825
|
-
}
|
|
32826
|
-
function jsonToGeojsonFeature(object) {
|
|
32827
|
-
const { id, properties } = Object.keys(object)
|
|
32828
|
-
.map((property) => (property ? property : 'unknown')) //prevent empty strings
|
|
32829
|
-
.reduce((prev, curr) => curr.toLowerCase().endsWith('id')
|
|
32830
|
-
? {
|
|
32831
|
-
...prev,
|
|
32832
|
-
id: object[curr],
|
|
32833
|
-
}
|
|
32834
|
-
: {
|
|
32835
|
-
...prev,
|
|
32836
|
-
properties: { ...prev.properties, [curr]: object[curr] },
|
|
32837
|
-
}, { id: undefined, properties: {} });
|
|
32838
|
-
return {
|
|
32839
|
-
type: 'Feature',
|
|
32840
|
-
geometry: null,
|
|
32841
|
-
properties,
|
|
32842
|
-
...(id !== undefined && { id }),
|
|
32843
|
-
};
|
|
32844
|
-
}
|
|
32845
|
-
function mutateProperties(items, mutators) {
|
|
32846
|
-
const mutatorKeys = Object.keys(mutators);
|
|
32847
|
-
for (let i = 0, ii = items.length; i < ii; i++) {
|
|
32848
|
-
const item = items[i];
|
|
32849
|
-
for (const mutatorField of mutatorKeys) {
|
|
32850
|
-
if (!(mutatorField in item.properties))
|
|
32851
|
-
continue;
|
|
32852
|
-
item.properties[mutatorField] = mutators[mutatorField](item.properties[mutatorField]);
|
|
32853
|
-
}
|
|
32854
|
-
}
|
|
32855
|
-
return items;
|
|
32856
|
-
}
|
|
32857
|
-
const SAMPLE_SIZE = 20;
|
|
32858
|
-
/**
|
|
32859
|
-
* This will infer field types from a list of data items and cast the values accordingly
|
|
32860
|
-
* @param items
|
|
32861
|
-
* @param inferTypes
|
|
32862
|
-
*/
|
|
32863
|
-
function processItemProperties(items, inferTypes = false) {
|
|
32864
|
-
const foundFields = {};
|
|
32865
|
-
for (let i = 0, ii = Math.min(SAMPLE_SIZE, items.length); i < ii; i++) {
|
|
32866
|
-
const item = items[i];
|
|
32867
|
-
const fields = Object.keys(item.properties);
|
|
32868
|
-
for (const field of fields) {
|
|
32869
|
-
if (!(field in foundFields)) {
|
|
32870
|
-
foundFields[field] = {
|
|
32871
|
-
label: field,
|
|
32872
|
-
name: field,
|
|
32873
|
-
type: null,
|
|
32874
|
-
};
|
|
32875
|
-
}
|
|
32876
|
-
const value = item.properties[field];
|
|
32877
|
-
const info = foundFields[field];
|
|
32878
|
-
if (value === undefined || value === '' || value === null)
|
|
32879
|
-
continue;
|
|
32880
|
-
if (!inferTypes) {
|
|
32881
|
-
if (info.type === null && typeof value === 'number') {
|
|
32882
|
-
info.type = 'number';
|
|
32883
|
-
}
|
|
32884
|
-
else if (info.type === 'number' && typeof value !== 'number') {
|
|
32885
|
-
info.type = 'string';
|
|
32886
|
-
}
|
|
32887
|
-
continue;
|
|
32888
|
-
}
|
|
32889
|
-
const parsedNumber = tryParseNumber(value);
|
|
32890
|
-
if (info.type === null && parsedNumber !== null) {
|
|
32891
|
-
info.type = 'number';
|
|
32892
|
-
continue;
|
|
32893
|
-
}
|
|
32894
|
-
else if (info.type === 'number' && parsedNumber === null) {
|
|
32895
|
-
info.type = 'string';
|
|
32896
|
-
continue;
|
|
32897
|
-
}
|
|
32898
|
-
const parsedDate = tryParseDate(value);
|
|
32899
|
-
if (info.type === null && parsedDate !== null) {
|
|
32900
|
-
info.type = 'date';
|
|
32901
|
-
}
|
|
32902
|
-
else if (info.type === 'date' && parsedDate === null) {
|
|
32903
|
-
info.type = 'string';
|
|
32904
|
-
}
|
|
32905
|
-
}
|
|
32906
|
-
}
|
|
32907
|
-
const properties = [];
|
|
32908
|
-
const mutators = {};
|
|
32909
|
-
for (const field in foundFields) {
|
|
32910
|
-
const info = foundFields[field];
|
|
32911
|
-
if (info.type === 'number') {
|
|
32912
|
-
mutators[field] = tryParseNumber;
|
|
32913
|
-
}
|
|
32914
|
-
else if (info.type === 'date') {
|
|
32915
|
-
mutators[field] = tryParseDate;
|
|
32916
|
-
}
|
|
32917
|
-
properties.push({ ...info, type: info.type || 'string' });
|
|
32918
|
-
}
|
|
32919
|
-
if (inferTypes) {
|
|
32920
|
-
mutateProperties(items, mutators);
|
|
32921
|
-
}
|
|
32922
|
-
return { items, properties };
|
|
32923
|
-
}
|
|
32924
|
-
/**
|
|
32925
|
-
* This creates a Proxy that allows reading and writing to the data item properties
|
|
32926
|
-
* as if it was a simple array of JSON objects
|
|
32927
|
-
* @param items
|
|
32928
|
-
*/
|
|
32929
|
-
function getJsonDataItemsProxy(items) {
|
|
32930
|
-
return new Proxy(items, {
|
|
32931
|
-
get(target, p) {
|
|
32932
|
-
if (typeof p === 'string' &&
|
|
32933
|
-
!Number.isNaN(parseInt(p)) &&
|
|
32934
|
-
target[p]?.properties) {
|
|
32935
|
-
return target[p].properties;
|
|
32936
|
-
}
|
|
32937
|
-
return target[p];
|
|
32938
|
-
},
|
|
32939
|
-
set() {
|
|
32940
|
-
throw new Error('This object is read-only');
|
|
32941
|
-
},
|
|
32942
|
-
});
|
|
32943
|
-
}
|
|
32944
|
-
|
|
32945
33264
|
function filterToSql(filter) {
|
|
32946
33265
|
const operator = filter[0];
|
|
32947
33266
|
const args = filter.slice(1);
|
|
@@ -32956,10 +33275,10 @@ function filterToSql(filter) {
|
|
|
32956
33275
|
case '=':
|
|
32957
33276
|
case '!=':
|
|
32958
33277
|
case 'like':
|
|
32959
|
-
return
|
|
33278
|
+
return `${fieldToSql(args[0])} ${operator.toUpperCase()} ${valueToSql(args[1])}`;
|
|
32960
33279
|
case 'in': {
|
|
32961
33280
|
const values = args.slice(1);
|
|
32962
|
-
return
|
|
33281
|
+
return `${fieldToSql(args[0])} IN (${values.map(valueToSql).join(', ')})`;
|
|
32963
33282
|
}
|
|
32964
33283
|
case 'and':
|
|
32965
33284
|
case 'or': {
|
|
@@ -32978,17 +33297,18 @@ function aggregationToSql(aggregation) {
|
|
|
32978
33297
|
const field = aggregation[1];
|
|
32979
33298
|
switch (operation) {
|
|
32980
33299
|
case 'average':
|
|
32981
|
-
return `AVG(
|
|
33300
|
+
return `CAST(AVG(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`average(${field})`)}`;
|
|
32982
33301
|
case 'sum':
|
|
32983
33302
|
case 'max':
|
|
32984
33303
|
case 'min':
|
|
32985
|
-
return
|
|
33304
|
+
return `CAST(${operation.toUpperCase()}(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`${operation}(${field})`)}`;
|
|
32986
33305
|
case 'count':
|
|
32987
|
-
return 'COUNT(*) as
|
|
33306
|
+
return 'CAST(COUNT(*) AS INTEGER) as "count()"'; // we don't need Bigint precision here
|
|
32988
33307
|
}
|
|
32989
33308
|
}
|
|
32990
33309
|
/**
|
|
32991
33310
|
* Leave arguments at null if not used
|
|
33311
|
+
* @param tableName
|
|
32992
33312
|
* @param selected
|
|
32993
33313
|
* @param filter
|
|
32994
33314
|
* @param sort
|
|
@@ -32997,22 +33317,25 @@ function aggregationToSql(aggregation) {
|
|
|
32997
33317
|
* @param groupBy
|
|
32998
33318
|
* @param aggregations
|
|
32999
33319
|
*/
|
|
33000
|
-
function generateSqlQuery(selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null) {
|
|
33320
|
+
function generateSqlQuery(tableName, selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null, geometryColumn = null) {
|
|
33001
33321
|
let sqlSelect = 'SELECT *';
|
|
33002
|
-
const sqlFrom =
|
|
33322
|
+
const sqlFrom = ` FROM ${tableName}`;
|
|
33003
33323
|
let sqlOrderBy = '';
|
|
33004
33324
|
let sqlWhere = '';
|
|
33005
33325
|
let sqlLimit = '';
|
|
33006
33326
|
let sqlGroupBy = '';
|
|
33007
33327
|
if (selected !== null) {
|
|
33008
|
-
sqlSelect = `SELECT ${selected.map(
|
|
33328
|
+
sqlSelect = `SELECT ${selected.map(fieldToSql).join(', ')}`;
|
|
33329
|
+
}
|
|
33330
|
+
if (geometryColumn !== null) {
|
|
33331
|
+
sqlSelect += `, ST_AsGeoJSON(${fieldToSql(geometryColumn)}) as ${GEOMETRY_COLUMN_ALIAS}`;
|
|
33009
33332
|
}
|
|
33010
33333
|
if (filter !== null) {
|
|
33011
33334
|
sqlWhere = ` WHERE ${filterToSql(filter)}`;
|
|
33012
33335
|
}
|
|
33013
33336
|
if (sort?.length) {
|
|
33014
33337
|
sqlOrderBy = ` ORDER BY ${sort
|
|
33015
|
-
.map((sort) =>
|
|
33338
|
+
.map((sort) => `${fieldToSql(sort[1])} ${sort[0].toUpperCase()}`)
|
|
33016
33339
|
.join(', ')}`;
|
|
33017
33340
|
}
|
|
33018
33341
|
if (startIndex !== null && count !== null) {
|
|
@@ -33022,17 +33345,212 @@ function generateSqlQuery(selected = null, filter = null, sort = null, startInde
|
|
|
33022
33345
|
sqlSelect = `SELECT ${aggregations.map(aggregationToSql).join(', ')}`;
|
|
33023
33346
|
const groupedByDistinct = groupBy.filter((group) => group[0] === 'distinct');
|
|
33024
33347
|
const sqlGroupByFields = groupedByDistinct
|
|
33025
|
-
.map((group) =>
|
|
33348
|
+
.map((group) => fieldToSql(group[1]))
|
|
33026
33349
|
.join(', ');
|
|
33027
33350
|
const sqlGroupBySelect = groupedByDistinct
|
|
33028
|
-
.map((group) =>
|
|
33351
|
+
.map((group) => `${fieldToSql(group[1])} as ${fieldToSql(`distinct(${group[1]})`)}`)
|
|
33029
33352
|
.join(', ');
|
|
33030
33353
|
if (sqlGroupByFields && sqlGroupBySelect) {
|
|
33031
33354
|
sqlGroupBy = ` GROUP BY ${sqlGroupByFields}`;
|
|
33032
33355
|
sqlSelect += `, ${sqlGroupBySelect}`;
|
|
33033
33356
|
}
|
|
33034
33357
|
}
|
|
33035
|
-
return sqlSelect + sqlFrom + sqlGroupBy +
|
|
33358
|
+
return sqlSelect + sqlFrom + sqlGroupBy + sqlWhere + sqlOrderBy + sqlLimit;
|
|
33359
|
+
}
|
|
33360
|
+
|
|
33361
|
+
function arrowTableToDataItems(table) {
|
|
33362
|
+
const fields = table.schema.fields;
|
|
33363
|
+
return table.toArray().map((row) => {
|
|
33364
|
+
const rowJson = row.toJSON();
|
|
33365
|
+
const feature = {
|
|
33366
|
+
type: 'Feature',
|
|
33367
|
+
geometry: null,
|
|
33368
|
+
properties: {},
|
|
33369
|
+
};
|
|
33370
|
+
const keys = Object.keys(rowJson);
|
|
33371
|
+
for (let i = 0; i < keys.length; i++) {
|
|
33372
|
+
const key = keys[i];
|
|
33373
|
+
const dataType = fields[i].type;
|
|
33374
|
+
let value = rowJson[key];
|
|
33375
|
+
// this might happen if we get an array inside a field
|
|
33376
|
+
if (value instanceof Vector) {
|
|
33377
|
+
value = Array.from(value);
|
|
33378
|
+
}
|
|
33379
|
+
// cast bigints to ints
|
|
33380
|
+
if (typeof value === 'bigint') {
|
|
33381
|
+
value = Number(value);
|
|
33382
|
+
}
|
|
33383
|
+
// rename columns with empty name
|
|
33384
|
+
if (!key) {
|
|
33385
|
+
feature.properties['unknown'] = value;
|
|
33386
|
+
continue;
|
|
33387
|
+
}
|
|
33388
|
+
// assign properties that look like an id to the geojson `id` field
|
|
33389
|
+
if (/^(object|feature)?_?id$/.test(key.toLowerCase()) &&
|
|
33390
|
+
(typeof value == 'string' || typeof value === 'number')) {
|
|
33391
|
+
feature.id = value;
|
|
33392
|
+
}
|
|
33393
|
+
// if a date is in timestamp (number) format, convert it to native
|
|
33394
|
+
if (typeof value === 'number' &&
|
|
33395
|
+
(DataType.isTimestamp(dataType) || DataType.isDate(dataType))) {
|
|
33396
|
+
value = new Date(value);
|
|
33397
|
+
}
|
|
33398
|
+
// if a binary field (most likely a geometry column): skip
|
|
33399
|
+
if (DataType.isBinary(dataType)) {
|
|
33400
|
+
continue;
|
|
33401
|
+
}
|
|
33402
|
+
// geometry column
|
|
33403
|
+
if (key === GEOMETRY_COLUMN_ALIAS && DataType.isUtf8(dataType)) {
|
|
33404
|
+
feature.geometry = JSON.parse(value);
|
|
33405
|
+
continue;
|
|
33406
|
+
}
|
|
33407
|
+
feature.properties[key] = value;
|
|
33408
|
+
}
|
|
33409
|
+
return feature;
|
|
33410
|
+
});
|
|
33411
|
+
}
|
|
33412
|
+
|
|
33413
|
+
// init code taken from https://github.com/duckdb/duckdb-wasm/blob/main/packages/duckdb-wasm/README.md
|
|
33414
|
+
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
|
|
33415
|
+
// from https://duckdb.org/docs/current/sql/data_types/overview
|
|
33416
|
+
const typesMapping = {
|
|
33417
|
+
INTEGER: 'number',
|
|
33418
|
+
SMALLINT: 'number',
|
|
33419
|
+
TINYINT: 'number',
|
|
33420
|
+
BIGINT: 'number',
|
|
33421
|
+
HUGEINT: 'number',
|
|
33422
|
+
UINTEGER: 'number',
|
|
33423
|
+
USMALLINT: 'number',
|
|
33424
|
+
UTINYINT: 'number',
|
|
33425
|
+
UBIGINT: 'number',
|
|
33426
|
+
UHUGEINT: 'number',
|
|
33427
|
+
DOUBLE: 'number',
|
|
33428
|
+
BIGNUM: 'number',
|
|
33429
|
+
DECIMAL: 'number',
|
|
33430
|
+
NUMERIC: 'number',
|
|
33431
|
+
FLOAT: 'number',
|
|
33432
|
+
REAL: 'number',
|
|
33433
|
+
'TIMESTAMP WITH TIME ZONE': 'date',
|
|
33434
|
+
TIMESTAMP: 'date',
|
|
33435
|
+
DATE: 'date',
|
|
33436
|
+
CHAR: 'string',
|
|
33437
|
+
VARCHAR: 'string',
|
|
33438
|
+
TEXT: 'string',
|
|
33439
|
+
UUID: 'string',
|
|
33440
|
+
BLOB: 'string',
|
|
33441
|
+
BIT: 'string',
|
|
33442
|
+
INTERVAL: 'string',
|
|
33443
|
+
LIST: 'string',
|
|
33444
|
+
BOOLEAN: 'boolean',
|
|
33445
|
+
};
|
|
33446
|
+
class Engine {
|
|
33447
|
+
async makeInit() {
|
|
33448
|
+
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
|
|
33449
|
+
let worker_url = bundle.mainWorker;
|
|
33450
|
+
// this is necessary to let browsers execute WASM code coming from a cross-origin host
|
|
33451
|
+
if (worker_url.startsWith('https://')) {
|
|
33452
|
+
worker_url = URL.createObjectURL(new Blob([`importScripts("${worker_url}");`], {
|
|
33453
|
+
type: 'text/javascript',
|
|
33454
|
+
}));
|
|
33455
|
+
}
|
|
33456
|
+
const worker = new Worker(worker_url);
|
|
33457
|
+
const logger = new duckdb.ConsoleLogger(duckdb.LogLevel.WARNING);
|
|
33458
|
+
this.db = new duckdb.AsyncDuckDB(logger, worker);
|
|
33459
|
+
await this.db.instantiate(bundle.mainModule, bundle.pthreadWorker);
|
|
33460
|
+
// setup duckdb options
|
|
33461
|
+
const conn = await this.db.connect();
|
|
33462
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
33463
|
+
await conn.query(`INSTALL spatial; LOAD spatial;`);
|
|
33464
|
+
await conn.query(`SET TimeZone = '${timezone}';`);
|
|
33465
|
+
await conn.query(`SET threads = 1;`);
|
|
33466
|
+
// await conn.query(`SET memory_limit = '2GB';`) // used for experimenting when we encounter memory issues
|
|
33467
|
+
await conn.query(`SET preserve_insertion_order = false;`); // this reduces memory usage when loading a dataset
|
|
33468
|
+
conn.close();
|
|
33469
|
+
return this;
|
|
33470
|
+
}
|
|
33471
|
+
isReady() {
|
|
33472
|
+
if (!this.init_) {
|
|
33473
|
+
this.init_ = this.makeInit();
|
|
33474
|
+
}
|
|
33475
|
+
return this.init_;
|
|
33476
|
+
}
|
|
33477
|
+
/**
|
|
33478
|
+
* Returns information about a dataset once it's loaded:
|
|
33479
|
+
* - a list of properties description
|
|
33480
|
+
* - the name of the dataset geometry column (null if no geometry present)
|
|
33481
|
+
* @param datasetId name of the table under which the dataset will be stored
|
|
33482
|
+
* @param loadQuery duckdb-specific query for creating a table out of the data
|
|
33483
|
+
* @param forceReload if true, any existing data will be dropped and redownloaded
|
|
33484
|
+
*/
|
|
33485
|
+
async loadFile(datasetId, loadQuery, forceReload = false) {
|
|
33486
|
+
const conn = await this.db.connect();
|
|
33487
|
+
let results;
|
|
33488
|
+
// either we want to recreate the table, or we keep it if it already exists
|
|
33489
|
+
const safeLoadQuery = forceReload
|
|
33490
|
+
? `DROP TABLE IF EXISTS ${datasetId};
|
|
33491
|
+
${loadQuery}`
|
|
33492
|
+
: loadQuery.replace(/CREATE TABLE(?! IF NOT EXISTS)/gi, 'CREATE TABLE IF NOT EXISTS');
|
|
33493
|
+
// create the table
|
|
33494
|
+
try {
|
|
33495
|
+
results = await conn.query(safeLoadQuery);
|
|
33496
|
+
}
|
|
33497
|
+
catch (e) {
|
|
33498
|
+
throw new FetchError('parse', `DuckDB encountered an error when loading the data: ${e.message}`);
|
|
33499
|
+
}
|
|
33500
|
+
// read rows count
|
|
33501
|
+
results = await conn.query(`SELECT count(*) FROM ${datasetId}`);
|
|
33502
|
+
const { 'count_star()': recordsCount } = results.toArray()[0].toJSON();
|
|
33503
|
+
// read columns
|
|
33504
|
+
results = await conn.query(`SELECT * FROM information_schema.columns WHERE table_name = '${datasetId}';`);
|
|
33505
|
+
let geometryColumn = null;
|
|
33506
|
+
const properties = results
|
|
33507
|
+
.toArray()
|
|
33508
|
+
.map((row) => {
|
|
33509
|
+
const rowObj = row.toJSON();
|
|
33510
|
+
if (rowObj['data_type'] === 'GEOMETRY') {
|
|
33511
|
+
// the geometry is not part of the properties
|
|
33512
|
+
// note: right now we only keep one geometry column name, but if there are multiple they will
|
|
33513
|
+
// all get discarded
|
|
33514
|
+
geometryColumn = rowObj['column_name'];
|
|
33515
|
+
return null;
|
|
33516
|
+
}
|
|
33517
|
+
return {
|
|
33518
|
+
name: rowObj['column_name'],
|
|
33519
|
+
label: rowObj['column_name'],
|
|
33520
|
+
type: typesMapping[rowObj['data_type']] ?? 'other',
|
|
33521
|
+
};
|
|
33522
|
+
})
|
|
33523
|
+
.filter((prop) => prop !== null);
|
|
33524
|
+
conn.close();
|
|
33525
|
+
return {
|
|
33526
|
+
properties,
|
|
33527
|
+
geometryColumn,
|
|
33528
|
+
rowsCount: Number(recordsCount),
|
|
33529
|
+
};
|
|
33530
|
+
}
|
|
33531
|
+
// register a Uint8 buffer using a handle in the duckdb instance
|
|
33532
|
+
async registerData(name, buffer) {
|
|
33533
|
+
return this.db.registerFileBuffer(name, buffer);
|
|
33534
|
+
}
|
|
33535
|
+
/**
|
|
33536
|
+
* @param query duckdb-specific query for fetching items
|
|
33537
|
+
*/
|
|
33538
|
+
async queryItems(query) {
|
|
33539
|
+
const conn = await this.db.connect();
|
|
33540
|
+
const results = await conn.query(query);
|
|
33541
|
+
conn.close();
|
|
33542
|
+
return arrowTableToDataItems(results);
|
|
33543
|
+
}
|
|
33544
|
+
close() {
|
|
33545
|
+
this.db?.terminate();
|
|
33546
|
+
}
|
|
33547
|
+
}
|
|
33548
|
+
let engine = null;
|
|
33549
|
+
async function getEngine() {
|
|
33550
|
+
if (!engine) {
|
|
33551
|
+
engine = new Engine();
|
|
33552
|
+
}
|
|
33553
|
+
return engine.isReady();
|
|
33036
33554
|
}
|
|
33037
33555
|
|
|
33038
33556
|
class BaseReader {
|
|
@@ -33045,10 +33563,18 @@ class BaseReader {
|
|
|
33045
33563
|
this.sort = null;
|
|
33046
33564
|
this.startIndex = null;
|
|
33047
33565
|
this.count = null;
|
|
33566
|
+
this.loadPromise_ = Promise.resolve();
|
|
33567
|
+
this.cacheEnabled = false;
|
|
33568
|
+
}
|
|
33569
|
+
enableCache(enabled) {
|
|
33570
|
+
this.cacheEnabled = enabled;
|
|
33048
33571
|
}
|
|
33049
33572
|
load() {
|
|
33050
33573
|
throw new Error('not implemented');
|
|
33051
33574
|
}
|
|
33575
|
+
get isLoaded() {
|
|
33576
|
+
return this.loadPromise_;
|
|
33577
|
+
}
|
|
33052
33578
|
get properties() {
|
|
33053
33579
|
throw new Error('not implemented');
|
|
33054
33580
|
}
|
|
@@ -33097,178 +33623,237 @@ class BaseReader {
|
|
|
33097
33623
|
}
|
|
33098
33624
|
}
|
|
33099
33625
|
|
|
33100
|
-
|
|
33101
|
-
|
|
33102
|
-
|
|
33103
|
-
|
|
33104
|
-
|
|
33105
|
-
|
|
33106
|
-
|
|
33107
|
-
|
|
33108
|
-
|
|
33109
|
-
|
|
33110
|
-
|
|
33111
|
-
|
|
33112
|
-
|
|
33626
|
+
/**
|
|
33627
|
+
* This reader handles file formats supported natively by DuckDB
|
|
33628
|
+
*/
|
|
33629
|
+
class BaseFileReader extends BaseReader {
|
|
33630
|
+
// a table id should not exceed 63 chars
|
|
33631
|
+
generateDatasetId() {
|
|
33632
|
+
// generate a hash out of the url
|
|
33633
|
+
let hash = 0;
|
|
33634
|
+
for (const char of this.url) {
|
|
33635
|
+
hash = (hash << 5) - hash + char.charCodeAt(0);
|
|
33636
|
+
hash = hash >>> 0; // make it unsigned
|
|
33637
|
+
}
|
|
33638
|
+
return `datafetcher_${hash.toString(16)}`;
|
|
33639
|
+
}
|
|
33640
|
+
async getLoadQuery() {
|
|
33113
33641
|
throw new Error('not implemented');
|
|
33114
33642
|
}
|
|
33115
|
-
load() {
|
|
33116
|
-
this.
|
|
33643
|
+
async load() {
|
|
33644
|
+
this.datasetId = this.generateDatasetId();
|
|
33645
|
+
this.loadPromise_ = getEngine()
|
|
33646
|
+
.then((engine) => {
|
|
33647
|
+
this.engine = engine;
|
|
33648
|
+
return this.getLoadQuery();
|
|
33649
|
+
})
|
|
33650
|
+
.then((loadQuery) => this.engine.loadFile(this.datasetId, loadQuery, !this.cacheEnabled))
|
|
33651
|
+
.then((datasetInfo) => {
|
|
33652
|
+
this.properties_ = datasetInfo.properties;
|
|
33653
|
+
this.geometryColumn = datasetInfo.geometryColumn;
|
|
33654
|
+
this.rowsCount = datasetInfo.rowsCount;
|
|
33655
|
+
// returns void for the loaded promise
|
|
33656
|
+
});
|
|
33117
33657
|
}
|
|
33118
33658
|
get properties() {
|
|
33119
|
-
return this.
|
|
33659
|
+
return this.isLoaded.then(() => this.properties_);
|
|
33120
33660
|
}
|
|
33121
33661
|
get info() {
|
|
33122
|
-
return this.
|
|
33123
|
-
itemsCount:
|
|
33662
|
+
return this.isLoaded.then(() => ({
|
|
33663
|
+
itemsCount: this.rowsCount,
|
|
33664
|
+
hasGeometry: !!this.geometryColumn,
|
|
33124
33665
|
}));
|
|
33125
33666
|
}
|
|
33126
33667
|
async read() {
|
|
33127
|
-
|
|
33128
|
-
//
|
|
33129
|
-
|
|
33130
|
-
|
|
33131
|
-
|
|
33132
|
-
this.sort == null &&
|
|
33133
|
-
this.filter == null &&
|
|
33134
|
-
this.startIndex == null &&
|
|
33135
|
-
this.count == null) {
|
|
33136
|
-
return items;
|
|
33137
|
-
}
|
|
33138
|
-
const jsonItems = getJsonDataItemsProxy(items);
|
|
33139
|
-
const query = generateSqlQuery(this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations);
|
|
33140
|
-
const result = await import('alasql').then((module) => module.default(query, [jsonItems]));
|
|
33141
|
-
return result.map(jsonToGeojsonFeature);
|
|
33142
|
-
}
|
|
33143
|
-
}
|
|
33144
|
-
|
|
33145
|
-
function parseCsv(text) {
|
|
33146
|
-
// first parse the header to guess the delimiter
|
|
33147
|
-
// note that we do that to not rely on Papaparse logic for guessing delimiter
|
|
33148
|
-
let delimiter;
|
|
33149
|
-
try {
|
|
33150
|
-
const header = text.split('\n')[0];
|
|
33151
|
-
const result = Papa.parse(header, {
|
|
33152
|
-
header: false,
|
|
33153
|
-
});
|
|
33154
|
-
delimiter = result.meta.delimiter;
|
|
33155
|
-
}
|
|
33156
|
-
catch (e) {
|
|
33157
|
-
throw new Error('CSV parsing failed: the delimiter could not be guessed');
|
|
33158
|
-
}
|
|
33159
|
-
const parsed = Papa.parse(text, {
|
|
33160
|
-
header: true,
|
|
33161
|
-
skipEmptyLines: true,
|
|
33162
|
-
delimiter,
|
|
33163
|
-
});
|
|
33164
|
-
if (parsed.errors.length) {
|
|
33165
|
-
throw new Error('CSV parsing failed for the following reasons:\n' +
|
|
33166
|
-
parsed.errors
|
|
33167
|
-
.map((error) => `* ${error.message} at row ${error.row}, column ${error.index}`)
|
|
33168
|
-
.join('\n'));
|
|
33668
|
+
await this.isLoaded;
|
|
33669
|
+
// if only certain fields are selected, omit the geometry
|
|
33670
|
+
const geometryColumn = this.selected === null ? this.geometryColumn : null;
|
|
33671
|
+
const query = generateSqlQuery(this.datasetId, this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations, geometryColumn);
|
|
33672
|
+
return this.engine.queryItems(query);
|
|
33169
33673
|
}
|
|
33170
|
-
const items = parsed.data.map(jsonToGeojsonFeature);
|
|
33171
|
-
return processItemProperties(items, true);
|
|
33172
33674
|
}
|
|
33675
|
+
|
|
33173
33676
|
class CsvReader extends BaseFileReader {
|
|
33174
|
-
|
|
33175
|
-
|
|
33677
|
+
async getLoadQuery() {
|
|
33678
|
+
// first we get a list of columns hich have a detected type of VARCHAR
|
|
33679
|
+
// then we make sure that for those columns, we don't cast an empty string to null; instead we want to keep the empty string
|
|
33680
|
+
return `
|
|
33681
|
+
SET VARIABLE strColumns = (SELECT list(name) FROM (SELECT unnest(Columns, recursive := true) FROM sniff_csv("${this.url}")) WHERE type = 'VARCHAR');
|
|
33682
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_csv("${this.url}",
|
|
33683
|
+
force_not_null = getvariable('strColumns'),
|
|
33684
|
+
auto_type_candidates = ['NULL', 'BOOLEAN', 'INTEGER', 'DOUBLE', 'DATE', 'VARCHAR']
|
|
33685
|
+
);`;
|
|
33176
33686
|
}
|
|
33177
33687
|
}
|
|
33178
33688
|
|
|
33179
|
-
/**
|
|
33180
|
-
* This parser only supports arrays of simple flat objects with properties
|
|
33181
|
-
* @param text
|
|
33182
|
-
*/
|
|
33183
|
-
function parseJson(text) {
|
|
33184
|
-
const parsed = JSON.parse(text);
|
|
33185
|
-
if (!Array.isArray(parsed)) {
|
|
33186
|
-
throw new Error('Could not parse JSON, expected an array at root level');
|
|
33187
|
-
}
|
|
33188
|
-
return processItemProperties(parsed.map(jsonToGeojsonFeature));
|
|
33189
|
-
}
|
|
33190
33689
|
class JsonReader extends BaseFileReader {
|
|
33191
|
-
|
|
33192
|
-
return
|
|
33690
|
+
async getLoadQuery() {
|
|
33691
|
+
return `
|
|
33692
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_json("${this.url}",
|
|
33693
|
+
maximum_object_size = 536870912 -- 500MB
|
|
33694
|
+
);`;
|
|
33193
33695
|
}
|
|
33194
33696
|
}
|
|
33195
33697
|
|
|
33196
|
-
/**
|
|
33197
|
-
* This parser supports both Geojson Feature collections or arrays
|
|
33198
|
-
* of Features
|
|
33199
|
-
* @param text
|
|
33200
|
-
*/
|
|
33201
|
-
function parseGeojson(text) {
|
|
33202
|
-
const parsed = JSON.parse(text);
|
|
33203
|
-
const features = parsed.type === 'FeatureCollection' ? parsed.features : parsed;
|
|
33204
|
-
if (!Array.isArray(features)) {
|
|
33205
|
-
throw new Error('Could not parse GeoJSON, expected a features collection or an array of features at root level');
|
|
33206
|
-
}
|
|
33207
|
-
return processItemProperties(features);
|
|
33208
|
-
}
|
|
33209
33698
|
class GeojsonReader extends BaseFileReader {
|
|
33210
|
-
|
|
33211
|
-
return
|
|
33699
|
+
async getLoadQuery() {
|
|
33700
|
+
return `
|
|
33701
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33702
|
+
allowed_drivers = ['GeoJSON']
|
|
33703
|
+
);`;
|
|
33212
33704
|
}
|
|
33213
33705
|
}
|
|
33214
33706
|
|
|
33707
|
+
async function inferDatasetType(url, typeHint) {
|
|
33708
|
+
const fileExtensionMatches = new URL(url, typeof window !== 'undefined' ? window.location.toString() : undefined).pathname.match(/\.(.+)$/);
|
|
33709
|
+
const fileExtension = fileExtensionMatches && fileExtensionMatches.length
|
|
33710
|
+
? fileExtensionMatches[1].toLowerCase()
|
|
33711
|
+
: null;
|
|
33712
|
+
// 1. type hint
|
|
33713
|
+
if (typeHint)
|
|
33714
|
+
return Promise.resolve(typeHint);
|
|
33715
|
+
// 2. content-type header
|
|
33716
|
+
const headers = await fetchHeaders(url);
|
|
33717
|
+
if ('supportedType' in headers)
|
|
33718
|
+
return headers.supportedType;
|
|
33719
|
+
// 3. file extension from url
|
|
33720
|
+
else if (SupportedTypes.indexOf(fileExtension) > -1)
|
|
33721
|
+
return fileExtension;
|
|
33722
|
+
// no type inferred or hinted
|
|
33723
|
+
if ('mimeType' in headers)
|
|
33724
|
+
throw FetchError.unsupportedType(headers.mimeType);
|
|
33725
|
+
else
|
|
33726
|
+
throw FetchError.unknownType();
|
|
33727
|
+
}
|
|
33728
|
+
function fetchHeaders(url) {
|
|
33729
|
+
return sharedFetch(url, 'HEAD')
|
|
33730
|
+
.catch((error) => {
|
|
33731
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33732
|
+
})
|
|
33733
|
+
.then((response) => {
|
|
33734
|
+
if (!response.ok) {
|
|
33735
|
+
throw FetchError.http(response.status);
|
|
33736
|
+
}
|
|
33737
|
+
return parseHeaders(response.headers);
|
|
33738
|
+
});
|
|
33739
|
+
}
|
|
33740
|
+
function fetchDataAsText(url, cacheActive) {
|
|
33741
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33742
|
+
.catch((error) => {
|
|
33743
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33744
|
+
})
|
|
33745
|
+
.then(async (response) => {
|
|
33746
|
+
if (!response.ok) {
|
|
33747
|
+
const clonedResponse = response.clone();
|
|
33748
|
+
throw FetchError.http(response.status, await clonedResponse.text());
|
|
33749
|
+
}
|
|
33750
|
+
const clonedResponse = response.clone();
|
|
33751
|
+
return clonedResponse.text();
|
|
33752
|
+
});
|
|
33753
|
+
return cacheActive ? useCache(fetchFactory, url, 'asText') : fetchFactory();
|
|
33754
|
+
}
|
|
33755
|
+
function fetchDataAsArrayBuffer(url, cacheActive) {
|
|
33756
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33757
|
+
.catch((error) => {
|
|
33758
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33759
|
+
})
|
|
33760
|
+
.then(async (response) => {
|
|
33761
|
+
if (!response.ok) {
|
|
33762
|
+
throw FetchError.http(response.status, await response.text());
|
|
33763
|
+
}
|
|
33764
|
+
// convert to a numeric array so that we can store the response in cache
|
|
33765
|
+
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
|
33766
|
+
});
|
|
33767
|
+
return (cacheActive ? useCache(fetchFactory, url, 'asArrayBuffer') : fetchFactory()).then((array) => {
|
|
33768
|
+
return new Uint8Array(array).buffer;
|
|
33769
|
+
});
|
|
33770
|
+
}
|
|
33215
33771
|
/**
|
|
33216
|
-
* This
|
|
33217
|
-
*
|
|
33218
|
-
* @param
|
|
33772
|
+
* This creates a Proxy that allows reading and writing to the data item properties
|
|
33773
|
+
* as if it was a simple array of JSON objects
|
|
33774
|
+
* @param items
|
|
33219
33775
|
*/
|
|
33220
|
-
function
|
|
33221
|
-
return
|
|
33222
|
-
|
|
33223
|
-
|
|
33224
|
-
|
|
33225
|
-
|
|
33226
|
-
|
|
33227
|
-
|
|
33228
|
-
|
|
33776
|
+
function getJsonDataItemsProxy(items) {
|
|
33777
|
+
return new Proxy(items, {
|
|
33778
|
+
get(target, p) {
|
|
33779
|
+
if (typeof p === 'string' &&
|
|
33780
|
+
!Number.isNaN(parseInt(p)) &&
|
|
33781
|
+
target[p]?.properties) {
|
|
33782
|
+
return target[p].properties;
|
|
33783
|
+
}
|
|
33784
|
+
return target[p];
|
|
33785
|
+
},
|
|
33786
|
+
set() {
|
|
33787
|
+
throw new Error('This object is read-only');
|
|
33788
|
+
},
|
|
33229
33789
|
});
|
|
33230
33790
|
}
|
|
33791
|
+
|
|
33231
33792
|
class ExcelReader extends BaseFileReader {
|
|
33232
|
-
|
|
33233
|
-
|
|
33793
|
+
async getLoadQuery() {
|
|
33794
|
+
// we download the file as an array buffer first, in order to be able to check if it's an XLS file
|
|
33795
|
+
let buffer = await fetchDataAsArrayBuffer(this.url, this.cacheEnabled);
|
|
33796
|
+
const bufferHandle = `B${this.datasetId}`;
|
|
33797
|
+
// checking against the magic number at the beginning of XLS files, see https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
33798
|
+
const magicNumber = new Uint8Array(buffer, 0, 8); // first 8 bytes
|
|
33799
|
+
const isXls = Array.from(magicNumber)
|
|
33800
|
+
.map((n) => n.toString(16).toUpperCase())
|
|
33801
|
+
.join(' ') === 'D0 CF 11 E0 A1 B1 1A E1';
|
|
33802
|
+
// uh oh, this is an XLS file (not supported by duckdb); convert it to CSV using the xlsx package
|
|
33803
|
+
if (isXls) {
|
|
33804
|
+
buffer = await import('xlsx').then(({ read, utils }) => {
|
|
33805
|
+
const workbook = read(buffer);
|
|
33806
|
+
const json = utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
|
|
33807
|
+
return new TextEncoder().encode(JSON.stringify(json)).buffer;
|
|
33808
|
+
});
|
|
33809
|
+
}
|
|
33810
|
+
const duckDbFn = isXls ? 'read_json' : 'read_xlsx';
|
|
33811
|
+
await this.engine.registerData(bufferHandle, new Uint8Array(buffer));
|
|
33812
|
+
return `
|
|
33813
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM ${duckDbFn}("${bufferHandle}", ignore_errors = true);`;
|
|
33234
33814
|
}
|
|
33235
33815
|
}
|
|
33236
33816
|
|
|
33237
|
-
|
|
33238
|
-
|
|
33239
|
-
|
|
33817
|
+
class GmlReader extends BaseFileReader {
|
|
33818
|
+
async getLoadQuery() {
|
|
33819
|
+
return `
|
|
33820
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33821
|
+
allowed_drivers = ['GML']
|
|
33822
|
+
);`;
|
|
33823
|
+
}
|
|
33824
|
+
}
|
|
33825
|
+
|
|
33826
|
+
const formatGeojson = new GeoJSON$1();
|
|
33827
|
+
function parseGeojson(text) {
|
|
33828
|
+
const parsed = JSON.parse(text);
|
|
33829
|
+
const features = parsed.type === 'FeatureCollection' ? parsed.features : parsed;
|
|
33830
|
+
if (!Array.isArray(features)) {
|
|
33831
|
+
throw new Error('Could not parse GeoJSON, expected a features collection or an array of features at root level');
|
|
33832
|
+
}
|
|
33833
|
+
return features;
|
|
33834
|
+
}
|
|
33835
|
+
function parseGml(text, featureType, version) {
|
|
33836
|
+
const parts = featureType.split(':');
|
|
33837
|
+
const regex = new RegExp(`xmlns:${parts[0]}=["']([^'"]*)["']`);
|
|
33240
33838
|
const match = regex.exec(text);
|
|
33241
33839
|
if (match && match.length >= 2) {
|
|
33242
|
-
const
|
|
33840
|
+
const wfs = new WFS({
|
|
33243
33841
|
featureNS: match[1],
|
|
33244
|
-
featureType:
|
|
33842
|
+
featureType: parts[1],
|
|
33245
33843
|
version: version,
|
|
33246
33844
|
});
|
|
33247
33845
|
let features;
|
|
33248
33846
|
try {
|
|
33249
|
-
features =
|
|
33847
|
+
features = wfs.readFeatures(text);
|
|
33250
33848
|
}
|
|
33251
33849
|
catch (e) {
|
|
33252
|
-
throw Error(
|
|
33850
|
+
throw Error(`Couldn't parse WFS with GML features: ${e.message}`);
|
|
33253
33851
|
}
|
|
33254
|
-
const geojsonItem =
|
|
33255
|
-
return
|
|
33852
|
+
const geojsonItem = formatGeojson.writeFeaturesObject(features);
|
|
33853
|
+
return geojsonItem.features;
|
|
33256
33854
|
}
|
|
33257
33855
|
throw Error("Couldn't retrieve namespace url");
|
|
33258
33856
|
}
|
|
33259
|
-
class GmlReader extends BaseFileReader {
|
|
33260
|
-
constructor(url, namespace, version, cacheActive = true) {
|
|
33261
|
-
super(url);
|
|
33262
|
-
this.url = url;
|
|
33263
|
-
this.namespace = namespace;
|
|
33264
|
-
this.version = version;
|
|
33265
|
-
this.cacheActive = cacheActive;
|
|
33266
|
-
}
|
|
33267
|
-
getData() {
|
|
33268
|
-
return fetchDataAsText(this.url, this.cacheActive).then((text) => parseGml(text, this.namespace, this.version));
|
|
33269
|
-
}
|
|
33270
|
-
}
|
|
33271
|
-
|
|
33272
33857
|
async function getWfsEndpoint(wfsUrl) {
|
|
33273
33858
|
try {
|
|
33274
33859
|
return await new WfsEndpoint(wfsUrl).isReady();
|
|
@@ -33296,21 +33881,65 @@ async function getWfsEndpoint(wfsUrl) {
|
|
|
33296
33881
|
}
|
|
33297
33882
|
}
|
|
33298
33883
|
}
|
|
33299
|
-
class WfsReader extends
|
|
33300
|
-
constructor(url,
|
|
33301
|
-
super(url
|
|
33302
|
-
this.endpoint =
|
|
33303
|
-
this.
|
|
33304
|
-
|
|
33884
|
+
class WfsReader extends BaseReader {
|
|
33885
|
+
constructor(url, featureTypeName) {
|
|
33886
|
+
super(url);
|
|
33887
|
+
this.endpoint = getWfsEndpoint(url);
|
|
33888
|
+
this.featureType = this.endpoint
|
|
33889
|
+
.then((endpoint) => {
|
|
33890
|
+
const featureTypes = endpoint.getFeatureTypes();
|
|
33891
|
+
return endpoint.getFeatureTypeFull(featureTypes.length === 1 && !featureTypeName
|
|
33892
|
+
? featureTypes[0].name
|
|
33893
|
+
: featureTypeName);
|
|
33894
|
+
})
|
|
33895
|
+
.then((featureType) => {
|
|
33896
|
+
if (!featureType) {
|
|
33897
|
+
throw new Error('wfs.featuretype.notfound');
|
|
33898
|
+
}
|
|
33899
|
+
return featureType;
|
|
33900
|
+
});
|
|
33901
|
+
}
|
|
33902
|
+
get backupReader() {
|
|
33903
|
+
if (this.backupReader_) {
|
|
33904
|
+
return this.backupReader_;
|
|
33905
|
+
}
|
|
33906
|
+
this.backupReader_ = Promise.all([this.endpoint, this.featureType]).then(([endpoint, featureType]) => {
|
|
33907
|
+
let reader;
|
|
33908
|
+
if (endpoint.supportsJson(featureType.name)) {
|
|
33909
|
+
reader = new GeojsonReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33910
|
+
asJson: true,
|
|
33911
|
+
outputCrs: 'EPSG:4326',
|
|
33912
|
+
}));
|
|
33913
|
+
}
|
|
33914
|
+
else {
|
|
33915
|
+
if (featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')) &&
|
|
33916
|
+
(featureType.defaultCrs === 'EPSG:4326' ||
|
|
33917
|
+
featureType.otherCrs?.includes('EPSG:4326'))) {
|
|
33918
|
+
reader = new GmlReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33919
|
+
outputFormat: featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')),
|
|
33920
|
+
outputCrs: 'EPSG:4326',
|
|
33921
|
+
}));
|
|
33922
|
+
}
|
|
33923
|
+
}
|
|
33924
|
+
reader.enableCache(this.cacheEnabled);
|
|
33925
|
+
reader.load();
|
|
33926
|
+
return reader;
|
|
33927
|
+
});
|
|
33928
|
+
return this.backupReader_;
|
|
33305
33929
|
}
|
|
33306
33930
|
get properties() {
|
|
33307
|
-
return this.
|
|
33308
|
-
.getFeatureTypeFull(this.featureTypeName)
|
|
33309
|
-
.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33931
|
+
return this.featureType.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33310
33932
|
const originalType = featureType.properties[prop];
|
|
33311
|
-
|
|
33312
|
-
|
|
33313
|
-
|
|
33933
|
+
let type;
|
|
33934
|
+
if (originalType === 'float' || originalType === 'integer') {
|
|
33935
|
+
type = 'number';
|
|
33936
|
+
}
|
|
33937
|
+
else if (originalType === 'boolean') {
|
|
33938
|
+
type = 'string'; // we don't handle booleans yet in the data fetcher
|
|
33939
|
+
}
|
|
33940
|
+
else {
|
|
33941
|
+
type = originalType;
|
|
33942
|
+
}
|
|
33314
33943
|
return {
|
|
33315
33944
|
name: prop,
|
|
33316
33945
|
label: prop,
|
|
@@ -33319,83 +33948,63 @@ class WfsReader extends BaseCacheReader {
|
|
|
33319
33948
|
}));
|
|
33320
33949
|
}
|
|
33321
33950
|
get info() {
|
|
33322
|
-
return this.
|
|
33951
|
+
return this.featureType.then((result) => ({
|
|
33323
33952
|
itemsCount: result.objectCount,
|
|
33953
|
+
hasGeometry: !!result.geometryName,
|
|
33324
33954
|
}));
|
|
33325
33955
|
}
|
|
33326
|
-
|
|
33327
|
-
|
|
33328
|
-
const featureTypes = wfsEndpoint.getFeatureTypes();
|
|
33329
|
-
const featureType = wfsEndpoint.getFeatureTypeSummary(featureTypes.length === 1 && !featureTypeName
|
|
33330
|
-
? featureTypes[0].name
|
|
33331
|
-
: featureTypeName);
|
|
33332
|
-
if (!featureType) {
|
|
33333
|
-
throw new Error('wfs.featuretype.notfound');
|
|
33334
|
-
}
|
|
33335
|
-
if (wfsEndpoint.supportsStartIndex()) {
|
|
33336
|
-
return new WfsReader(wfsUrlEndpoint, wfsEndpoint, featureType.name);
|
|
33337
|
-
}
|
|
33338
|
-
else if (wfsEndpoint.supportsJson(featureType.name)) {
|
|
33339
|
-
return new GeojsonReader(wfsEndpoint.getFeatureUrl(featureType.name, {
|
|
33340
|
-
asJson: true,
|
|
33341
|
-
outputCrs: 'EPSG:4326',
|
|
33342
|
-
}));
|
|
33343
|
-
}
|
|
33344
|
-
else {
|
|
33345
|
-
if (featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')) &&
|
|
33346
|
-
(featureType.defaultCrs === 'EPSG:4326' ||
|
|
33347
|
-
featureType.otherCrs?.includes('EPSG:4326'))) {
|
|
33348
|
-
return new GmlReader(wfsEndpoint.getFeatureUrl(featureType.name, {
|
|
33349
|
-
outputFormat: featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')),
|
|
33350
|
-
outputCrs: 'EPSG:4326',
|
|
33351
|
-
}), featureType.name, wfsEndpoint.getVersion());
|
|
33352
|
-
}
|
|
33353
|
-
throw new Error('wfs.geojsongml.notsupported');
|
|
33354
|
-
}
|
|
33956
|
+
load() {
|
|
33957
|
+
// Nothing to load for Wfs
|
|
33355
33958
|
}
|
|
33356
|
-
async
|
|
33357
|
-
|
|
33358
|
-
|
|
33959
|
+
async read() {
|
|
33960
|
+
const endpoint = await this.endpoint;
|
|
33961
|
+
const featureType = await this.featureType;
|
|
33962
|
+
// if we can't use the WFS protocol we fall back to the backup reader
|
|
33963
|
+
if (this.aggregations || this.groupedBy || !endpoint.supportsStartIndex()) {
|
|
33964
|
+
const backupReader = await this.backupReader;
|
|
33965
|
+
backupReader.selectAll();
|
|
33966
|
+
if (this.selected) {
|
|
33967
|
+
backupReader.select(...this.selected);
|
|
33968
|
+
}
|
|
33969
|
+
if (this.aggregations) {
|
|
33970
|
+
backupReader.aggregate(...this.aggregations);
|
|
33971
|
+
}
|
|
33972
|
+
if (this.groupedBy) {
|
|
33973
|
+
backupReader.groupBy(...this.groupedBy);
|
|
33974
|
+
}
|
|
33975
|
+
if (this.sort) {
|
|
33976
|
+
backupReader.orderBy(...this.sort);
|
|
33977
|
+
}
|
|
33978
|
+
if (this.startIndex !== null && this.count !== null) {
|
|
33979
|
+
backupReader.limit(this.startIndex, this.count);
|
|
33980
|
+
}
|
|
33981
|
+
return backupReader.read();
|
|
33359
33982
|
}
|
|
33360
|
-
const asJson =
|
|
33983
|
+
const asJson = endpoint.supportsJson(featureType.name);
|
|
33361
33984
|
const attributes = this.selected ?? undefined;
|
|
33362
|
-
let
|
|
33985
|
+
let sortBy = null;
|
|
33986
|
+
if (this.sort) {
|
|
33987
|
+
const mapSort = (s) => [s[0] === 'desc' ? 'D' : 'A', s[1]];
|
|
33988
|
+
sortBy = Array.isArray(this.sort[0])
|
|
33989
|
+
? this.sort.map(mapSort)
|
|
33990
|
+
: mapSort(this.sort);
|
|
33991
|
+
}
|
|
33992
|
+
const url = endpoint.getFeatureUrl(featureType.name, {
|
|
33363
33993
|
...(this.startIndex !== null && { startIndex: this.startIndex }),
|
|
33364
33994
|
...(this.count !== null && { maxFeatures: this.count }),
|
|
33365
33995
|
asJson,
|
|
33366
33996
|
outputCrs: 'EPSG:4326',
|
|
33367
33997
|
attributes,
|
|
33368
|
-
|
|
33998
|
+
sortBy,
|
|
33369
33999
|
});
|
|
33370
|
-
|
|
33371
|
-
const finalUrl = new URL(url);
|
|
33372
|
-
const sorts = this.sort
|
|
33373
|
-
.map((fieldSort) => `${fieldSort[1]}+${fieldSort[0] === 'asc' ? 'A' : 'D'}`)
|
|
33374
|
-
.join(',');
|
|
33375
|
-
// Direct update on string url to prevent encoding of +A and +D
|
|
33376
|
-
url = `${url}${finalUrl.search ? '&' : ''}SORTBY=${sorts}`;
|
|
33377
|
-
}
|
|
33378
|
-
return fetchDataAsText(url, this.cacheActive).then((text) => asJson
|
|
34000
|
+
return fetchDataAsText(url, this.cacheEnabled).then((text) => asJson
|
|
33379
34001
|
? parseGeojson(text)
|
|
33380
|
-
: parseGml(text,
|
|
33381
|
-
}
|
|
33382
|
-
async getQueryData() {
|
|
33383
|
-
const items = (await this.getData()).items;
|
|
33384
|
-
const jsonItems = getJsonDataItemsProxy(items);
|
|
33385
|
-
const query = generateSqlQuery(this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations);
|
|
33386
|
-
const result = await import('alasql').then((module) => module.default(query, [jsonItems]));
|
|
33387
|
-
return result.map(jsonToGeojsonFeature);
|
|
33388
|
-
}
|
|
33389
|
-
load() {
|
|
33390
|
-
// Nothing to load for Wfs
|
|
33391
|
-
}
|
|
33392
|
-
async read() {
|
|
33393
|
-
return (await this.getData(this.aggregations, this.groupedBy)).items;
|
|
34002
|
+
: parseGml(text, featureType.name, endpoint.getVersion()));
|
|
33394
34003
|
}
|
|
33395
34004
|
}
|
|
33396
34005
|
|
|
33397
|
-
async function openDataset(url,
|
|
33398
|
-
const fileType = await inferDatasetType(url, typeHint);
|
|
34006
|
+
async function openDataset(url, options) {
|
|
34007
|
+
const fileType = await inferDatasetType(url, options?.typeHint);
|
|
33399
34008
|
let reader;
|
|
33400
34009
|
try {
|
|
33401
34010
|
switch (fileType) {
|
|
@@ -33412,18 +34021,18 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33412
34021
|
reader = new ExcelReader(url);
|
|
33413
34022
|
break;
|
|
33414
34023
|
case 'gml':
|
|
33415
|
-
reader = new GmlReader(url
|
|
34024
|
+
reader = new GmlReader(url);
|
|
33416
34025
|
break;
|
|
33417
34026
|
case 'wfs':
|
|
33418
|
-
reader =
|
|
34027
|
+
reader = new WfsReader(url, options?.wfsFeatureType);
|
|
33419
34028
|
break;
|
|
33420
34029
|
}
|
|
33421
|
-
reader.
|
|
34030
|
+
reader.enableCache(options?.enableCache ?? true);
|
|
33422
34031
|
reader.load();
|
|
33423
34032
|
return reader;
|
|
33424
34033
|
}
|
|
33425
34034
|
catch (e) {
|
|
33426
|
-
//WfsReader may already raise a FetchError
|
|
34035
|
+
// WfsReader may already raise a FetchError
|
|
33427
34036
|
if (e instanceof FetchError)
|
|
33428
34037
|
throw e;
|
|
33429
34038
|
else
|
|
@@ -33434,13 +34043,13 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33434
34043
|
* This fetches the full dataset at the given URL and parses it according to its mime type.
|
|
33435
34044
|
* All items in the dataset are converted to GeoJSON features, even if they do not bear any spatial geometry.
|
|
33436
34045
|
* File type can be either inferred (from the HTTP headers or the URL), or hinted using the 2nd argument
|
|
33437
|
-
* File type is determined
|
|
34046
|
+
* File type is determined like so:
|
|
33438
34047
|
* 1. if a type hint is given, use it
|
|
33439
34048
|
* 2. otherwise, look for a Content-Type header in the response with a supported mime type
|
|
33440
34049
|
* 3. if no valid mime type was found, look for an explicit file extension in the url (.csv, .geojson etc.)
|
|
33441
34050
|
*/
|
|
33442
|
-
async function readDataset(url,
|
|
33443
|
-
const reader = await openDataset(url,
|
|
34051
|
+
async function readDataset(url, options) {
|
|
34052
|
+
const reader = await openDataset(url, options);
|
|
33444
34053
|
try {
|
|
33445
34054
|
return await reader.read();
|
|
33446
34055
|
}
|
|
@@ -33671,9 +34280,11 @@ class DataService {
|
|
|
33671
34280
|
getDataset(link, cacheActive) {
|
|
33672
34281
|
if (link.type === 'service' && link.accessServiceProtocol === 'wfs') {
|
|
33673
34282
|
const wfsUrlEndpoint = this.proxy.getProxiedUrl(link.url.toString());
|
|
33674
|
-
return from(openDataset(wfsUrlEndpoint,
|
|
34283
|
+
return from(openDataset(wfsUrlEndpoint, {
|
|
34284
|
+
typeHint: 'wfs',
|
|
33675
34285
|
wfsFeatureType: link.name,
|
|
33676
|
-
|
|
34286
|
+
enableCache: cacheActive,
|
|
34287
|
+
}));
|
|
33677
34288
|
}
|
|
33678
34289
|
else if (link.type === 'download') {
|
|
33679
34290
|
const linkProxifiedUrl = this.proxy.getProxiedUrl(link.url.toString());
|
|
@@ -33681,12 +34292,15 @@ class DataService {
|
|
|
33681
34292
|
const supportedType = SupportedTypes.indexOf(format) > -1
|
|
33682
34293
|
? format
|
|
33683
34294
|
: undefined;
|
|
33684
|
-
return from(openDataset(linkProxifiedUrl,
|
|
34295
|
+
return from(openDataset(linkProxifiedUrl, {
|
|
34296
|
+
typeHint: supportedType,
|
|
34297
|
+
enableCache: cacheActive,
|
|
34298
|
+
})).pipe();
|
|
33685
34299
|
}
|
|
33686
34300
|
else if (link.type === 'service' &&
|
|
33687
34301
|
link.accessServiceProtocol === 'esriRest') {
|
|
33688
34302
|
const url = this.getDownloadUrlFromEsriRest(link.url.toString(), 'geojson');
|
|
33689
|
-
return from(openDataset(url, 'geojson',
|
|
34303
|
+
return from(openDataset(url, { typeHint: 'geojson', enableCache: cacheActive })).pipe();
|
|
33690
34304
|
}
|
|
33691
34305
|
else if (link.type === 'service' &&
|
|
33692
34306
|
link.accessServiceProtocol === 'ogcFeatures') {
|
|
@@ -33700,7 +34314,10 @@ class DataService {
|
|
|
33700
34314
|
}
|
|
33701
34315
|
const urlWithoutLimit = new URL(geojsonUrl);
|
|
33702
34316
|
urlWithoutLimit.searchParams.delete('limit');
|
|
33703
|
-
return openDataset(urlWithoutLimit.toString(),
|
|
34317
|
+
return openDataset(urlWithoutLimit.toString(), {
|
|
34318
|
+
typeHint: 'geojson',
|
|
34319
|
+
enableCache: cacheActive,
|
|
34320
|
+
});
|
|
33704
34321
|
}));
|
|
33705
34322
|
}
|
|
33706
34323
|
return throwError(() => 'protocol not supported');
|
|
@@ -33952,20 +34569,31 @@ class DataTableComponent {
|
|
|
33952
34569
|
this.eltRef = inject(ElementRef);
|
|
33953
34570
|
this.cdr = inject(ChangeDetectorRef);
|
|
33954
34571
|
this.translateService = inject(TranslateService);
|
|
33955
|
-
this.
|
|
34572
|
+
this.columnsFromFeatureCatalog = null;
|
|
34573
|
+
this.columnsFromDataset = [];
|
|
33956
34574
|
this.selected = new EventEmitter();
|
|
33957
|
-
this.properties$ = new BehaviorSubject(null);
|
|
33958
34575
|
this.loading$ = new BehaviorSubject(false);
|
|
33959
34576
|
this.error = null;
|
|
33960
34577
|
}
|
|
33961
34578
|
set featureAttributes(value) {
|
|
33962
|
-
this.
|
|
33963
|
-
|
|
34579
|
+
this.columnsFromFeatureCatalog = value.map((attrs) => ({
|
|
34580
|
+
name: attrs.value,
|
|
34581
|
+
label: attrs.label,
|
|
34582
|
+
}));
|
|
33964
34583
|
}
|
|
33965
34584
|
set dataset(value) {
|
|
33966
34585
|
this.dataset_ = value;
|
|
33967
34586
|
this.dataset_.load();
|
|
33968
|
-
this.dataset_.info.then((info) =>
|
|
34587
|
+
this.dataset_.info.then((info) => {
|
|
34588
|
+
this.count = info.itemsCount;
|
|
34589
|
+
this.cdr.detectChanges();
|
|
34590
|
+
});
|
|
34591
|
+
}
|
|
34592
|
+
get columns() {
|
|
34593
|
+
return this.columnsFromFeatureCatalog ?? this.columnsFromDataset;
|
|
34594
|
+
}
|
|
34595
|
+
get columnNames() {
|
|
34596
|
+
return this.columns.map((c) => c.name);
|
|
33969
34597
|
}
|
|
33970
34598
|
ngOnInit() {
|
|
33971
34599
|
this.dataSource = new DataTableDataSource();
|
|
@@ -34000,11 +34628,12 @@ class DataTableComponent {
|
|
|
34000
34628
|
}
|
|
34001
34629
|
async readData() {
|
|
34002
34630
|
this.loading$.next(true);
|
|
34003
|
-
// wait for properties to be read
|
|
34004
|
-
const properties = await firstValueFrom(this.properties$.pipe(filter((p) => !!p)));
|
|
34005
|
-
const propsWithoutGeom = properties.filter((p) => !p.toLowerCase().startsWith('geom'));
|
|
34006
|
-
this.dataset_.select(...propsWithoutGeom);
|
|
34007
34631
|
try {
|
|
34632
|
+
// wait for properties to be read
|
|
34633
|
+
if (!this.columnsFromFeatureCatalog) {
|
|
34634
|
+
this.columnsFromDataset = await this.dataset_.properties;
|
|
34635
|
+
}
|
|
34636
|
+
this.dataset_.select(...this.columnNames);
|
|
34008
34637
|
await this.dataSource.showData(this.dataset_.read());
|
|
34009
34638
|
this.error = null;
|
|
34010
34639
|
}
|
|
@@ -34034,7 +34663,7 @@ class DataTableComponent {
|
|
|
34034
34663
|
}
|
|
34035
34664
|
}
|
|
34036
34665
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
34037
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DataTableComponent, isStandalone: true, selector: "gn-ui-data-table", inputs: { featureAttributes: "featureAttributes", dataset: "dataset", activeId: "activeId" }, outputs: { selected: "selected" }, providers: [{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col border border-gray-300 rounded-lg bg-white h-full\">\n <div class=\"flex-1 overflow-y-hidden overflow-x-auto rounded-lg relative\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"setSort($event)\"\n [matSortDisableClear]=\"true\"\n
|
|
34666
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DataTableComponent, isStandalone: true, selector: "gn-ui-data-table", inputs: { featureAttributes: "featureAttributes", dataset: "dataset", activeId: "activeId" }, outputs: { selected: "selected" }, providers: [{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"flex flex-col border border-gray-300 rounded-lg bg-white h-full\">\n <div class=\"flex-1 overflow-y-hidden overflow-x-auto rounded-lg relative\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"setSort($event)\"\n [matSortDisableClear]=\"true\"\n >\n @for (column of columns; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n class=\"text-sm text-black bg-white\"\n >\n {{ column.label }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n class=\"whitespace-nowrap pr-1 truncate\"\n >\n {{ element[column.name] }}\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames; sticky: true\"></tr>\n <tr\n [id]=\"getRowEltId(row.id)\"\n mat-row\n *matRowDef=\"let row; columns: columnNames\"\n (click)=\"selected.emit(row)\"\n [class.active]=\"\n activeId !== undefined && activeId !== null && row.id === activeId\n \"\n ></tr>\n </table>\n @if (loading$ | async) {\n <gn-ui-loading-mask\n class=\"sticky inset-0\"\n [message]=\"'table.loading.data' | translate\"\n ></gn-ui-loading-mask>\n }\n @if (error) {\n <gn-ui-popup-alert\n type=\"warning\"\n icon=\"matErrorOutlineOutline\"\n class=\"absolute m-2 inset-0 z-[100]\"\n >\n <span translate>{{ error }}</span>\n </gn-ui-popup-alert>\n }\n </div>\n <div class=\"flex justify-between items-center overflow-hidden\">\n <div class=\"text-gray-900 px-4 py-2 text-sm\">\n <span class=\"count font-extrabold text-primary\">{{ count }}</span\n > <span translate>table.object.count</span>.\n </div>\n\n <mat-paginator\n class=\"my-[-16px]\"\n (page)=\"setPagination()\"\n [length]=\"count\"\n [pageSize]=\"10\"\n [showFirstLastButtons]=\"true\"\n [hidePageSize]=\"true\"\n ></mat-paginator>\n </div>\n</div>\n", styles: ["table{width:100%;background:#fff}th.mat-mdc-header-cell,td.mat-mdc-cell,td.mat-mdc-footer-cell{padding-right:20px}tr.mat-mdc-row,tr.mat-mdc-footer-row{height:36px}tr:hover{background:#f5f5f5}tr.mat-mdc-header-row{height:48px}[mat-header-cell]{color:#0000008a;font-size:12px;font-weight:500}tr{cursor:pointer}.active .mat-mdc-cell{color:var(--color-primary)}.mat-mdc-paginator{background:none}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$b.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$b.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$b.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$b.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$b.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$b.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$b.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$b.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$b.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$b.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i2$4.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i2$4.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: LoadingMaskComponent, selector: "gn-ui-loading-mask", inputs: ["message"] }, { kind: "component", type: PopupAlertComponent, selector: "gn-ui-popup-alert", inputs: ["icon", "type", "position"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
34038
34667
|
}
|
|
34039
34668
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
34040
34669
|
type: Component,
|
|
@@ -34046,10 +34675,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
34046
34675
|
CommonModule,
|
|
34047
34676
|
LoadingMaskComponent,
|
|
34048
34677
|
PopupAlertComponent,
|
|
34049
|
-
LetDirective,
|
|
34050
34678
|
TranslatePipe,
|
|
34051
34679
|
TranslateDirective,
|
|
34052
|
-
], providers: [{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl }], selector: 'gn-ui-data-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col border border-gray-300 rounded-lg bg-white h-full\">\n <div class=\"flex-1 overflow-y-hidden overflow-x-auto rounded-lg relative\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"setSort($event)\"\n [matSortDisableClear]=\"true\"\n
|
|
34680
|
+
], providers: [{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl }], selector: 'gn-ui-data-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col border border-gray-300 rounded-lg bg-white h-full\">\n <div class=\"flex-1 overflow-y-hidden overflow-x-auto rounded-lg relative\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n matSort\n (matSortChange)=\"setSort($event)\"\n [matSortDisableClear]=\"true\"\n >\n @for (column of columns; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th\n mat-header-cell\n *matHeaderCellDef\n mat-sort-header\n class=\"text-sm text-black bg-white\"\n >\n {{ column.label }}\n </th>\n <td\n mat-cell\n *matCellDef=\"let element\"\n class=\"whitespace-nowrap pr-1 truncate\"\n >\n {{ element[column.name] }}\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"columnNames; sticky: true\"></tr>\n <tr\n [id]=\"getRowEltId(row.id)\"\n mat-row\n *matRowDef=\"let row; columns: columnNames\"\n (click)=\"selected.emit(row)\"\n [class.active]=\"\n activeId !== undefined && activeId !== null && row.id === activeId\n \"\n ></tr>\n </table>\n @if (loading$ | async) {\n <gn-ui-loading-mask\n class=\"sticky inset-0\"\n [message]=\"'table.loading.data' | translate\"\n ></gn-ui-loading-mask>\n }\n @if (error) {\n <gn-ui-popup-alert\n type=\"warning\"\n icon=\"matErrorOutlineOutline\"\n class=\"absolute m-2 inset-0 z-[100]\"\n >\n <span translate>{{ error }}</span>\n </gn-ui-popup-alert>\n }\n </div>\n <div class=\"flex justify-between items-center overflow-hidden\">\n <div class=\"text-gray-900 px-4 py-2 text-sm\">\n <span class=\"count font-extrabold text-primary\">{{ count }}</span\n > <span translate>table.object.count</span>.\n </div>\n\n <mat-paginator\n class=\"my-[-16px]\"\n (page)=\"setPagination()\"\n [length]=\"count\"\n [pageSize]=\"10\"\n [showFirstLastButtons]=\"true\"\n [hidePageSize]=\"true\"\n ></mat-paginator>\n </div>\n</div>\n", styles: ["table{width:100%;background:#fff}th.mat-mdc-header-cell,td.mat-mdc-cell,td.mat-mdc-footer-cell{padding-right:20px}tr.mat-mdc-row,tr.mat-mdc-footer-row{height:36px}tr:hover{background:#f5f5f5}tr.mat-mdc-header-row{height:48px}[mat-header-cell]{color:#0000008a;font-size:12px;font-weight:500}tr{cursor:pointer}.active .mat-mdc-cell{color:var(--color-primary)}.mat-mdc-paginator{background:none}\n"] }]
|
|
34053
34681
|
}], propDecorators: { featureAttributes: [{
|
|
34054
34682
|
type: Input
|
|
34055
34683
|
}], dataset: [{
|
|
@@ -34152,7 +34780,7 @@ class ChartViewComponent {
|
|
|
34152
34780
|
}), shareReplay$1(1));
|
|
34153
34781
|
this.properties$ = combineLatest([this.dataset$, this.featureCatalog$]).pipe(switchMap$1(([dataset, catalog]) => this.setProperties(dataset, catalog)), shareReplay$1(1));
|
|
34154
34782
|
this.yChoices$ = this.properties$.pipe(map$1((properties) => properties
|
|
34155
|
-
.filter((prop) => prop.type === 'number'
|
|
34783
|
+
.filter((prop) => prop.type === 'number')
|
|
34156
34784
|
.map((prop) => ({ value: prop.name, label: prop.label || prop.name }))), tap$1((choices) => {
|
|
34157
34785
|
if (!choices.find((choice) => choice.value === this.yProperty$.value)) {
|
|
34158
34786
|
const newProp = choices[0]?.value || '';
|
|
@@ -34179,6 +34807,7 @@ class ChartViewComponent {
|
|
|
34179
34807
|
this.aggregation$,
|
|
34180
34808
|
]).pipe(filter$1(([_, x, y]) => !!x || !!y), switchMap$1(([dataset, xProp, yProp, aggregation]) => {
|
|
34181
34809
|
const fieldAgg = aggregation === 'count' ? ['count'] : [aggregation, yProp];
|
|
34810
|
+
this.loading = true;
|
|
34182
34811
|
return dataset
|
|
34183
34812
|
.groupBy(['distinct', xProp])
|
|
34184
34813
|
.aggregate(fieldAgg)
|
|
@@ -34420,6 +35049,7 @@ class GeoTableViewComponent {
|
|
|
34420
35049
|
}));
|
|
34421
35050
|
}
|
|
34422
35051
|
async initMapContext() {
|
|
35052
|
+
this.dataset.load();
|
|
34423
35053
|
this.dataset.selectAll();
|
|
34424
35054
|
return {
|
|
34425
35055
|
layers: [
|
|
@@ -34593,8 +35223,7 @@ class MdViewFacade {
|
|
|
34593
35223
|
}));
|
|
34594
35224
|
this.error$ = this.store.pipe(select(getMetadataError));
|
|
34595
35225
|
this.related$ = this.store.pipe(select(getRelated));
|
|
34596
|
-
this.
|
|
34597
|
-
this.sourceOf$ = this.store.pipe(select(getSourceOf));
|
|
35226
|
+
this.linkedRecords$ = this.store.pipe(select(getLinkedRecords));
|
|
34598
35227
|
this.chartConfig$ = this.store.pipe(select(getChartConfig));
|
|
34599
35228
|
this.allLinks$ = this.metadata$.pipe(map$1((record) => 'onlineResources' in record ? record.onlineResources : []), shareReplay$1(1));
|
|
34600
35229
|
this.resourceDoi$ = this.metadata$.pipe(map$1((record) => {
|
|
@@ -34713,12 +35342,9 @@ class MdViewEffects {
|
|
|
34713
35342
|
this.loadRelatedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getSimilarRecords(full)), map$1((related) => {
|
|
34714
35343
|
return setRelated({ related });
|
|
34715
35344
|
}), catchError(() => of(setRelated({ related: null })))));
|
|
34716
|
-
this.
|
|
34717
|
-
return
|
|
34718
|
-
}), catchError(() => of(
|
|
34719
|
-
this.loadSourceOf$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getSourceOf(full)), map$1((sourceOf) => {
|
|
34720
|
-
return setSourceOf({ sourceOf });
|
|
34721
|
-
}), catchError(() => of(setSourceOf({ sourceOf: null })))));
|
|
35345
|
+
this.loadLinkedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getLinkedRecords(full)), map$1((linkedRecords) => {
|
|
35346
|
+
return setLinkedRecords({ linkedRecords });
|
|
35347
|
+
}), catchError(() => of(setLinkedRecords({ linkedRecords: null })))));
|
|
34722
35348
|
/*
|
|
34723
35349
|
UserFeedback effects
|
|
34724
35350
|
*/
|
|
@@ -36452,6 +37078,11 @@ const DEFAULT_CONFIGURATION = {
|
|
|
36452
37078
|
},
|
|
36453
37079
|
hidden: '${record.kind == "service"}',
|
|
36454
37080
|
},
|
|
37081
|
+
{
|
|
37082
|
+
model: 'associatedRecords',
|
|
37083
|
+
formFieldConfig: {},
|
|
37084
|
+
hidden: '${record.kind == "service"}',
|
|
37085
|
+
},
|
|
36455
37086
|
],
|
|
36456
37087
|
},
|
|
36457
37088
|
// Section: Geographical coverage
|
|
@@ -37414,7 +38045,7 @@ class GenericKeywordsComponent {
|
|
|
37414
38045
|
this.deletedKeyword.emit(keyword);
|
|
37415
38046
|
}
|
|
37416
38047
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GenericKeywordsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
37417
|
-
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 }); }
|
|
38048
|
+
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 }); }
|
|
37418
38049
|
}
|
|
37419
38050
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GenericKeywordsComponent, decorators: [{
|
|
37420
38051
|
type: Component,
|
|
@@ -37589,7 +38220,7 @@ class FormFieldTemporalExtentsComponent {
|
|
|
37589
38220
|
provideNgIconsConfig({
|
|
37590
38221
|
size: '1.5rem',
|
|
37591
38222
|
}),
|
|
37592
|
-
], ngImport: i0, template: "<div class=\"flex gap-2
|
|
38223
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\n <div class=\"flex gap-2\">\n @for (addOption of addOptions$ | async; track addOption) {\n <gn-ui-button type=\"gray\" (buttonClick)=\"onAdd(addOption.eventName)\">\n <ng-icon name=\"iconoirPlus\" class=\"text-primary\"></ng-icon> {{\n addOption.buttonLabel\n }}</gn-ui-button\n >\n }\n </div>\n @if (extents.length) {\n <gn-ui-sortable-list\n [items]=\"extents\"\n (itemsOrderChange)=\"onItemsOrderChange($event)\"\n [elementTemplate]=\"template\"\n ></gn-ui-sortable-list>\n }\n</div>\n<ng-template #template let-extent let-index=\"index\">\n @if (extent.end === undefined) {\n <div class=\"border rounded-lg px-4 pb-4\">\n <p class=\"my-2\" translate>editor.record.form.temporalExtents.date</p>\n <gn-ui-date-picker\n [date]=\"extent.start\"\n (dateChange)=\"onExtentChange({ start: $event }, index)\"\n ></gn-ui-date-picker>\n </div>\n }\n @if (extent.end !== undefined) {\n <div class=\"border rounded-lg px-4 pb-4\">\n <p class=\"my-2\" translate>editor.record.form.temporalExtents.range</p>\n <gn-ui-date-range-picker\n [startDate]=\"extent.start\"\n [endDate]=\"extent.end\"\n (startDateChange)=\"onExtentChange({ start: $event }, index)\"\n (endDateChange)=\"onExtentChange({ end: $event }, index)\"\n ></gn-ui-date-range-picker>\n </div>\n }\n</ng-template>\n", styles: [":host{--gn-ui-button-padding: 8px 8px;--gn-ui-button-rounded: 8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: SortableListComponent, selector: "gn-ui-sortable-list", inputs: ["elementTemplate", "items"], outputs: ["itemsOrderChange"] }, { kind: "component", type: DatePickerComponent, selector: "gn-ui-date-picker", inputs: ["date"], outputs: ["dateChange"] }, { kind: "component", type: DateRangePickerComponent, selector: "gn-ui-date-range-picker", inputs: ["startDate", "endDate"], outputs: ["startDateChange", "endDateChange"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { 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 }); }
|
|
37593
38224
|
}
|
|
37594
38225
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldTemporalExtentsComponent, decorators: [{
|
|
37595
38226
|
type: Component,
|
|
@@ -37606,7 +38237,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37606
38237
|
provideNgIconsConfig({
|
|
37607
38238
|
size: '1.5rem',
|
|
37608
38239
|
}),
|
|
37609
|
-
], template: "<div class=\"flex gap-2
|
|
38240
|
+
], template: "<div class=\"flex flex-col gap-2\">\n <div class=\"flex gap-2\">\n @for (addOption of addOptions$ | async; track addOption) {\n <gn-ui-button type=\"gray\" (buttonClick)=\"onAdd(addOption.eventName)\">\n <ng-icon name=\"iconoirPlus\" class=\"text-primary\"></ng-icon> {{\n addOption.buttonLabel\n }}</gn-ui-button\n >\n }\n </div>\n @if (extents.length) {\n <gn-ui-sortable-list\n [items]=\"extents\"\n (itemsOrderChange)=\"onItemsOrderChange($event)\"\n [elementTemplate]=\"template\"\n ></gn-ui-sortable-list>\n }\n</div>\n<ng-template #template let-extent let-index=\"index\">\n @if (extent.end === undefined) {\n <div class=\"border rounded-lg px-4 pb-4\">\n <p class=\"my-2\" translate>editor.record.form.temporalExtents.date</p>\n <gn-ui-date-picker\n [date]=\"extent.start\"\n (dateChange)=\"onExtentChange({ start: $event }, index)\"\n ></gn-ui-date-picker>\n </div>\n }\n @if (extent.end !== undefined) {\n <div class=\"border rounded-lg px-4 pb-4\">\n <p class=\"my-2\" translate>editor.record.form.temporalExtents.range</p>\n <gn-ui-date-range-picker\n [startDate]=\"extent.start\"\n [endDate]=\"extent.end\"\n (startDateChange)=\"onExtentChange({ start: $event }, index)\"\n (endDateChange)=\"onExtentChange({ end: $event }, index)\"\n ></gn-ui-date-range-picker>\n </div>\n }\n</ng-template>\n", styles: [":host{--gn-ui-button-padding: 8px 8px;--gn-ui-button-rounded: 8px}\n"] }]
|
|
37610
38241
|
}], propDecorators: { value: [{
|
|
37611
38242
|
type: Input
|
|
37612
38243
|
}], valueChange: [{
|
|
@@ -37822,6 +38453,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37822
38453
|
], template: "<div class=\"flex flex-col gap-3\">\n <gn-ui-generic-keywords\n [placeholder]=\"'editor.record.form.keywords.place.placeholder' | translate\"\n [keywords]=\"shownKeywords$ | async\"\n [keywordTypes]=\"['place']\"\n (deletedKeyword)=\"handleKeywordDelete($event)\"\n (addedKeyword)=\"handleKeywordAdd($event)\"\n >\n </gn-ui-generic-keywords>\n <div class=\"w-full h-96 mt-2\">\n <gn-ui-spatial-extent\n [spatialExtents]=\"spatialExtents$ | async\"\n ></gn-ui-spatial-extent>\n </div>\n</div>\n" }]
|
|
37823
38454
|
}] });
|
|
37824
38455
|
|
|
38456
|
+
class FormFieldAssociatedRecordsComponent {
|
|
38457
|
+
constructor() {
|
|
38458
|
+
this.valueChange = new EventEmitter();
|
|
38459
|
+
}
|
|
38460
|
+
get list() {
|
|
38461
|
+
return this.value ?? [];
|
|
38462
|
+
}
|
|
38463
|
+
get first() {
|
|
38464
|
+
return this.list[0];
|
|
38465
|
+
}
|
|
38466
|
+
get rest() {
|
|
38467
|
+
return this.list.slice(1);
|
|
38468
|
+
}
|
|
38469
|
+
get hasParentLink() {
|
|
38470
|
+
return this.list.length > 0;
|
|
38471
|
+
}
|
|
38472
|
+
get uniqueIdentifier() {
|
|
38473
|
+
return this.first?.uniqueIdentifier ?? '';
|
|
38474
|
+
}
|
|
38475
|
+
get selectedType() {
|
|
38476
|
+
return this.first?.associationType;
|
|
38477
|
+
}
|
|
38478
|
+
get choices() {
|
|
38479
|
+
return associationTypeValues.map((value) => ({
|
|
38480
|
+
value,
|
|
38481
|
+
label: `domain.record.associationType.${value}`,
|
|
38482
|
+
}));
|
|
38483
|
+
}
|
|
38484
|
+
onToggle(checked) {
|
|
38485
|
+
this.valueChange.emit(checked
|
|
38486
|
+
? [
|
|
38487
|
+
{
|
|
38488
|
+
uniqueIdentifier: '',
|
|
38489
|
+
associationType: associationTypeValues[0],
|
|
38490
|
+
},
|
|
38491
|
+
...this.rest,
|
|
38492
|
+
]
|
|
38493
|
+
: this.rest);
|
|
38494
|
+
}
|
|
38495
|
+
onUniqueIdentifierChange(uniqueIdentifier) {
|
|
38496
|
+
this.valueChange.emit(uniqueIdentifier
|
|
38497
|
+
? [{ ...this.first, uniqueIdentifier }, ...this.rest]
|
|
38498
|
+
: this.rest);
|
|
38499
|
+
}
|
|
38500
|
+
onTypeChange(associationType) {
|
|
38501
|
+
this.valueChange.emit([
|
|
38502
|
+
{ ...this.first, associationType: associationType },
|
|
38503
|
+
...this.rest,
|
|
38504
|
+
]);
|
|
38505
|
+
}
|
|
38506
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
38507
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FormFieldAssociatedRecordsComponent, isStandalone: true, selector: "gn-ui-form-field-associated-records", inputs: { value: "value" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n [label]=\"'editor.record.form.field.parentLink' | translate\"\n [value]=\"hasParentLink\"\n (toggled)=\"onToggle($event)\"\n data-cy=\"associated-record-toggle\"\n ></gn-ui-check-toggle>\n @if (hasParentLink) {\n <gn-ui-form-field-wrapper\n [label]=\"'editor.record.form.field.parentIdentifier' | translate\"\n >\n <gn-ui-text-input\n [value]=\"uniqueIdentifier\"\n (valueChange)=\"onUniqueIdentifierChange($event)\"\n placeholder=\"\"\n data-cy=\"associated-record-identifier\"\n ></gn-ui-text-input>\n </gn-ui-form-field-wrapper>\n <gn-ui-form-field-wrapper\n [label]=\"'editor.record.form.field.parentType' | translate\"\n >\n <gn-ui-dropdown-selector\n [title]=\"'editor.record.form.field.parentType' | translate\"\n [showTitle]=\"false\"\n [choices]=\"choices\"\n [selected]=\"selectedType\"\n (selectValue)=\"onTypeChange($event)\"\n [extraBtnClass]=\"'input-as-button gn-ui-text-input'\"\n data-cy=\"associated-record-type\"\n ></gn-ui-dropdown-selector>\n </gn-ui-form-field-wrapper>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: CheckToggleComponent, selector: "gn-ui-check-toggle", inputs: ["title", "label", "value", "color"], outputs: ["toggled"] }, { kind: "component", type: TextInputComponent, selector: "gn-ui-text-input", inputs: ["value", "extraClass", "placeholder", "required", "disabled", "type"], outputs: ["valueChange"] }, { kind: "component", type: DropdownSelectorComponent, selector: "gn-ui-dropdown-selector", inputs: ["title", "showTitle", "ariaName", "choices", "selected", "maxRows", "extraBtnClass", "minWidth", "disabled"], outputs: ["selectValue"] }, { kind: "component", type: FormFieldWrapperComponent, selector: "gn-ui-form-field-wrapper", inputs: ["label", "hint"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
38508
|
+
}
|
|
38509
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, decorators: [{
|
|
38510
|
+
type: Component,
|
|
38511
|
+
args: [{ selector: 'gn-ui-form-field-associated-records', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
38512
|
+
CheckToggleComponent,
|
|
38513
|
+
TextInputComponent,
|
|
38514
|
+
DropdownSelectorComponent,
|
|
38515
|
+
FormFieldWrapperComponent,
|
|
38516
|
+
TranslatePipe,
|
|
38517
|
+
], template: "<div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n [label]=\"'editor.record.form.field.parentLink' | translate\"\n [value]=\"hasParentLink\"\n (toggled)=\"onToggle($event)\"\n data-cy=\"associated-record-toggle\"\n ></gn-ui-check-toggle>\n @if (hasParentLink) {\n <gn-ui-form-field-wrapper\n [label]=\"'editor.record.form.field.parentIdentifier' | translate\"\n >\n <gn-ui-text-input\n [value]=\"uniqueIdentifier\"\n (valueChange)=\"onUniqueIdentifierChange($event)\"\n placeholder=\"\"\n data-cy=\"associated-record-identifier\"\n ></gn-ui-text-input>\n </gn-ui-form-field-wrapper>\n <gn-ui-form-field-wrapper\n [label]=\"'editor.record.form.field.parentType' | translate\"\n >\n <gn-ui-dropdown-selector\n [title]=\"'editor.record.form.field.parentType' | translate\"\n [showTitle]=\"false\"\n [choices]=\"choices\"\n [selected]=\"selectedType\"\n (selectValue)=\"onTypeChange($event)\"\n [extraBtnClass]=\"'input-as-button gn-ui-text-input'\"\n data-cy=\"associated-record-type\"\n ></gn-ui-dropdown-selector>\n </gn-ui-form-field-wrapper>\n }\n</div>\n" }]
|
|
38518
|
+
}], propDecorators: { value: [{
|
|
38519
|
+
type: Input
|
|
38520
|
+
}], valueChange: [{
|
|
38521
|
+
type: Output
|
|
38522
|
+
}] } });
|
|
38523
|
+
|
|
37825
38524
|
class ContactCardComponent {
|
|
37826
38525
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContactCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
37827
38526
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: ContactCardComponent, isStandalone: true, selector: "gn-ui-contact-card", inputs: { contact: "contact" }, ngImport: i0, template: "<div class=\"gn-ui-card\">\n <gn-ui-thumbnail\n class=\"w-[56px] h-[56px] rounded-[4px] overflow-hidden shrink-0\"\n [thumbnailUrl]=\"contact.organization?.logoUrl?.href\"\n [fit]=\"'contain'\"\n ></gn-ui-thumbnail>\n <div class=\"flex flex-col w-full overflow-hidden leading-snug justify-center\">\n <div class=\"text-[16px] font-bold text-main\" data-test=\"contactCardName\">\n {{ contact.firstName }} {{ contact.lastName }}\n </div>\n <div class=\"text-[14px] text-gray-900\" data-test=\"contactCardEmail\">\n {{ contact.email }}\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: ThumbnailComponent, selector: "gn-ui-thumbnail", inputs: ["thumbnailUrl", "fit"], outputs: ["placeholderShown"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
@@ -37938,7 +38637,7 @@ class FormFieldContactsForResourceComponent {
|
|
|
37938
38637
|
provideNgIconsConfig({
|
|
37939
38638
|
size: '1.5rem',
|
|
37940
38639
|
}),
|
|
37941
|
-
], 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 \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 }); }
|
|
38640
|
+
], 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 \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 }); }
|
|
37942
38641
|
}
|
|
37943
38642
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsForResourceComponent, decorators: [{
|
|
37944
38643
|
type: Component,
|
|
@@ -38038,7 +38737,7 @@ class FormFieldContactsComponent {
|
|
|
38038
38737
|
this.subscription.unsubscribe();
|
|
38039
38738
|
}
|
|
38040
38739
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
38041
|
-
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 }); }
|
|
38740
|
+
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 }); }
|
|
38042
38741
|
}
|
|
38043
38742
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldContactsComponent, decorators: [{
|
|
38044
38743
|
type: Component,
|
|
@@ -38391,7 +39090,7 @@ class OnlineServiceResourceInputComponent {
|
|
|
38391
39090
|
provideNgIconsConfig({
|
|
38392
39091
|
size: '1.5em',
|
|
38393
39092
|
}),
|
|
38394
|
-
], 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 }); }
|
|
39093
|
+
], 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 }); }
|
|
38395
39094
|
}
|
|
38396
39095
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OnlineServiceResourceInputComponent, decorators: [{
|
|
38397
39096
|
type: Component,
|
|
@@ -39207,6 +39906,9 @@ class FormFieldComponent {
|
|
|
39207
39906
|
get valueAsUpdateFrequency() {
|
|
39208
39907
|
return this.value;
|
|
39209
39908
|
}
|
|
39909
|
+
get valueAsAssociatedRecords() {
|
|
39910
|
+
return this.value;
|
|
39911
|
+
}
|
|
39210
39912
|
get valueAsTemporalExtents() {
|
|
39211
39913
|
return this.value;
|
|
39212
39914
|
}
|
|
@@ -39246,7 +39948,7 @@ class FormFieldComponent {
|
|
|
39246
39948
|
}
|
|
39247
39949
|
}
|
|
39248
39950
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
39249
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FormFieldComponent, isStandalone: true, selector: "gn-ui-form-field", inputs: { uniqueIdentifier: "uniqueIdentifier", recordKind: "recordKind", model: "model", modelSpecifier: "modelSpecifier", componentName: "componentName", config: "config", value: "value" }, outputs: { valueChange: "valueChange" }, providers: [provideIcons({ matEditOutline, matHelpOutline })], viewQueries: [{ propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }], hostDirectives: [{ directive: FieldFocusDirective }], ngImport: i0, template: "<!-- TEMPORARY - disabling the open data switch -->\n<!-- <ng-container *ngIf=\"model === 'licenses'\">\n <gn-ui-form-field-open-data\n [value]=\"valueAsConstraints\"\n (valueChange)=\"valueChange.emit($event)\"\n (openDataChange)=\"toggleIsOpenData($event)\"\n ></gn-ui-form-field-open-data>\n</ng-container> -->\n<div class=\"flex flex-col h-full\">\n <ng-container *ngIf=\"withoutWrapper; else withGenericWrapper\">\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </ng-container>\n <ng-template #withGenericWrapper>\n <gn-ui-form-field-wrapper\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n >\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </gn-ui-form-field-wrapper>\n </ng-template>\n</div>\n\n<ng-template #fieldContent>\n <ng-container [ngSwitch]=\"model\">\n <ng-container *ngSwitchCase=\"'title'\">\n <div class=\"flex flex-row flex-start items-center gap-3 mb-[12px]\">\n <textarea\n #titleInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n data-test=\"recordTitleInput\"\n class=\"grow font-title text-3xl font-normal overflow-hidden text-black/80\"\n [value]=\"valueAsString\"\n (change)=\"valueChange.emit($event.target.value)\"\n [placeholder]=\"\n 'editor.record.form.field.title.placeholder'\n | translate: { recordKind }\n \"\n ></textarea>\n <div class=\"flex flex-row justify-between self-start mt-0.5\">\n <ng-icon\n name=\"matEditOutline\"\n size=\"16\"\n class=\"m-2 cursor-pointer\"\n (click)=\"focusTitleInput()\"\n ></ng-icon>\n <ng-icon\n *ngIf=\"config.hintKey\"\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"config.hintKey! | translate: { recordKind }\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'abstract'\">\n <gn-ui-form-field-rich\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n [value]=\"valueAsString\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-rich>\n </ng-container>\n <ng-container *ngSwitchCase=\"'overviews'\">\n <gn-ui-form-field-overviews\n [metadataUuid]=\"uniqueIdentifier\"\n [recordKind]=\"recordKind\"\n [value]=\"valueAsOverviews\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-overviews>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceIdentifiers'\">\n <gn-ui-form-field-simple\n [type]=\"'text'\"\n [value]=\"valueAsResourceIdentifierCode\"\n (valueChange)=\"handleResourceIdentifierChange($event)\"\n ></gn-ui-form-field-simple>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceCreated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceUpdated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'updateFrequency'\">\n <gn-ui-form-field-update-frequency\n [value]=\"valueAsUpdateFrequency\"\n (valueChange)=\"valueChange.emit($event)\"\n [recordKind]=\"recordKind\"\n ></gn-ui-form-field-update-frequency>\n </ng-container>\n <ng-container *ngSwitchCase=\"'temporalExtents'\">\n <gn-ui-form-field-temporal-extents\n [value]=\"valueAsTemporalExtents\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-temporal-extents>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spatialExtents'\">\n <gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>\n </ng-container>\n <ng-container *ngSwitchCase=\"'keywords'\">\n <gn-ui-form-field-keywords\n [value]=\"valueAsKeywords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-keywords>\n </ng-container>\n <ng-container *ngSwitchCase=\"'topics'\">\n <gn-ui-form-field-topics\n [value]=\"valueAsTopics\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-topics>\n </ng-container>\n <ng-container *ngSwitchCase=\"'licenses'\">\n <gn-ui-form-field-license\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [recordLicences]=\"valueAsConstraints\"\n (recordLicencesChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-license>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'legalConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'securityConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'otherConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container\n ></ng-container>\n <ng-template #formFieldConstraints>\n <gn-ui-form-field-constraints\n [label]=\"config.labelKey\"\n [value]=\"valueAsConstraints\"\n [constraintType]=\"model\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-constraints\n ></ng-template>\n\n <ng-container *ngSwitchCase=\"'contactsForResource'\">\n <gn-ui-form-field-contacts-for-resource\n [value]=\"valueAsIndividuals\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts-for-resource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'contacts'\">\n <gn-ui-form-field-contacts\n [value]=\"valueAsIndividuals\"\n [modelSpecifier]=\"modelSpecifier\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:!link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-link-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-link-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-single-link-resource\n *ngIf=\"modelSpecifier === 'onlineResourceType:singleLink'\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-single-link-resource>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"!model\">\n <ng-container [ngSwitch]=\"componentName\">\n <ng-container *ngSwitchCase=\"'form-field-constraints-shortcuts'\">\n <gn-ui-form-field-constraints-shortcuts></gn-ui-form-field-constraints-shortcuts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'form-field-spatial-toggle'\">\n <gn-ui-form-field-spatial-toggle></gn-ui-form-field-spatial-toggle>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n", styles: [":host{scroll-margin-top:90px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FormFieldWrapperComponent, selector: "gn-ui-form-field-wrapper", inputs: ["label", "hint"] }, { kind: "component", type: FormFieldLicenseComponent, selector: "gn-ui-form-field-license", inputs: ["label", "recordLicences"], outputs: ["recordLicencesChange"] }, { kind: "component", type: FormFieldDateComponent, selector: "gn-ui-form-field-date", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldUpdateFrequencyComponent, selector: "gn-ui-form-field-update-frequency", inputs: ["value", "recordKind"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldTemporalExtentsComponent, selector: "gn-ui-form-field-temporal-extents", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldSimpleComponent, selector: "gn-ui-form-field-simple", inputs: ["type", "readonly", "invalid", "placeholder", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldRichComponent, selector: "gn-ui-form-field-rich", inputs: ["label", "hint", "placeholder", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldSpatialExtentComponent, selector: "gn-ui-form-field-spatial-extent" }, { kind: "component", type: FormFieldKeywordsComponent, selector: "gn-ui-form-field-keywords", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOverviewsComponent, selector: "gn-ui-form-field-overviews", inputs: ["metadataUuid", "recordKind", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldContactsForResourceComponent, selector: "gn-ui-form-field-contacts-for-resource", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineResourcesComponent, selector: "gn-ui-form-field-online-resources", inputs: ["metadataUuid", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineLinkResourcesComponent, selector: "gn-ui-form-field-online-link-resources", inputs: ["metadataUuid", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineSingleLinkResourceComponent, selector: "gn-ui-form-field-online-single-link-resource", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldContactsComponent, selector: "gn-ui-form-field-contacts", inputs: ["value", "modelSpecifier"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldConstraintsComponent, selector: "gn-ui-form-field-constraints", inputs: ["label", "value", "constraintType"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldConstraintsShortcutsComponent, selector: "gn-ui-form-field-constraints-shortcuts" }, { kind: "component", type: FormFieldSpatialToggleComponent, selector: "gn-ui-form-field-spatial-toggle" }, { kind: "component", type: FormFieldTopicsComponent, selector: "gn-ui-form-field-topics", inputs: ["value"], outputs: ["valueChange"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "directive", type: i4$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
39951
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FormFieldComponent, isStandalone: true, selector: "gn-ui-form-field", inputs: { uniqueIdentifier: "uniqueIdentifier", recordKind: "recordKind", model: "model", modelSpecifier: "modelSpecifier", componentName: "componentName", config: "config", value: "value" }, outputs: { valueChange: "valueChange" }, providers: [provideIcons({ matEditOutline, matHelpOutline })], viewQueries: [{ propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }], hostDirectives: [{ directive: FieldFocusDirective }], ngImport: i0, template: "<!-- TEMPORARY - disabling the open data switch -->\n<!-- <ng-container *ngIf=\"model === 'licenses'\">\n <gn-ui-form-field-open-data\n [value]=\"valueAsConstraints\"\n (valueChange)=\"valueChange.emit($event)\"\n (openDataChange)=\"toggleIsOpenData($event)\"\n ></gn-ui-form-field-open-data>\n</ng-container> -->\n<div class=\"flex flex-col h-full\">\n <ng-container *ngIf=\"withoutWrapper; else withGenericWrapper\">\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </ng-container>\n <ng-template #withGenericWrapper>\n <gn-ui-form-field-wrapper\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n >\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </gn-ui-form-field-wrapper>\n </ng-template>\n</div>\n\n<ng-template #fieldContent>\n <ng-container [ngSwitch]=\"model\">\n <ng-container *ngSwitchCase=\"'title'\">\n <div class=\"flex flex-row flex-start items-center gap-3 mb-[12px]\">\n <textarea\n #titleInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n data-test=\"recordTitleInput\"\n class=\"grow font-title text-3xl font-normal overflow-hidden text-black/80\"\n [value]=\"valueAsString\"\n (change)=\"valueChange.emit($event.target.value)\"\n [placeholder]=\"\n 'editor.record.form.field.title.placeholder'\n | translate: { recordKind }\n \"\n ></textarea>\n <div class=\"flex flex-row justify-between self-start mt-0.5\">\n <ng-icon\n name=\"matEditOutline\"\n size=\"16\"\n class=\"m-2 cursor-pointer\"\n (click)=\"focusTitleInput()\"\n ></ng-icon>\n <ng-icon\n *ngIf=\"config.hintKey\"\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"config.hintKey! | translate: { recordKind }\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'abstract'\">\n <gn-ui-form-field-rich\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n [value]=\"valueAsString\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-rich>\n </ng-container>\n <ng-container *ngSwitchCase=\"'overviews'\">\n <gn-ui-form-field-overviews\n [metadataUuid]=\"uniqueIdentifier\"\n [recordKind]=\"recordKind\"\n [value]=\"valueAsOverviews\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-overviews>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceIdentifiers'\">\n <gn-ui-form-field-simple\n [type]=\"'text'\"\n [value]=\"valueAsResourceIdentifierCode\"\n (valueChange)=\"handleResourceIdentifierChange($event)\"\n ></gn-ui-form-field-simple>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceCreated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceUpdated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'updateFrequency'\">\n <gn-ui-form-field-update-frequency\n [value]=\"valueAsUpdateFrequency\"\n (valueChange)=\"valueChange.emit($event)\"\n [recordKind]=\"recordKind\"\n ></gn-ui-form-field-update-frequency>\n </ng-container>\n <ng-container *ngSwitchCase=\"'associatedRecords'\">\n <gn-ui-form-field-associated-records\n [value]=\"valueAsAssociatedRecords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-associated-records>\n </ng-container>\n <ng-container *ngSwitchCase=\"'temporalExtents'\">\n <gn-ui-form-field-temporal-extents\n [value]=\"valueAsTemporalExtents\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-temporal-extents>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spatialExtents'\">\n <gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>\n </ng-container>\n <ng-container *ngSwitchCase=\"'keywords'\">\n <gn-ui-form-field-keywords\n [value]=\"valueAsKeywords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-keywords>\n </ng-container>\n <ng-container *ngSwitchCase=\"'topics'\">\n <gn-ui-form-field-topics\n [value]=\"valueAsTopics\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-topics>\n </ng-container>\n <ng-container *ngSwitchCase=\"'licenses'\">\n <gn-ui-form-field-license\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [recordLicences]=\"valueAsConstraints\"\n (recordLicencesChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-license>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'legalConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'securityConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'otherConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container\n ></ng-container>\n <ng-template #formFieldConstraints>\n <gn-ui-form-field-constraints\n [label]=\"config.labelKey\"\n [value]=\"valueAsConstraints\"\n [constraintType]=\"model\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-constraints\n ></ng-template>\n\n <ng-container *ngSwitchCase=\"'contactsForResource'\">\n <gn-ui-form-field-contacts-for-resource\n [value]=\"valueAsIndividuals\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts-for-resource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'contacts'\">\n <gn-ui-form-field-contacts\n [value]=\"valueAsIndividuals\"\n [modelSpecifier]=\"modelSpecifier\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:!link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-link-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-link-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-single-link-resource\n *ngIf=\"modelSpecifier === 'onlineResourceType:singleLink'\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-single-link-resource>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"!model\">\n <ng-container [ngSwitch]=\"componentName\">\n <ng-container *ngSwitchCase=\"'form-field-constraints-shortcuts'\">\n <gn-ui-form-field-constraints-shortcuts></gn-ui-form-field-constraints-shortcuts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'form-field-spatial-toggle'\">\n <gn-ui-form-field-spatial-toggle></gn-ui-form-field-spatial-toggle>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n", styles: [":host{scroll-margin-top:90px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FormFieldWrapperComponent, selector: "gn-ui-form-field-wrapper", inputs: ["label", "hint"] }, { kind: "component", type: FormFieldLicenseComponent, selector: "gn-ui-form-field-license", inputs: ["label", "recordLicences"], outputs: ["recordLicencesChange"] }, { kind: "component", type: FormFieldDateComponent, selector: "gn-ui-form-field-date", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldUpdateFrequencyComponent, selector: "gn-ui-form-field-update-frequency", inputs: ["value", "recordKind"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldAssociatedRecordsComponent, selector: "gn-ui-form-field-associated-records", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldTemporalExtentsComponent, selector: "gn-ui-form-field-temporal-extents", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldSimpleComponent, selector: "gn-ui-form-field-simple", inputs: ["type", "readonly", "invalid", "placeholder", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldRichComponent, selector: "gn-ui-form-field-rich", inputs: ["label", "hint", "placeholder", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldSpatialExtentComponent, selector: "gn-ui-form-field-spatial-extent" }, { kind: "component", type: FormFieldKeywordsComponent, selector: "gn-ui-form-field-keywords", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOverviewsComponent, selector: "gn-ui-form-field-overviews", inputs: ["metadataUuid", "recordKind", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldContactsForResourceComponent, selector: "gn-ui-form-field-contacts-for-resource", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineResourcesComponent, selector: "gn-ui-form-field-online-resources", inputs: ["metadataUuid", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineLinkResourcesComponent, selector: "gn-ui-form-field-online-link-resources", inputs: ["metadataUuid", "value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldOnlineSingleLinkResourceComponent, selector: "gn-ui-form-field-online-single-link-resource", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldContactsComponent, selector: "gn-ui-form-field-contacts", inputs: ["value", "modelSpecifier"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldConstraintsComponent, selector: "gn-ui-form-field-constraints", inputs: ["label", "value", "constraintType"], outputs: ["valueChange"] }, { kind: "component", type: FormFieldConstraintsShortcutsComponent, selector: "gn-ui-form-field-constraints-shortcuts" }, { kind: "component", type: FormFieldSpatialToggleComponent, selector: "gn-ui-form-field-spatial-toggle" }, { kind: "component", type: FormFieldTopicsComponent, selector: "gn-ui-form-field-topics", inputs: ["value"], outputs: ["valueChange"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "directive", type: i4$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
39250
39952
|
}
|
|
39251
39953
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
39252
39954
|
type: Component,
|
|
@@ -39258,6 +39960,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39258
39960
|
FormFieldLicenseComponent,
|
|
39259
39961
|
FormFieldDateComponent,
|
|
39260
39962
|
FormFieldUpdateFrequencyComponent,
|
|
39963
|
+
FormFieldAssociatedRecordsComponent,
|
|
39261
39964
|
FormFieldTemporalExtentsComponent,
|
|
39262
39965
|
FormFieldSimpleComponent,
|
|
39263
39966
|
FormFieldRichComponent,
|
|
@@ -39275,7 +39978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39275
39978
|
FormFieldTopicsComponent,
|
|
39276
39979
|
TextFieldModule,
|
|
39277
39980
|
NgIconComponent,
|
|
39278
|
-
], providers: [provideIcons({ matEditOutline, matHelpOutline })], hostDirectives: [FieldFocusDirective], template: "<!-- TEMPORARY - disabling the open data switch -->\n<!-- <ng-container *ngIf=\"model === 'licenses'\">\n <gn-ui-form-field-open-data\n [value]=\"valueAsConstraints\"\n (valueChange)=\"valueChange.emit($event)\"\n (openDataChange)=\"toggleIsOpenData($event)\"\n ></gn-ui-form-field-open-data>\n</ng-container> -->\n<div class=\"flex flex-col h-full\">\n <ng-container *ngIf=\"withoutWrapper; else withGenericWrapper\">\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </ng-container>\n <ng-template #withGenericWrapper>\n <gn-ui-form-field-wrapper\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n >\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </gn-ui-form-field-wrapper>\n </ng-template>\n</div>\n\n<ng-template #fieldContent>\n <ng-container [ngSwitch]=\"model\">\n <ng-container *ngSwitchCase=\"'title'\">\n <div class=\"flex flex-row flex-start items-center gap-3 mb-[12px]\">\n <textarea\n #titleInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n data-test=\"recordTitleInput\"\n class=\"grow font-title text-3xl font-normal overflow-hidden text-black/80\"\n [value]=\"valueAsString\"\n (change)=\"valueChange.emit($event.target.value)\"\n [placeholder]=\"\n 'editor.record.form.field.title.placeholder'\n | translate: { recordKind }\n \"\n ></textarea>\n <div class=\"flex flex-row justify-between self-start mt-0.5\">\n <ng-icon\n name=\"matEditOutline\"\n size=\"16\"\n class=\"m-2 cursor-pointer\"\n (click)=\"focusTitleInput()\"\n ></ng-icon>\n <ng-icon\n *ngIf=\"config.hintKey\"\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"config.hintKey! | translate: { recordKind }\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'abstract'\">\n <gn-ui-form-field-rich\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n [value]=\"valueAsString\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-rich>\n </ng-container>\n <ng-container *ngSwitchCase=\"'overviews'\">\n <gn-ui-form-field-overviews\n [metadataUuid]=\"uniqueIdentifier\"\n [recordKind]=\"recordKind\"\n [value]=\"valueAsOverviews\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-overviews>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceIdentifiers'\">\n <gn-ui-form-field-simple\n [type]=\"'text'\"\n [value]=\"valueAsResourceIdentifierCode\"\n (valueChange)=\"handleResourceIdentifierChange($event)\"\n ></gn-ui-form-field-simple>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceCreated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceUpdated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'updateFrequency'\">\n <gn-ui-form-field-update-frequency\n [value]=\"valueAsUpdateFrequency\"\n (valueChange)=\"valueChange.emit($event)\"\n [recordKind]=\"recordKind\"\n ></gn-ui-form-field-update-frequency>\n </ng-container>\n <ng-container *ngSwitchCase=\"'temporalExtents'\">\n <gn-ui-form-field-temporal-extents\n [value]=\"valueAsTemporalExtents\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-temporal-extents>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spatialExtents'\">\n <gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>\n </ng-container>\n <ng-container *ngSwitchCase=\"'keywords'\">\n <gn-ui-form-field-keywords\n [value]=\"valueAsKeywords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-keywords>\n </ng-container>\n <ng-container *ngSwitchCase=\"'topics'\">\n <gn-ui-form-field-topics\n [value]=\"valueAsTopics\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-topics>\n </ng-container>\n <ng-container *ngSwitchCase=\"'licenses'\">\n <gn-ui-form-field-license\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [recordLicences]=\"valueAsConstraints\"\n (recordLicencesChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-license>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'legalConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'securityConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'otherConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container\n ></ng-container>\n <ng-template #formFieldConstraints>\n <gn-ui-form-field-constraints\n [label]=\"config.labelKey\"\n [value]=\"valueAsConstraints\"\n [constraintType]=\"model\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-constraints\n ></ng-template>\n\n <ng-container *ngSwitchCase=\"'contactsForResource'\">\n <gn-ui-form-field-contacts-for-resource\n [value]=\"valueAsIndividuals\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts-for-resource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'contacts'\">\n <gn-ui-form-field-contacts\n [value]=\"valueAsIndividuals\"\n [modelSpecifier]=\"modelSpecifier\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:!link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-link-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-link-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-single-link-resource\n *ngIf=\"modelSpecifier === 'onlineResourceType:singleLink'\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-single-link-resource>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"!model\">\n <ng-container [ngSwitch]=\"componentName\">\n <ng-container *ngSwitchCase=\"'form-field-constraints-shortcuts'\">\n <gn-ui-form-field-constraints-shortcuts></gn-ui-form-field-constraints-shortcuts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'form-field-spatial-toggle'\">\n <gn-ui-form-field-spatial-toggle></gn-ui-form-field-spatial-toggle>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n", styles: [":host{scroll-margin-top:90px}\n"] }]
|
|
39981
|
+
], providers: [provideIcons({ matEditOutline, matHelpOutline })], hostDirectives: [FieldFocusDirective], template: "<!-- TEMPORARY - disabling the open data switch -->\n<!-- <ng-container *ngIf=\"model === 'licenses'\">\n <gn-ui-form-field-open-data\n [value]=\"valueAsConstraints\"\n (valueChange)=\"valueChange.emit($event)\"\n (openDataChange)=\"toggleIsOpenData($event)\"\n ></gn-ui-form-field-open-data>\n</ng-container> -->\n<div class=\"flex flex-col h-full\">\n <ng-container *ngIf=\"withoutWrapper; else withGenericWrapper\">\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </ng-container>\n <ng-template #withGenericWrapper>\n <gn-ui-form-field-wrapper\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n >\n <ng-container *ngTemplateOutlet=\"fieldContent\"></ng-container>\n </gn-ui-form-field-wrapper>\n </ng-template>\n</div>\n\n<ng-template #fieldContent>\n <ng-container [ngSwitch]=\"model\">\n <ng-container *ngSwitchCase=\"'title'\">\n <div class=\"flex flex-row flex-start items-center gap-3 mb-[12px]\">\n <textarea\n #titleInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n data-test=\"recordTitleInput\"\n class=\"grow font-title text-3xl font-normal overflow-hidden text-black/80\"\n [value]=\"valueAsString\"\n (change)=\"valueChange.emit($event.target.value)\"\n [placeholder]=\"\n 'editor.record.form.field.title.placeholder'\n | translate: { recordKind }\n \"\n ></textarea>\n <div class=\"flex flex-row justify-between self-start mt-0.5\">\n <ng-icon\n name=\"matEditOutline\"\n size=\"16\"\n class=\"m-2 cursor-pointer\"\n (click)=\"focusTitleInput()\"\n ></ng-icon>\n <ng-icon\n *ngIf=\"config.hintKey\"\n name=\"matHelpOutline\"\n size=\"16\"\n class=\"m-2\"\n [matTooltip]=\"config.hintKey! | translate: { recordKind }\"\n matTooltipPosition=\"above\"\n ></ng-icon>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'abstract'\">\n <gn-ui-form-field-rich\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [hint]=\"config.hintKey! | translate: { recordKind }\"\n [value]=\"valueAsString\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-rich>\n </ng-container>\n <ng-container *ngSwitchCase=\"'overviews'\">\n <gn-ui-form-field-overviews\n [metadataUuid]=\"uniqueIdentifier\"\n [recordKind]=\"recordKind\"\n [value]=\"valueAsOverviews\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-overviews>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceIdentifiers'\">\n <gn-ui-form-field-simple\n [type]=\"'text'\"\n [value]=\"valueAsResourceIdentifierCode\"\n (valueChange)=\"handleResourceIdentifierChange($event)\"\n ></gn-ui-form-field-simple>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceCreated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'resourceUpdated'\">\n <gn-ui-form-field-date\n [value]=\"valueAsDate\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-date>\n </ng-container>\n <ng-container *ngSwitchCase=\"'updateFrequency'\">\n <gn-ui-form-field-update-frequency\n [value]=\"valueAsUpdateFrequency\"\n (valueChange)=\"valueChange.emit($event)\"\n [recordKind]=\"recordKind\"\n ></gn-ui-form-field-update-frequency>\n </ng-container>\n <ng-container *ngSwitchCase=\"'associatedRecords'\">\n <gn-ui-form-field-associated-records\n [value]=\"valueAsAssociatedRecords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-associated-records>\n </ng-container>\n <ng-container *ngSwitchCase=\"'temporalExtents'\">\n <gn-ui-form-field-temporal-extents\n [value]=\"valueAsTemporalExtents\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-temporal-extents>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spatialExtents'\">\n <gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>\n </ng-container>\n <ng-container *ngSwitchCase=\"'keywords'\">\n <gn-ui-form-field-keywords\n [value]=\"valueAsKeywords\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-keywords>\n </ng-container>\n <ng-container *ngSwitchCase=\"'topics'\">\n <gn-ui-form-field-topics\n [value]=\"valueAsTopics\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-topics>\n </ng-container>\n <ng-container *ngSwitchCase=\"'licenses'\">\n <gn-ui-form-field-license\n [label]=\"config.labelKey! | translate: { recordKind }\"\n [recordLicences]=\"valueAsConstraints\"\n (recordLicencesChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-license>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'legalConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'securityConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'otherConstraints'\">\n <ng-container *ngTemplateOutlet=\"formFieldConstraints\"></ng-container\n ></ng-container>\n <ng-template #formFieldConstraints>\n <gn-ui-form-field-constraints\n [label]=\"config.labelKey\"\n [value]=\"valueAsConstraints\"\n [constraintType]=\"model\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-constraints\n ></ng-template>\n\n <ng-container *ngSwitchCase=\"'contactsForResource'\">\n <gn-ui-form-field-contacts-for-resource\n [value]=\"valueAsIndividuals\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts-for-resource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'contacts'\">\n <gn-ui-form-field-contacts\n [value]=\"valueAsIndividuals\"\n [modelSpecifier]=\"modelSpecifier\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-contacts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:!link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-link-resources\n *ngIf=\"modelSpecifier === 'onlineResourceType:link'\"\n [metadataUuid]=\"uniqueIdentifier\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-link-resources>\n </ng-container>\n <ng-container *ngSwitchCase=\"'onlineResources'\">\n <gn-ui-form-field-online-single-link-resource\n *ngIf=\"modelSpecifier === 'onlineResourceType:singleLink'\"\n [value]=\"valueAsOnlineResources\"\n (valueChange)=\"valueChange.emit($event)\"\n ></gn-ui-form-field-online-single-link-resource>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"!model\">\n <ng-container [ngSwitch]=\"componentName\">\n <ng-container *ngSwitchCase=\"'form-field-constraints-shortcuts'\">\n <gn-ui-form-field-constraints-shortcuts></gn-ui-form-field-constraints-shortcuts>\n </ng-container>\n <ng-container *ngSwitchCase=\"'form-field-spatial-toggle'\">\n <gn-ui-form-field-spatial-toggle></gn-ui-form-field-spatial-toggle>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n", styles: [":host{scroll-margin-top:90px}\n"] }]
|
|
39279
39982
|
}], propDecorators: { uniqueIdentifier: [{
|
|
39280
39983
|
type: Input
|
|
39281
39984
|
}], recordKind: [{
|
|
@@ -39860,7 +40563,7 @@ class RouterService {
|
|
|
39860
40563
|
return ROUTER_ROUTE_ORGANIZATION;
|
|
39861
40564
|
}
|
|
39862
40565
|
getDefaultSort() {
|
|
39863
|
-
return SortByEnum.
|
|
40566
|
+
return SortByEnum.RESOURCE_DATE;
|
|
39864
40567
|
}
|
|
39865
40568
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39866
40569
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, providedIn: 'root' }); }
|
|
@@ -39920,7 +40623,7 @@ function flattenQueryParams(params) {
|
|
|
39920
40623
|
const start = flattened[key].start;
|
|
39921
40624
|
const end = flattened[key].end;
|
|
39922
40625
|
flattened[key] = [
|
|
39923
|
-
`${start ? formatDate(start) : ''}..${formatDate(end)
|
|
40626
|
+
`${start ? formatDate(start) : ''}..${end ? formatDate(end) : ''}`,
|
|
39924
40627
|
];
|
|
39925
40628
|
}
|
|
39926
40629
|
}
|
|
@@ -40277,5 +40980,5 @@ const CHART_TYPE_VALUES = [
|
|
|
40277
40980
|
* Generated bundle index. Do not edit.
|
|
40278
40981
|
*/
|
|
40279
40982
|
|
|
40280
|
-
export { ADD_RESULTS, ADD_SEARCH, AVAILABLE_LICENSES, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, 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_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, 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, 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, isConfigLoaded, isDateRange, 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, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, 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 };
|
|
40983
|
+
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, 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, 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 };
|
|
40281
40984
|
//# sourceMappingURL=geonetwork-ui.mjs.map
|