geonetwork-ui 2.11.0-dev.a2881de31 → 2.11.0-dev.a5c259d9e
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 +1208 -714
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +170 -61
- package/index.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +5 -5
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +5 -5
- 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/metadata-converter/src/lib/iso19115-3/write-parts.ts +2 -2
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +9 -5
- package/src/libs/api/metadata-converter/src/lib/iso19139/utils/association-type.mapper.ts +12 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +2 -2
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +23 -3
- 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 +40 -2
- 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.css +0 -0
- 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/lib/add-layer-from-file/add-layer-from-file.component.html +1 -0
- 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/search/src/lib/filter-dropdown/filter-dropdown.component.html +7 -0
- package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.ts +39 -0
- 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 +3 -1
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +16 -1
- 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/inputs/src/index.ts +1 -0
- 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/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 +117 -0
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.ts +191 -0
- package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +4 -5
- package/src/libs/util/app-config/src/lib/app-config.ts +3 -0
- package/src/libs/util/app-config/src/lib/model.ts +1 -0
- 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/lib/utils/file.ts +15 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/tailwind.base.css +5 -0
- package/translations/de.json +23 -1
- package/translations/en.json +23 -1
- package/translations/es.json +22 -0
- package/translations/fr.json +23 -1
- package/translations/it.json +23 -1
- package/translations/nl.json +22 -0
- package/translations/pt.json +22 -0
- package/translations/sk.json +23 -1
- package/src/libs/util/data-fetcher/src/lib/readers/base-cache.ts +0 -14
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { parseXml, XmlDocument, XmlElement, XmlText } from '@rgrove/parse-xml';
|
|
2
2
|
export { XmlDocument, XmlElement } from '@rgrove/parse-xml';
|
|
3
|
+
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
|
|
3
4
|
import GML32 from 'ol/format/GML32.js';
|
|
4
5
|
import GeoJSON from 'ol/format/GeoJSON.js';
|
|
5
6
|
import { parse as parse$1 } from 'ol/xml.js';
|
|
6
|
-
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
|
|
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, takeUntil, EMPTY, mergeMap as mergeMap$1, withLatestFrom as withLatestFrom$1 } from 'rxjs';
|
|
10
10
|
import * as i0 from '@angular/core';
|
|
11
11
|
import { InjectionToken, inject, Injectable, NgModule, Injector, provideAppInitializer, makeEnvironmentProviders, ElementRef, HostListener, Input, Directive, Renderer2, DestroyRef, EventEmitter, Output, ViewChild, ChangeDetectionStrategy, Component, ViewEncapsulation, ChangeDetectorRef, HostBinding, ViewContainerRef, TemplateRef, ViewChildren, ContentChild, input, output, signal, viewChild, computed, ContentChildren, NgZone, ComponentFactoryResolver, afterNextRender, viewChildren } from '@angular/core';
|
|
12
12
|
import { HttpClient, HttpHeaders, HttpParams, HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi, HttpEventType } from '@angular/common/http';
|
|
@@ -41,7 +41,7 @@ import * as TOML from '@ltd/j-toml';
|
|
|
41
41
|
import { Style, Stroke, Fill, Circle } from 'ol/style.js';
|
|
42
42
|
import CircleStyle from 'ol/style/Circle.js';
|
|
43
43
|
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,
|
|
44
|
+
import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, iconoirTrash, iconoirSquareDashed, iconoirImport, iconoirCheckCircle, iconoirReduce, iconoirNavArrowUp, iconoirNavArrowDown, iconoirExpand, iconoirSettings, iconoirDownload, iconoirPlus, iconoirBin, iconoirMediaImageXmark, iconoirMediaImage, iconoirAppWindow, iconoirCode, iconoirDatabase, iconoirAppleWallet, iconoirBank, iconoirList, iconoirTranslate, iconoirLock, iconoirUser, iconoirArrowLeft, iconoirLightBulbOn, iconoirBadgeCheck, iconoirSystemShut, iconoirCircle, iconoirAttachment, iconoirRefresh } from '@ng-icons/iconoir';
|
|
45
45
|
import { MatButtonModule } from '@angular/material/button';
|
|
46
46
|
import * as i1$8 from '@angular/cdk/overlay';
|
|
47
47
|
import { OverlayContainer, ScrollStrategyOptions, OverlayModule, CdkConnectedOverlay, ScrollDispatcher, Overlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
|
@@ -61,7 +61,7 @@ import { DateAdapter, MatNativeDateModule, MAT_DATE_LOCALE } from '@angular/mate
|
|
|
61
61
|
import * as i1$6 from '@angular/material/datepicker';
|
|
62
62
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
63
63
|
import * as i1$7 from 'ngx-dropzone';
|
|
64
|
-
import { NgxDropzoneModule } from 'ngx-dropzone';
|
|
64
|
+
import { NgxDropzoneModule, NgxDropzoneComponent } from 'ngx-dropzone';
|
|
65
65
|
import * as i1$9 from '@angular/material/button-toggle';
|
|
66
66
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
67
67
|
import { moveItemInArray, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
|
@@ -79,10 +79,10 @@ import { ScrollingModule, CdkScrollable } from '@angular/cdk/scrolling';
|
|
|
79
79
|
import Duration from 'duration-relativetimeformat';
|
|
80
80
|
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
|
81
81
|
import { trigger, transition, animate, keyframes, style } from '@angular/animations';
|
|
82
|
-
import * as
|
|
83
|
-
import {
|
|
84
|
-
import
|
|
85
|
-
import
|
|
82
|
+
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
83
|
+
import { Vector, DataType } from 'apache-arrow';
|
|
84
|
+
import WFS from 'ol/format/WFS';
|
|
85
|
+
import GeoJSON$1 from 'ol/format/GeoJSON';
|
|
86
86
|
import { Chart, BarController, BarElement, CategoryScale, LinearScale, LineController, LineElement, PointElement, PieController, ArcElement, ScatterController, Tooltip, Colors, Legend } from 'chart.js';
|
|
87
87
|
import * as i2$4 from '@angular/material/sort';
|
|
88
88
|
import { MatSortModule, MatSort } from '@angular/material/sort';
|
|
@@ -90,7 +90,6 @@ import * as i1$b from '@angular/material/table';
|
|
|
90
90
|
import { MatTableModule } from '@angular/material/table';
|
|
91
91
|
import * as i3 from '@angular/material/paginator';
|
|
92
92
|
import { MatPaginatorIntl, MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
|
|
93
|
-
import { LetDirective } from '@ngrx/component';
|
|
94
93
|
import { Meta } from '@angular/platform-browser';
|
|
95
94
|
import { tablerFolderOpen } from '@ng-icons/tabler-icons';
|
|
96
95
|
import * as i3$1 from '@angular/material/radio';
|
|
@@ -674,6 +673,149 @@ function matchMimeType(format) {
|
|
|
674
673
|
return format || null;
|
|
675
674
|
}
|
|
676
675
|
|
|
676
|
+
const RoleValues = [
|
|
677
|
+
'unspecified',
|
|
678
|
+
'other',
|
|
679
|
+
'author', // Party who authored the resource
|
|
680
|
+
'collaborator', // party who assists with the generation of the resource other than the principal investigator
|
|
681
|
+
'contributor', // party contributing to the resource
|
|
682
|
+
'custodian', // Party that accepts accountability and responsibility for the data and ensures appropriate care and maintenance of the resource
|
|
683
|
+
'distributor', // Party who distributes the resource
|
|
684
|
+
'editor', // party who reviewed or modified the resource to improve the content
|
|
685
|
+
'funder', // party providing monetary support for the resource
|
|
686
|
+
'mediator', // a class of entity that mediates access to the resource and for whom the resource is intended or useful
|
|
687
|
+
'originator', // Party who created the resource
|
|
688
|
+
'owner', // Party that owns the resource
|
|
689
|
+
'point_of_contact', // Party who can be contacted for acquiring knowledge about or acquisition of the resource
|
|
690
|
+
'principal_investigator', // Key party responsible for gathering information and conducting research
|
|
691
|
+
'processor', // Party who has processed the data in a manner such that the resource has been modified
|
|
692
|
+
'publisher', // Party who published the resource
|
|
693
|
+
'resource_provider', // Party that supplies the resource
|
|
694
|
+
'rights_holder', // party owning or managing rights over the resource
|
|
695
|
+
'sponsor', // party that sponsors the resource
|
|
696
|
+
'stakeholder', // party who has an interest in the resource or the use of the resource
|
|
697
|
+
'user', // Party who uses the resource
|
|
698
|
+
];
|
|
699
|
+
const RoleLabels = new Map([
|
|
700
|
+
['unspecified', marker('domain.contact.role.unspecified')],
|
|
701
|
+
['other', marker('domain.contact.role.other')],
|
|
702
|
+
['author', marker('domain.contact.role.author')],
|
|
703
|
+
['collaborator', marker('domain.contact.role.collaborator')],
|
|
704
|
+
['contributor', marker('domain.contact.role.contributor')],
|
|
705
|
+
['custodian', marker('domain.contact.role.custodian')],
|
|
706
|
+
['distributor', marker('domain.contact.role.distributor')],
|
|
707
|
+
['editor', marker('domain.contact.role.editor')],
|
|
708
|
+
['funder', marker('domain.contact.role.funder')],
|
|
709
|
+
['mediator', marker('domain.contact.role.mediator')],
|
|
710
|
+
['originator', marker('domain.contact.role.originator')],
|
|
711
|
+
['owner', marker('domain.contact.role.owner')],
|
|
712
|
+
['point_of_contact', marker('domain.contact.role.point_of_contact')],
|
|
713
|
+
[
|
|
714
|
+
'principal_investigator',
|
|
715
|
+
marker('domain.contact.role.principal_investigator'),
|
|
716
|
+
],
|
|
717
|
+
['processor', marker('domain.contact.role.processor')],
|
|
718
|
+
['publisher', marker('domain.contact.role.publisher')],
|
|
719
|
+
['resource_provider', marker('domain.contact.role.resource_provider')],
|
|
720
|
+
['rights_holder', marker('domain.contact.role.rights_holder')],
|
|
721
|
+
['sponsor', marker('domain.contact.role.sponsor')],
|
|
722
|
+
['stakeholder', marker('domain.contact.role.stakeholder')],
|
|
723
|
+
['user', marker('domain.contact.role.user')],
|
|
724
|
+
]);
|
|
725
|
+
|
|
726
|
+
marker('domain.record.updateFrequency.unknown');
|
|
727
|
+
marker('domain.record.updateFrequency.notPlanned');
|
|
728
|
+
marker('domain.record.updateFrequency.asNeeded');
|
|
729
|
+
marker('domain.record.updateFrequency.irregular');
|
|
730
|
+
marker('domain.record.updateFrequency.continual');
|
|
731
|
+
marker('domain.record.updateFrequency.periodic');
|
|
732
|
+
const updateFrequencyCodeValues = [
|
|
733
|
+
'unknown',
|
|
734
|
+
'notPlanned',
|
|
735
|
+
'asNeeded',
|
|
736
|
+
'irregular',
|
|
737
|
+
'continual',
|
|
738
|
+
'periodic',
|
|
739
|
+
'daily',
|
|
740
|
+
'weekly',
|
|
741
|
+
'fortnightly',
|
|
742
|
+
'semimonthly',
|
|
743
|
+
'monthly',
|
|
744
|
+
'quarterly',
|
|
745
|
+
'biannually',
|
|
746
|
+
'annually',
|
|
747
|
+
'biennially',
|
|
748
|
+
];
|
|
749
|
+
marker('domain.record.updateFrequency.day');
|
|
750
|
+
marker('domain.record.updateFrequency.week');
|
|
751
|
+
marker('domain.record.updateFrequency.month');
|
|
752
|
+
marker('domain.record.updateFrequency.year');
|
|
753
|
+
marker('domain.record.updateFrequency.daily');
|
|
754
|
+
marker('domain.record.updateFrequency.weekly');
|
|
755
|
+
marker('domain.record.updateFrequency.fortnightly');
|
|
756
|
+
marker('domain.record.updateFrequency.monthly');
|
|
757
|
+
marker('domain.record.updateFrequency.quarterly');
|
|
758
|
+
marker('domain.record.updateFrequency.biannually');
|
|
759
|
+
marker('domain.record.updateFrequency.annually');
|
|
760
|
+
marker('domain.record.updateFrequency.semimonthly');
|
|
761
|
+
marker('domain.record.updateFrequency.biennially');
|
|
762
|
+
marker('domain.record.status.completed');
|
|
763
|
+
marker('domain.record.status.ongoing');
|
|
764
|
+
marker('domain.record.status.under_development');
|
|
765
|
+
marker('domain.record.status.deprecated');
|
|
766
|
+
marker('domain.record.status.removed');
|
|
767
|
+
marker('domain.record.status.planned');
|
|
768
|
+
marker('domain.record.status.required');
|
|
769
|
+
const RecordStatusValues = [
|
|
770
|
+
'completed',
|
|
771
|
+
'ongoing',
|
|
772
|
+
'under_development',
|
|
773
|
+
'deprecated',
|
|
774
|
+
'removed',
|
|
775
|
+
'planned',
|
|
776
|
+
'required',
|
|
777
|
+
];
|
|
778
|
+
marker('record.metadata.api.accessServiceProtocol.wms');
|
|
779
|
+
marker('record.metadata.api.accessServiceProtocol.wfs');
|
|
780
|
+
marker('record.metadata.api.accessServiceProtocol.wps');
|
|
781
|
+
marker('record.metadata.api.accessServiceProtocol.wmts');
|
|
782
|
+
marker('record.metadata.api.accessServiceProtocol.esriRest');
|
|
783
|
+
marker('record.metadata.api.accessServiceProtocol.ogcFeatures');
|
|
784
|
+
marker('record.metadata.api.accessServiceProtocol.GPFDL');
|
|
785
|
+
marker('record.metadata.api.accessServiceProtocol.tms');
|
|
786
|
+
marker('record.metadata.api.accessServiceProtocol.maplibre-style');
|
|
787
|
+
marker('record.metadata.api.accessServiceProtocol.postgis');
|
|
788
|
+
marker('record.metadata.api.accessServiceProtocol.stac');
|
|
789
|
+
marker('record.metadata.api.accessServiceProtocol.other');
|
|
790
|
+
marker('domain.record.associationType.crossReference');
|
|
791
|
+
marker('domain.record.associationType.largerWorkCitation');
|
|
792
|
+
marker('domain.record.associationType.partOfSeamlessDatabase');
|
|
793
|
+
marker('domain.record.associationType.stereoMate');
|
|
794
|
+
marker('domain.record.associationType.isComposedOf');
|
|
795
|
+
marker('domain.record.associationType.collectiveTitle');
|
|
796
|
+
marker('domain.record.associationType.series');
|
|
797
|
+
marker('domain.record.associationType.dependency');
|
|
798
|
+
marker('domain.record.associationType.revisionOf');
|
|
799
|
+
// DS_AssociationTypeCode values of the ISO19115-3 codelist, any unrecognized value
|
|
800
|
+
// being mapped to 'crossReference'
|
|
801
|
+
const associationTypeValues = [
|
|
802
|
+
'crossReference',
|
|
803
|
+
'largerWorkCitation',
|
|
804
|
+
'partOfSeamlessDatabase',
|
|
805
|
+
'stereoMate',
|
|
806
|
+
'isComposedOf',
|
|
807
|
+
'collectiveTitle',
|
|
808
|
+
'series',
|
|
809
|
+
'dependency',
|
|
810
|
+
'revisionOf',
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
function getAssociationTypeFromCode(associationTypeCode) {
|
|
814
|
+
return associationTypeValues.includes(associationTypeCode)
|
|
815
|
+
? associationTypeCode
|
|
816
|
+
: 'crossReference';
|
|
817
|
+
}
|
|
818
|
+
|
|
677
819
|
function readGeometry(el) {
|
|
678
820
|
const xmlDoc = createDocument(el);
|
|
679
821
|
xmlDoc.root.attributes['xmlns'] = 'http://www.opengis.net/gml/3.2';
|
|
@@ -802,121 +944,6 @@ function getStatusFromStatusCode(statusCode) {
|
|
|
802
944
|
}
|
|
803
945
|
}
|
|
804
946
|
|
|
805
|
-
const RoleValues = [
|
|
806
|
-
'unspecified',
|
|
807
|
-
'other',
|
|
808
|
-
'author', // Party who authored the resource
|
|
809
|
-
'collaborator', // party who assists with the generation of the resource other than the principal investigator
|
|
810
|
-
'contributor', // party contributing to the resource
|
|
811
|
-
'custodian', // Party that accepts accountability and responsibility for the data and ensures appropriate care and maintenance of the resource
|
|
812
|
-
'distributor', // Party who distributes the resource
|
|
813
|
-
'editor', // party who reviewed or modified the resource to improve the content
|
|
814
|
-
'funder', // party providing monetary support for the resource
|
|
815
|
-
'mediator', // a class of entity that mediates access to the resource and for whom the resource is intended or useful
|
|
816
|
-
'originator', // Party who created the resource
|
|
817
|
-
'owner', // Party that owns the resource
|
|
818
|
-
'point_of_contact', // Party who can be contacted for acquiring knowledge about or acquisition of the resource
|
|
819
|
-
'principal_investigator', // Key party responsible for gathering information and conducting research
|
|
820
|
-
'processor', // Party who has processed the data in a manner such that the resource has been modified
|
|
821
|
-
'publisher', // Party who published the resource
|
|
822
|
-
'resource_provider', // Party that supplies the resource
|
|
823
|
-
'rights_holder', // party owning or managing rights over the resource
|
|
824
|
-
'sponsor', // party that sponsors the resource
|
|
825
|
-
'stakeholder', // party who has an interest in the resource or the use of the resource
|
|
826
|
-
'user', // Party who uses the resource
|
|
827
|
-
];
|
|
828
|
-
const RoleLabels = new Map([
|
|
829
|
-
['unspecified', marker('domain.contact.role.unspecified')],
|
|
830
|
-
['other', marker('domain.contact.role.other')],
|
|
831
|
-
['author', marker('domain.contact.role.author')],
|
|
832
|
-
['collaborator', marker('domain.contact.role.collaborator')],
|
|
833
|
-
['contributor', marker('domain.contact.role.contributor')],
|
|
834
|
-
['custodian', marker('domain.contact.role.custodian')],
|
|
835
|
-
['distributor', marker('domain.contact.role.distributor')],
|
|
836
|
-
['editor', marker('domain.contact.role.editor')],
|
|
837
|
-
['funder', marker('domain.contact.role.funder')],
|
|
838
|
-
['mediator', marker('domain.contact.role.mediator')],
|
|
839
|
-
['originator', marker('domain.contact.role.originator')],
|
|
840
|
-
['owner', marker('domain.contact.role.owner')],
|
|
841
|
-
['point_of_contact', marker('domain.contact.role.point_of_contact')],
|
|
842
|
-
[
|
|
843
|
-
'principal_investigator',
|
|
844
|
-
marker('domain.contact.role.principal_investigator'),
|
|
845
|
-
],
|
|
846
|
-
['processor', marker('domain.contact.role.processor')],
|
|
847
|
-
['publisher', marker('domain.contact.role.publisher')],
|
|
848
|
-
['resource_provider', marker('domain.contact.role.resource_provider')],
|
|
849
|
-
['rights_holder', marker('domain.contact.role.rights_holder')],
|
|
850
|
-
['sponsor', marker('domain.contact.role.sponsor')],
|
|
851
|
-
['stakeholder', marker('domain.contact.role.stakeholder')],
|
|
852
|
-
['user', marker('domain.contact.role.user')],
|
|
853
|
-
]);
|
|
854
|
-
|
|
855
|
-
marker('domain.record.updateFrequency.unknown');
|
|
856
|
-
marker('domain.record.updateFrequency.notPlanned');
|
|
857
|
-
marker('domain.record.updateFrequency.asNeeded');
|
|
858
|
-
marker('domain.record.updateFrequency.irregular');
|
|
859
|
-
marker('domain.record.updateFrequency.continual');
|
|
860
|
-
marker('domain.record.updateFrequency.periodic');
|
|
861
|
-
const updateFrequencyCodeValues = [
|
|
862
|
-
'unknown',
|
|
863
|
-
'notPlanned',
|
|
864
|
-
'asNeeded',
|
|
865
|
-
'irregular',
|
|
866
|
-
'continual',
|
|
867
|
-
'periodic',
|
|
868
|
-
'daily',
|
|
869
|
-
'weekly',
|
|
870
|
-
'fortnightly',
|
|
871
|
-
'semimonthly',
|
|
872
|
-
'monthly',
|
|
873
|
-
'quarterly',
|
|
874
|
-
'biannually',
|
|
875
|
-
'annually',
|
|
876
|
-
'biennially',
|
|
877
|
-
];
|
|
878
|
-
marker('domain.record.updateFrequency.day');
|
|
879
|
-
marker('domain.record.updateFrequency.week');
|
|
880
|
-
marker('domain.record.updateFrequency.month');
|
|
881
|
-
marker('domain.record.updateFrequency.year');
|
|
882
|
-
marker('domain.record.updateFrequency.daily');
|
|
883
|
-
marker('domain.record.updateFrequency.weekly');
|
|
884
|
-
marker('domain.record.updateFrequency.fortnightly');
|
|
885
|
-
marker('domain.record.updateFrequency.monthly');
|
|
886
|
-
marker('domain.record.updateFrequency.quarterly');
|
|
887
|
-
marker('domain.record.updateFrequency.biannually');
|
|
888
|
-
marker('domain.record.updateFrequency.annually');
|
|
889
|
-
marker('domain.record.updateFrequency.semimonthly');
|
|
890
|
-
marker('domain.record.updateFrequency.biennially');
|
|
891
|
-
marker('domain.record.status.completed');
|
|
892
|
-
marker('domain.record.status.ongoing');
|
|
893
|
-
marker('domain.record.status.under_development');
|
|
894
|
-
marker('domain.record.status.deprecated');
|
|
895
|
-
marker('domain.record.status.removed');
|
|
896
|
-
marker('domain.record.status.planned');
|
|
897
|
-
marker('domain.record.status.required');
|
|
898
|
-
const RecordStatusValues = [
|
|
899
|
-
'completed',
|
|
900
|
-
'ongoing',
|
|
901
|
-
'under_development',
|
|
902
|
-
'deprecated',
|
|
903
|
-
'removed',
|
|
904
|
-
'planned',
|
|
905
|
-
'required',
|
|
906
|
-
];
|
|
907
|
-
marker('record.metadata.api.accessServiceProtocol.wms');
|
|
908
|
-
marker('record.metadata.api.accessServiceProtocol.wfs');
|
|
909
|
-
marker('record.metadata.api.accessServiceProtocol.wps');
|
|
910
|
-
marker('record.metadata.api.accessServiceProtocol.wmts');
|
|
911
|
-
marker('record.metadata.api.accessServiceProtocol.esriRest');
|
|
912
|
-
marker('record.metadata.api.accessServiceProtocol.ogcFeatures');
|
|
913
|
-
marker('record.metadata.api.accessServiceProtocol.GPFDL');
|
|
914
|
-
marker('record.metadata.api.accessServiceProtocol.tms');
|
|
915
|
-
marker('record.metadata.api.accessServiceProtocol.maplibre-style');
|
|
916
|
-
marker('record.metadata.api.accessServiceProtocol.postgis');
|
|
917
|
-
marker('record.metadata.api.accessServiceProtocol.stac');
|
|
918
|
-
marker('record.metadata.api.accessServiceProtocol.other');
|
|
919
|
-
|
|
920
947
|
function getUpdateFrequencyFromFrequencyCode(frequencyCode) {
|
|
921
948
|
return frequencyCode &&
|
|
922
949
|
updateFrequencyCodeValues.includes(frequencyCode)
|
|
@@ -1484,14 +1511,17 @@ function extractSourceRecords(liLineageEl) {
|
|
|
1484
1511
|
function readSourceRecords$1(rootEl) {
|
|
1485
1512
|
return extractSourceRecords(pipe(findNestedElement('gmd:dataQualityInfo', 'gmd:DQ_DataQuality', 'gmd:lineage', 'gmd:LI_Lineage'))(rootEl));
|
|
1486
1513
|
}
|
|
1487
|
-
function extractAssociatedRecords(containerName, aggregateName,
|
|
1514
|
+
function extractAssociatedRecords(containerName, aggregateName, readIdentifier) {
|
|
1488
1515
|
return pipe(findChildrenElement(containerName, false), mapArray((el) => {
|
|
1489
1516
|
const aggregateEl = findChildElement(aggregateName, false)(el);
|
|
1490
|
-
const
|
|
1491
|
-
const
|
|
1492
|
-
if (!
|
|
1517
|
+
const uniqueIdentifier = readIdentifier(aggregateEl);
|
|
1518
|
+
const associationTypeCode = pipe(findNestedElement('gmd:associationType', 'gmd:DS_AssociationTypeCode'), readAttribute('codeListValue'))(aggregateEl);
|
|
1519
|
+
if (!uniqueIdentifier || !associationTypeCode)
|
|
1493
1520
|
return null;
|
|
1494
|
-
return {
|
|
1521
|
+
return {
|
|
1522
|
+
uniqueIdentifier,
|
|
1523
|
+
associationType: getAssociationTypeFromCode(associationTypeCode),
|
|
1524
|
+
};
|
|
1495
1525
|
}), filterArray((r) => r !== null));
|
|
1496
1526
|
}
|
|
1497
1527
|
function readAssociatedRecords$1(rootEl) {
|
|
@@ -2039,8 +2069,8 @@ function writeSourceRecords$1(record, rootEl) {
|
|
|
2039
2069
|
}
|
|
2040
2070
|
function writeAssociatedRecords$1(record, rootEl) {
|
|
2041
2071
|
pipe(findOrCreateIdentification(), removeChildrenByName('gmd:aggregationInfo'), appendChildren(...record.associatedRecords
|
|
2042
|
-
.filter((assoc) => assoc.
|
|
2043
|
-
.map((assoc) => pipe(createNestedElement('gmd:aggregationInfo', 'gmd:MD_AggregateInformation'), appendChildren(pipe(createNestedElement('gmd:aggregateDataSetIdentifier', 'gmd:MD_Identifier', 'gmd:code'), writeCharacterString(assoc.
|
|
2072
|
+
.filter((assoc) => assoc.uniqueIdentifier && assoc.associationType)
|
|
2073
|
+
.map((assoc) => pipe(createNestedElement('gmd:aggregationInfo', 'gmd:MD_AggregateInformation'), appendChildren(pipe(createNestedElement('gmd:aggregateDataSetIdentifier', 'gmd:MD_Identifier', 'gmd:code'), writeCharacterString(assoc.uniqueIdentifier)), pipe(createNestedElement('gmd:associationType', 'gmd:DS_AssociationTypeCode'), writeAttribute('codeList', 'http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#DS_AssociationTypeCode'), writeAttribute('codeListValue', assoc.associationType)))))))(rootEl);
|
|
2044
2074
|
}
|
|
2045
2075
|
function getServiceEndpointProtocol(endpoint) {
|
|
2046
2076
|
switch (endpoint.accessServiceProtocol.toLowerCase()) {
|
|
@@ -2752,8 +2782,8 @@ function writeSourceRecords(record, rootEl) {
|
|
|
2752
2782
|
}
|
|
2753
2783
|
function writeAssociatedRecords(record, rootEl) {
|
|
2754
2784
|
pipe(findOrCreateIdentification(), removeChildrenByName('mri:associatedResource'), appendChildren(...record.associatedRecords
|
|
2755
|
-
.filter((assoc) => assoc.
|
|
2756
|
-
.map((assoc) => pipe(createNestedElement('mri:associatedResource', 'mri:MD_AssociatedResource'), appendChildren(pipe(createNestedElement('mri:associationType', 'mri:DS_AssociationTypeCode'), writeAttribute('codeList', 'http://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#DS_AssociationTypeCode'), writeAttribute('codeListValue', assoc.associationType)), pipe(createElement('mri:metadataReference'), writeAttribute('uuidref', assoc.
|
|
2785
|
+
.filter((assoc) => assoc.uniqueIdentifier && assoc.associationType)
|
|
2786
|
+
.map((assoc) => pipe(createNestedElement('mri:associatedResource', 'mri:MD_AssociatedResource'), appendChildren(pipe(createNestedElement('mri:associationType', 'mri:DS_AssociationTypeCode'), writeAttribute('codeList', 'http://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#DS_AssociationTypeCode'), writeAttribute('codeListValue', assoc.associationType)), pipe(createElement('mri:metadataReference'), writeAttribute('uuidref', assoc.uniqueIdentifier)))))))(rootEl);
|
|
2757
2787
|
}
|
|
2758
2788
|
|
|
2759
2789
|
class Iso191153Converter extends Iso19139Converter {
|
|
@@ -18876,14 +18906,29 @@ class Gn4FieldMapper {
|
|
|
18876
18906
|
featureTypes: selectField(source, 'featureTypes'),
|
|
18877
18907
|
}, output),
|
|
18878
18908
|
related: (output, source) => {
|
|
18879
|
-
const
|
|
18909
|
+
const related = selectField(source, 'related');
|
|
18910
|
+
const fcatSource = selectField(getFirstValue(selectField(related, 'fcats')) ?? {}, '_source');
|
|
18880
18911
|
const featureCatalogIdentifier = selectField(fcatSource, 'uuid');
|
|
18881
|
-
const sourceOfLinks = getAsArray(selectField(
|
|
18912
|
+
const sourceOfLinks = getAsArray(selectField(related, 'hassources'));
|
|
18882
18913
|
const sourceOfIdentifiers = sourceOfLinks
|
|
18883
18914
|
.filter((link) => link['origin'] === 'catalog')
|
|
18884
18915
|
.map((link) => {
|
|
18885
18916
|
return selectField(selectField(link, '_source'), 'uuid');
|
|
18886
18917
|
});
|
|
18918
|
+
const siblingLinks = getAsArray(selectField(related, 'siblings'));
|
|
18919
|
+
const siblings = siblingLinks
|
|
18920
|
+
.filter((link) => link['origin'] === 'catalog')
|
|
18921
|
+
.map((link) => ({
|
|
18922
|
+
uniqueIdentifier: selectField(selectField(link, '_source'), 'uuid'),
|
|
18923
|
+
associationType: getAssociationTypeFromCode(selectField(selectField(link, 'properties'), 'associationType')),
|
|
18924
|
+
}));
|
|
18925
|
+
const associatedLinks = getAsArray(selectField(related, 'associated'));
|
|
18926
|
+
const associatedIdentifiers = associatedLinks
|
|
18927
|
+
.filter((link) => link['origin'] === 'catalog')
|
|
18928
|
+
.map((link) => {
|
|
18929
|
+
return selectField(selectField(link, '_source'), 'uuid');
|
|
18930
|
+
})
|
|
18931
|
+
.filter((uuid) => !siblings.some((sibling) => sibling.uniqueIdentifier === uuid));
|
|
18887
18932
|
const extraValues = {};
|
|
18888
18933
|
if (featureCatalogIdentifier) {
|
|
18889
18934
|
extraValues.featureCatalogIdentifier = featureCatalogIdentifier;
|
|
@@ -18891,6 +18936,12 @@ class Gn4FieldMapper {
|
|
|
18891
18936
|
if (sourceOfIdentifiers && sourceOfIdentifiers.length > 0) {
|
|
18892
18937
|
extraValues.sourceOfIdentifiers = sourceOfIdentifiers;
|
|
18893
18938
|
}
|
|
18939
|
+
if (associatedIdentifiers && associatedIdentifiers.length > 0) {
|
|
18940
|
+
extraValues.associatedIdentifiers = associatedIdentifiers;
|
|
18941
|
+
}
|
|
18942
|
+
if (siblings && siblings.length > 0) {
|
|
18943
|
+
extraValues.siblings = siblings;
|
|
18944
|
+
}
|
|
18894
18945
|
return Object.keys(extraValues).length > 0
|
|
18895
18946
|
? this.addExtra(extraValues, output)
|
|
18896
18947
|
: output;
|
|
@@ -19467,6 +19518,18 @@ function propagateToDocumentOnly(event) {
|
|
|
19467
19518
|
}, 0);
|
|
19468
19519
|
}
|
|
19469
19520
|
|
|
19521
|
+
function isFileExtensionValid(fileName, acceptedExtensions) {
|
|
19522
|
+
return acceptedExtensions.some((ext) => fileName.toLowerCase().endsWith(ext));
|
|
19523
|
+
}
|
|
19524
|
+
function readFileAsText(file) {
|
|
19525
|
+
return new Promise((resolve, reject) => {
|
|
19526
|
+
const reader = new FileReader();
|
|
19527
|
+
reader.onload = () => resolve(reader.result);
|
|
19528
|
+
reader.onerror = () => reject(reader.error);
|
|
19529
|
+
reader.readAsText(file);
|
|
19530
|
+
});
|
|
19531
|
+
}
|
|
19532
|
+
|
|
19470
19533
|
function formatUserInfo(userInfo, displayCount = false) {
|
|
19471
19534
|
const infos = (typeof userInfo === 'string' ? userInfo : '').split('|');
|
|
19472
19535
|
const count = displayCount ? ` ${infos[3].split(' ')[1]}` : '';
|
|
@@ -20338,7 +20401,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
20338
20401
|
}] } });
|
|
20339
20402
|
|
|
20340
20403
|
var name = "geonetwork-ui";
|
|
20341
|
-
var version = "2.11.0-dev.
|
|
20404
|
+
var version = "2.11.0-dev.a5c259d9e";
|
|
20342
20405
|
var engines = {
|
|
20343
20406
|
node: ">=24"
|
|
20344
20407
|
};
|
|
@@ -20368,20 +20431,21 @@ var peerDependencies = {
|
|
|
20368
20431
|
"@ngrx/store": "19.x || 20.x || 21.x",
|
|
20369
20432
|
"@ngrx/store-devtools": "19.x || 20.x || 21.x",
|
|
20370
20433
|
"@ngrx/operators": "19.x || 20.x || 21.x",
|
|
20371
|
-
"@ngx-translate/core": "
|
|
20372
|
-
"@ngx-translate/http-loader": "
|
|
20373
|
-
"flag-icons": "
|
|
20434
|
+
"@ngx-translate/core": "17.x",
|
|
20435
|
+
"@ngx-translate/http-loader": "17.x",
|
|
20436
|
+
"flag-icons": "~7.5.0",
|
|
20374
20437
|
rxjs: "7.x",
|
|
20375
20438
|
"zone.js": "*",
|
|
20376
20439
|
tailwindcss: "3.x"
|
|
20377
20440
|
};
|
|
20378
20441
|
var dependencies = {
|
|
20379
20442
|
"@biesbjerg/ngx-translate-extract-marker": "~1.0.0",
|
|
20380
|
-
"@camptocamp/ogc-client": "1.3.1-dev.
|
|
20381
|
-
"@
|
|
20382
|
-
"@geospatial-sdk/
|
|
20383
|
-
"@geospatial-sdk/
|
|
20384
|
-
"@geospatial-sdk/
|
|
20443
|
+
"@camptocamp/ogc-client": "1.3.1-dev.200c02a",
|
|
20444
|
+
"@duckdb/duckdb-wasm": "~1.32.0",
|
|
20445
|
+
"@geospatial-sdk/core": "0.0.5-dev.78",
|
|
20446
|
+
"@geospatial-sdk/geocoding": "0.0.5-dev.78",
|
|
20447
|
+
"@geospatial-sdk/legend": "0.0.5-dev.78",
|
|
20448
|
+
"@geospatial-sdk/openlayers": "0.0.5-dev.78",
|
|
20385
20449
|
"@ltd/j-toml": "~1.38.0",
|
|
20386
20450
|
"@messageformat/core": "~3.4.0",
|
|
20387
20451
|
"@ng-icons/core": "~32.5.0",
|
|
@@ -20389,7 +20453,7 @@ var dependencies = {
|
|
|
20389
20453
|
"@ng-icons/material-icons": "~32.5.0",
|
|
20390
20454
|
"@ng-icons/tabler-icons": "~32.4.0",
|
|
20391
20455
|
"@rgrove/parse-xml": "4.2.0",
|
|
20392
|
-
|
|
20456
|
+
"apache-arrow": "~17.0.0",
|
|
20393
20457
|
"chart.js": "~4.5.1",
|
|
20394
20458
|
"chroma-js": "~3.2.0",
|
|
20395
20459
|
"date-fns": "4.1.0",
|
|
@@ -20402,7 +20466,6 @@ var dependencies = {
|
|
|
20402
20466
|
"ngx-dropzone": "~3.1.0",
|
|
20403
20467
|
"ngx-translate-messageformat-compiler": "~7.2.0",
|
|
20404
20468
|
ol: "~10.8.0",
|
|
20405
|
-
papaparse: "~5.5.3",
|
|
20406
20469
|
proj4: "~2.20.4",
|
|
20407
20470
|
rdflib: "~2.3.5",
|
|
20408
20471
|
semver: "~7.7.4",
|
|
@@ -20647,6 +20710,7 @@ class ElasticsearchService {
|
|
|
20647
20710
|
values: uuids,
|
|
20648
20711
|
},
|
|
20649
20712
|
},
|
|
20713
|
+
size: uuids.length,
|
|
20650
20714
|
};
|
|
20651
20715
|
}
|
|
20652
20716
|
getRelatedRecordPayload(record, size = 6, _source = [...ES_SOURCE_SUMMARY, 'createDate']) {
|
|
@@ -20697,10 +20761,28 @@ class ElasticsearchService {
|
|
|
20697
20761
|
};
|
|
20698
20762
|
}
|
|
20699
20763
|
buildPayloadSort(sortBy) {
|
|
20700
|
-
if (sortBy ===
|
|
20764
|
+
if (!sortBy || sortBy.length === 0)
|
|
20701
20765
|
return undefined;
|
|
20702
|
-
const fields = Array.isArray(sortBy[0])
|
|
20703
|
-
|
|
20766
|
+
const fields = Array.isArray(sortBy[0])
|
|
20767
|
+
? sortBy
|
|
20768
|
+
: [sortBy];
|
|
20769
|
+
return fields.map((field) => {
|
|
20770
|
+
// Sort by nested array of dates only works with the explicit syntax
|
|
20771
|
+
if (field[1].endsWith('.date')) {
|
|
20772
|
+
const nestedPath = field[1].slice(0, field[1].lastIndexOf('.date'));
|
|
20773
|
+
return {
|
|
20774
|
+
[field[1]]: {
|
|
20775
|
+
order: field[0],
|
|
20776
|
+
mode: field[0] === 'desc' ? 'max' : 'min',
|
|
20777
|
+
missing: '_last',
|
|
20778
|
+
nested: {
|
|
20779
|
+
path: nestedPath,
|
|
20780
|
+
},
|
|
20781
|
+
},
|
|
20782
|
+
};
|
|
20783
|
+
}
|
|
20784
|
+
return { [field[1]]: field[0] };
|
|
20785
|
+
});
|
|
20704
20786
|
}
|
|
20705
20787
|
injectLangInQueryStringFields(queryFieldsPriority) {
|
|
20706
20788
|
const queryLang = this.getQueryLang();
|
|
@@ -21180,7 +21262,7 @@ class Gn4Repository {
|
|
|
21180
21262
|
}
|
|
21181
21263
|
getRecord(uniqueIdentifier) {
|
|
21182
21264
|
return this.gn4SearchApi
|
|
21183
|
-
.search('bucket', ['fcats', 'hassources'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21265
|
+
.search('bucket', ['fcats', 'hassources', 'siblings', 'associated'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21184
21266
|
.pipe(map$1((results) => results.hits.hits[0]), switchMap((record) => record ? this.gn4Mapper.readRecord(record) : of(null)));
|
|
21185
21267
|
}
|
|
21186
21268
|
getMultipleRecords(uniqueIdentifiers) {
|
|
@@ -21234,19 +21316,28 @@ class Gn4Repository {
|
|
|
21234
21316
|
.search('bucket', null, JSON.stringify(this.gn4SearchHelper.getRelatedRecordPayload(similarTo, 3)))
|
|
21235
21317
|
.pipe(switchMap((results) => this.gn4Mapper.readRecords(results.hits.hits)));
|
|
21236
21318
|
}
|
|
21237
|
-
|
|
21238
|
-
const
|
|
21239
|
-
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
21247
|
-
|
|
21319
|
+
getLinkedRecords(record) {
|
|
21320
|
+
const siblings = (record.extras?.['siblings'] ?? []);
|
|
21321
|
+
const relations = [
|
|
21322
|
+
['source', (record.extras?.['sourcesIdentifiers'] ?? [])],
|
|
21323
|
+
['sourceOf', (record.extras?.['sourceOfIdentifiers'] ?? [])],
|
|
21324
|
+
['sibling', siblings.map(({ uniqueIdentifier }) => uniqueIdentifier)],
|
|
21325
|
+
[
|
|
21326
|
+
'associated',
|
|
21327
|
+
(record.extras?.['associatedIdentifiers'] ?? []),
|
|
21328
|
+
],
|
|
21329
|
+
];
|
|
21330
|
+
const requested = relations.filter(([, identifiers]) => identifiers.length > 0);
|
|
21331
|
+
if (requested.length === 0) {
|
|
21332
|
+
return of([]);
|
|
21248
21333
|
}
|
|
21249
|
-
return
|
|
21334
|
+
return forkJoin(requested.map(([relation, identifiers]) => this.getMultipleRecords(identifiers).pipe(map$1((records) => (records ?? []).map((record) => ({
|
|
21335
|
+
record,
|
|
21336
|
+
relation,
|
|
21337
|
+
associationType: relation === 'sibling'
|
|
21338
|
+
? siblings.find(({ uniqueIdentifier }) => uniqueIdentifier === record.uniqueIdentifier)?.associationType
|
|
21339
|
+
: undefined,
|
|
21340
|
+
}))), catchError(() => of([]))))).pipe(map$1((groups) => groups.flat()));
|
|
21250
21341
|
}
|
|
21251
21342
|
aggregate(params) {
|
|
21252
21343
|
// if aggregations are empty, return an empty object right away
|
|
@@ -22507,9 +22598,8 @@ const VECTOR_STYLE_DEFAULT = new InjectionToken('vectorStyleDefault', {
|
|
|
22507
22598
|
});
|
|
22508
22599
|
|
|
22509
22600
|
const DEFAULT_BASEMAP_LAYER = {
|
|
22510
|
-
type: '
|
|
22511
|
-
|
|
22512
|
-
attributions: `<span>© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="https://carto.com/">Carto</a></span>`,
|
|
22601
|
+
type: 'maplibre-style',
|
|
22602
|
+
styleUrl: `https://basemaps.cartocdn.com/gl/positron-gl-style/style.json`,
|
|
22513
22603
|
};
|
|
22514
22604
|
const DEFAULT_VIEW = {
|
|
22515
22605
|
center: [0, 15],
|
|
@@ -23224,6 +23314,7 @@ function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
|
|
|
23224
23314
|
'search_preset',
|
|
23225
23315
|
'advanced_filters',
|
|
23226
23316
|
'limit',
|
|
23317
|
+
'spatial_extent_max_file_size',
|
|
23227
23318
|
], warnings, errors);
|
|
23228
23319
|
const parsedSearchParams = parseMultiConfigSection(parsed, 'search_preset', ['name'], ['sort', 'filters'], warnings, errors);
|
|
23229
23320
|
searchConfig =
|
|
@@ -23241,6 +23332,7 @@ function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
|
|
|
23241
23332
|
})),
|
|
23242
23333
|
ADVANCED_FILTERS: parsedSearchSection.advanced_filters,
|
|
23243
23334
|
LIMIT: parsedSearchSection.limit,
|
|
23335
|
+
SPATIAL_EXTENT_MAX_FILE_SIZE: parsedSearchSection.spatial_extent_max_file_size,
|
|
23244
23336
|
};
|
|
23245
23337
|
const parsedMetadataQualitySection = parseConfigSection(parsed, 'metadata-quality', [], ['enabled'], warnings, errors);
|
|
23246
23338
|
metadataQualityConfig =
|
|
@@ -24638,28 +24730,68 @@ class DragAndDropFileInputComponent {
|
|
|
24638
24730
|
constructor() {
|
|
24639
24731
|
this.placeholder = placeholder;
|
|
24640
24732
|
this.accept = '*';
|
|
24733
|
+
this.maxFileSizeMb = null;
|
|
24734
|
+
this.icon = null;
|
|
24735
|
+
this.dropzoneBackgroundColor = null;
|
|
24736
|
+
this.textClass = '';
|
|
24737
|
+
this.extraClass = '';
|
|
24738
|
+
this.showFileName = true;
|
|
24641
24739
|
this.fileChange = new EventEmitter();
|
|
24740
|
+
this.errorChange = new EventEmitter();
|
|
24642
24741
|
this.selectedFile = null;
|
|
24643
24742
|
}
|
|
24644
24743
|
get fileName() {
|
|
24645
24744
|
return this.selectedFile && this.selectedFile.name;
|
|
24646
24745
|
}
|
|
24746
|
+
get maxFileSizeBytes() {
|
|
24747
|
+
return typeof this.maxFileSizeMb === 'number'
|
|
24748
|
+
? megabytesToBytes(this.maxFileSizeMb)
|
|
24749
|
+
: null;
|
|
24750
|
+
}
|
|
24647
24751
|
selectFile(event) {
|
|
24752
|
+
if (event.rejectedFiles?.length) {
|
|
24753
|
+
const reason = event.rejectedFiles[0].reason;
|
|
24754
|
+
this.errorChange.emit(reason === 'size' ? 'file-too-large' : 'invalid-extension');
|
|
24755
|
+
return;
|
|
24756
|
+
}
|
|
24648
24757
|
this.selectedFile = event.addedFiles[0];
|
|
24649
24758
|
this.fileChange.emit(this.selectedFile);
|
|
24650
24759
|
}
|
|
24760
|
+
openFileSelector() {
|
|
24761
|
+
this.dropzone.showFileSelector();
|
|
24762
|
+
}
|
|
24763
|
+
clear() {
|
|
24764
|
+
this.selectedFile = null;
|
|
24765
|
+
}
|
|
24651
24766
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DragAndDropFileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
24652
|
-
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
|
|
24767
|
+
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$7.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"] }] }); }
|
|
24653
24768
|
}
|
|
24654
24769
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DragAndDropFileInputComponent, decorators: [{
|
|
24655
24770
|
type: Component,
|
|
24656
|
-
args: [{ selector: 'gn-ui-drag-and-drop-file-input', standalone: true, imports: [NgxDropzoneModule], template: "<div
|
|
24771
|
+
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"] }]
|
|
24657
24772
|
}], propDecorators: { placeholder: [{
|
|
24658
24773
|
type: Input
|
|
24659
24774
|
}], accept: [{
|
|
24660
24775
|
type: Input
|
|
24776
|
+
}], maxFileSizeMb: [{
|
|
24777
|
+
type: Input
|
|
24778
|
+
}], icon: [{
|
|
24779
|
+
type: Input
|
|
24780
|
+
}], dropzoneBackgroundColor: [{
|
|
24781
|
+
type: Input
|
|
24782
|
+
}], textClass: [{
|
|
24783
|
+
type: Input
|
|
24784
|
+
}], extraClass: [{
|
|
24785
|
+
type: Input
|
|
24786
|
+
}], showFileName: [{
|
|
24787
|
+
type: Input
|
|
24661
24788
|
}], fileChange: [{
|
|
24662
24789
|
type: Output
|
|
24790
|
+
}], errorChange: [{
|
|
24791
|
+
type: Output
|
|
24792
|
+
}], dropzone: [{
|
|
24793
|
+
type: ViewChild,
|
|
24794
|
+
args: [NgxDropzoneComponent]
|
|
24663
24795
|
}] } });
|
|
24664
24796
|
|
|
24665
24797
|
class DropdownMultiselectComponent {
|
|
@@ -25736,6 +25868,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
25736
25868
|
type: Output
|
|
25737
25869
|
}] } });
|
|
25738
25870
|
|
|
25871
|
+
marker('search.filters.spatialExtent.import');
|
|
25872
|
+
marker('search.filters.spatialExtent.helpText');
|
|
25873
|
+
marker('search.filters.spatialExtent.error.title');
|
|
25874
|
+
marker('search.filters.spatialExtent.bboxPrefix');
|
|
25875
|
+
marker('search.filters.spatialExtent.bboxDelete');
|
|
25876
|
+
class SpatialExtentDropdownComponent {
|
|
25877
|
+
constructor() {
|
|
25878
|
+
this.cd = inject(ChangeDetectorRef);
|
|
25879
|
+
this.scrollStrategies = inject(ScrollStrategyOptions);
|
|
25880
|
+
this.maxFileSizeMb = null;
|
|
25881
|
+
this.bboxChange = new EventEmitter();
|
|
25882
|
+
this.errorChange = new EventEmitter();
|
|
25883
|
+
this.bbox = null;
|
|
25884
|
+
this.fileName = '';
|
|
25885
|
+
this.overlayPositions = [
|
|
25886
|
+
{
|
|
25887
|
+
originX: 'start',
|
|
25888
|
+
originY: 'bottom',
|
|
25889
|
+
overlayX: 'start',
|
|
25890
|
+
overlayY: 'top',
|
|
25891
|
+
offsetY: 8,
|
|
25892
|
+
},
|
|
25893
|
+
{
|
|
25894
|
+
originX: 'start',
|
|
25895
|
+
originY: 'top',
|
|
25896
|
+
overlayX: 'start',
|
|
25897
|
+
overlayY: 'bottom',
|
|
25898
|
+
offsetY: -8,
|
|
25899
|
+
},
|
|
25900
|
+
];
|
|
25901
|
+
this.scrollStrategy = this.scrollStrategies.reposition();
|
|
25902
|
+
this.overlayOpen = false;
|
|
25903
|
+
this.overlayMinWidth = 'none';
|
|
25904
|
+
this.errorKey = null;
|
|
25905
|
+
}
|
|
25906
|
+
get hasSelection() {
|
|
25907
|
+
return !!this.bbox;
|
|
25908
|
+
}
|
|
25909
|
+
openOverlay() {
|
|
25910
|
+
this.overlayMinWidth =
|
|
25911
|
+
this.overlayOrigin.elementRef.nativeElement.getBoundingClientRect()
|
|
25912
|
+
.width + 'px';
|
|
25913
|
+
this.overlayOpen = true;
|
|
25914
|
+
}
|
|
25915
|
+
closeOverlay() {
|
|
25916
|
+
this.overlayOpen = false;
|
|
25917
|
+
}
|
|
25918
|
+
toggleOverlay() {
|
|
25919
|
+
if (this.overlayOpen) {
|
|
25920
|
+
this.closeOverlay();
|
|
25921
|
+
}
|
|
25922
|
+
else {
|
|
25923
|
+
this.openOverlay();
|
|
25924
|
+
}
|
|
25925
|
+
}
|
|
25926
|
+
async handleFileSelected(file) {
|
|
25927
|
+
this.errorKey = null;
|
|
25928
|
+
let content;
|
|
25929
|
+
try {
|
|
25930
|
+
content = await readFileAsText(file);
|
|
25931
|
+
const parsed = JSON.parse(content);
|
|
25932
|
+
const geometry = getGeometryFromGeoJSON(parsed);
|
|
25933
|
+
if (!geometry) {
|
|
25934
|
+
this.setError(marker('search.filters.spatialExtent.error.noGeometry'));
|
|
25935
|
+
return;
|
|
25936
|
+
}
|
|
25937
|
+
const bbox = getGeometryBoundingBox(geometry);
|
|
25938
|
+
this.bbox = bbox;
|
|
25939
|
+
this.fileName = file.name;
|
|
25940
|
+
this.bboxChange.emit(bbox);
|
|
25941
|
+
this.cd.markForCheck();
|
|
25942
|
+
}
|
|
25943
|
+
catch {
|
|
25944
|
+
this.setError(marker('search.filters.spatialExtent.error.invalidFormat'));
|
|
25945
|
+
return;
|
|
25946
|
+
}
|
|
25947
|
+
}
|
|
25948
|
+
handleFileError(error) {
|
|
25949
|
+
if (error === 'file-too-large') {
|
|
25950
|
+
this.setError(marker('search.filters.spatialExtent.error.fileTooLarge'), {
|
|
25951
|
+
maxSize: this.maxFileSizeMb,
|
|
25952
|
+
});
|
|
25953
|
+
}
|
|
25954
|
+
else {
|
|
25955
|
+
this.setError(marker('search.filters.spatialExtent.error.invalidFormat'));
|
|
25956
|
+
}
|
|
25957
|
+
}
|
|
25958
|
+
setError(errorKey, params) {
|
|
25959
|
+
this.errorKey = errorKey;
|
|
25960
|
+
this.errorChange.emit({ key: errorKey, params });
|
|
25961
|
+
this.cd.markForCheck();
|
|
25962
|
+
}
|
|
25963
|
+
removeSelection(event) {
|
|
25964
|
+
this.bbox = null;
|
|
25965
|
+
this.fileName = '';
|
|
25966
|
+
this.errorKey = null;
|
|
25967
|
+
this.fileInput?.clear();
|
|
25968
|
+
this.bboxChange.emit(null);
|
|
25969
|
+
propagateToDocumentOnly(event);
|
|
25970
|
+
}
|
|
25971
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpatialExtentDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
25972
|
+
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" }, outputs: { bboxChange: "bboxChange", errorChange: "errorChange" }, providers: [
|
|
25973
|
+
provideIcons({
|
|
25974
|
+
iconoirCheckCircle,
|
|
25975
|
+
iconoirImport,
|
|
25976
|
+
iconoirSquareDashed,
|
|
25977
|
+
iconoirTrash,
|
|
25978
|
+
matClose,
|
|
25979
|
+
matExpandLess,
|
|
25980
|
+
matExpandMore,
|
|
25981
|
+
}),
|
|
25982
|
+
], viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: ["overlayOrigin"], descendants: true }, { propertyName: "overlay", first: true, predicate: CdkConnectedOverlay, descendants: true }, { propertyName: "fileInput", first: true, predicate: DragAndDropFileInputComponent, descendants: true }], ngImport: i0, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[8px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirImport\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"\n ('search.filters.spatialExtent.bboxDelete' | translate) +\n ' ' +\n fileName\n \"\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 {{ 'search.filters.spatialExtent.bboxPrefix' | translate }}\n {{ fileName }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ 'search.filters.spatialExtent.bboxDelete' | translate }}\n {{ fileName }}\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$8.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$8.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 }); }
|
|
25983
|
+
}
|
|
25984
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SpatialExtentDropdownComponent, decorators: [{
|
|
25985
|
+
type: Component,
|
|
25986
|
+
args: [{ selector: 'gn-ui-spatial-extent-dropdown', standalone: true, imports: [
|
|
25987
|
+
ButtonComponent,
|
|
25988
|
+
NgIcon,
|
|
25989
|
+
OverlayModule,
|
|
25990
|
+
TranslatePipe,
|
|
25991
|
+
DragAndDropFileInputComponent,
|
|
25992
|
+
], providers: [
|
|
25993
|
+
provideIcons({
|
|
25994
|
+
iconoirCheckCircle,
|
|
25995
|
+
iconoirImport,
|
|
25996
|
+
iconoirSquareDashed,
|
|
25997
|
+
iconoirTrash,
|
|
25998
|
+
matClose,
|
|
25999
|
+
matExpandLess,
|
|
26000
|
+
matExpandMore,
|
|
26001
|
+
}),
|
|
26002
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<gn-ui-button\n type=\"outline\"\n extraClass=\"bg-background w-full !p-[8px] !pl-[16px]\"\n [title]=\"title\"\n (buttonClick)=\"toggleOverlay()\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n>\n <div class=\"grow flex items-center mr-2 gap-2 overflow-hidden\">\n <div class=\"text-left font-medium truncate py-1\">\n {{ title }}\n </div>\n @if (hasSelection) {\n <div\n class=\"bg-primary-lighter text-white shrink-0 rounded-full font-bold text-[12px] w-[22px] h-[22px] flex items-center justify-center\"\n >\n 1\n </div>\n }\n </div>\n <button class=\"h-6 w-6 flex items-center\" data-cy=\"clearSelection\">\n @if (hasSelection && !overlayOpen) {\n <ng-icon\n class=\"shrink-0 opacity-40 mr-1.5 hover:opacity-80 transition-colors clear-btn\"\n (click)=\"removeSelection($event)\"\n name=\"matClose\"\n ></ng-icon>\n }\n </button>\n <ng-icon\n [name]=\"overlayOpen ? 'matExpandLess' : 'matExpandMore'\"\n class=\"shrink-0 opacity-40\"\n >\n </ng-icon>\n</gn-ui-button>\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"overlayOpen\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n (overlayOutsideClick)=\"closeOverlay()\"\n (detach)=\"closeOverlay()\"\n>\n <div\n class=\"bg-white border border-gray-400 rounded shadow-lg pt-[12px] px-[16px] overlay-container w-[280px] flex flex-col gap-2\"\n [style.min-width]=\"overlayMinWidth\"\n >\n <div class=\"text-xs text-black\">\n {{ 'search.filters.spatialExtent.helpText' | translate }}\n </div>\n\n <div\n [class]=\"\n (hasSelection\n ? 'border-b-[1px] border-gray-400 pb-[20px]'\n : 'pb-[8px]') + ' text-black'\n \"\n >\n <gn-ui-drag-and-drop-file-input\n accept=\".json,.geojson\"\n [placeholder]=\"'search.filters.spatialExtent.import' | translate\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [showFileName]=\"false\"\n textClass=\"text-black truncate\"\n dropzoneBackgroundColor=\"transparent\"\n icon=\"iconoirImport\"\n extraClass=\"gn-ui-gray-outline-input w-full !h-[32px] px-[8px] py-[4px] justify-between\"\n (fileChange)=\"handleFileSelected($event)\"\n (errorChange)=\"handleFileError($event)\"\n data-cy=\"importGeojson\"\n ></gn-ui-drag-and-drop-file-input>\n </div>\n\n @if (hasSelection) {\n <gn-ui-button\n [type]=\"'primary-light'\"\n [title]=\"\n ('search.filters.spatialExtent.bboxDelete' | translate) +\n ' ' +\n fileName\n \"\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 {{ 'search.filters.spatialExtent.bboxPrefix' | translate }}\n {{ fileName }}\n </span>\n <span class=\"hidden group-hover:block truncate text-sm m-auto\">\n {{ 'search.filters.spatialExtent.bboxDelete' | translate }}\n {{ fileName }}\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" }]
|
|
26003
|
+
}], propDecorators: { title: [{
|
|
26004
|
+
type: Input
|
|
26005
|
+
}], maxFileSizeMb: [{
|
|
26006
|
+
type: Input
|
|
26007
|
+
}], bboxChange: [{
|
|
26008
|
+
type: Output
|
|
26009
|
+
}], errorChange: [{
|
|
26010
|
+
type: Output
|
|
26011
|
+
}], overlayOrigin: [{
|
|
26012
|
+
type: ViewChild,
|
|
26013
|
+
args: ['overlayOrigin']
|
|
26014
|
+
}], overlay: [{
|
|
26015
|
+
type: ViewChild,
|
|
26016
|
+
args: [CdkConnectedOverlay]
|
|
26017
|
+
}], fileInput: [{
|
|
26018
|
+
type: ViewChild,
|
|
26019
|
+
args: [DragAndDropFileInputComponent]
|
|
26020
|
+
}] } });
|
|
26021
|
+
|
|
25739
26022
|
class CellPopinComponent {
|
|
25740
26023
|
constructor() {
|
|
25741
26024
|
this.scrollDispatcher = inject(ScrollDispatcher);
|
|
@@ -27902,6 +28185,18 @@ class DateRangeSearchField extends SimpleSearchField {
|
|
|
27902
28185
|
return 'dateRange';
|
|
27903
28186
|
}
|
|
27904
28187
|
}
|
|
28188
|
+
class SpatialExtentSearchField extends SimpleSearchField {
|
|
28189
|
+
constructor(injector) {
|
|
28190
|
+
super('spatialExtent', injector, 'asc');
|
|
28191
|
+
}
|
|
28192
|
+
getAvailableValues() {
|
|
28193
|
+
// TODO: return an array of spatial extents to show which ones are available in the dropdown
|
|
28194
|
+
return of([]);
|
|
28195
|
+
}
|
|
28196
|
+
getType() {
|
|
28197
|
+
return 'spatialExtent';
|
|
28198
|
+
}
|
|
28199
|
+
}
|
|
27905
28200
|
marker('search.filters.availableServices.view');
|
|
27906
28201
|
marker('search.filters.availableServices.download');
|
|
27907
28202
|
class AvailableServicesField extends SimpleSearchField {
|
|
@@ -28046,6 +28341,7 @@ marker('search.filters.producerOrg');
|
|
|
28046
28341
|
marker('search.filters.publisherOrg');
|
|
28047
28342
|
marker('search.filters.user');
|
|
28048
28343
|
marker('search.filters.changeDate');
|
|
28344
|
+
marker('search.filters.spatialExtent');
|
|
28049
28345
|
class FieldsService {
|
|
28050
28346
|
constructor() {
|
|
28051
28347
|
this.injector = inject(Injector);
|
|
@@ -28069,6 +28365,7 @@ class FieldsService {
|
|
|
28069
28365
|
user: new UserSearchField(this.injector),
|
|
28070
28366
|
changeDate: new DateRangeSearchField('changeDate', this.injector, 'desc'),
|
|
28071
28367
|
availableServices: new AvailableServicesField(this.injector),
|
|
28368
|
+
spatialExtent: new SpatialExtentSearchField(this.injector),
|
|
28072
28369
|
};
|
|
28073
28370
|
}
|
|
28074
28371
|
get supportedFields() {
|
|
@@ -31253,19 +31550,111 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31253
31550
|
type: Output
|
|
31254
31551
|
}] } });
|
|
31255
31552
|
|
|
31553
|
+
class NotificationsService {
|
|
31554
|
+
constructor() {
|
|
31555
|
+
this.notifications$ = new BehaviorSubject([]);
|
|
31556
|
+
}
|
|
31557
|
+
showNotification(content, timeoutMs, error) {
|
|
31558
|
+
error && console.error(error);
|
|
31559
|
+
const id = Math.floor(Math.random() * 1000000);
|
|
31560
|
+
this.notifications$.next([...this.notifications$.value, { ...content, id }]);
|
|
31561
|
+
if (typeof timeoutMs !== 'undefined') {
|
|
31562
|
+
setTimeout(() => {
|
|
31563
|
+
this.removeNotificationById(id);
|
|
31564
|
+
}, timeoutMs);
|
|
31565
|
+
}
|
|
31566
|
+
return id;
|
|
31567
|
+
}
|
|
31568
|
+
removeNotificationById(id) {
|
|
31569
|
+
this.notifications$.next(this.notifications$.value.filter((n) => n.id !== id));
|
|
31570
|
+
}
|
|
31571
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
31572
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, providedIn: 'root' }); }
|
|
31573
|
+
}
|
|
31574
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, decorators: [{
|
|
31575
|
+
type: Injectable,
|
|
31576
|
+
args: [{
|
|
31577
|
+
providedIn: 'root',
|
|
31578
|
+
}]
|
|
31579
|
+
}] });
|
|
31580
|
+
|
|
31581
|
+
class NotificationsContainerComponent {
|
|
31582
|
+
constructor() {
|
|
31583
|
+
this.notificationsService = inject(NotificationsService);
|
|
31584
|
+
}
|
|
31585
|
+
trackById(index, notification) {
|
|
31586
|
+
return notification.id;
|
|
31587
|
+
}
|
|
31588
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31589
|
+
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: [
|
|
31590
|
+
trigger('enterExit', [
|
|
31591
|
+
transition(':enter', [
|
|
31592
|
+
animate('150ms', keyframes([
|
|
31593
|
+
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31594
|
+
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31595
|
+
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31596
|
+
])),
|
|
31597
|
+
]),
|
|
31598
|
+
transition(':leave', [
|
|
31599
|
+
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31600
|
+
]),
|
|
31601
|
+
]),
|
|
31602
|
+
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31603
|
+
}
|
|
31604
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, decorators: [{
|
|
31605
|
+
type: Component,
|
|
31606
|
+
args: [{ selector: 'gn-ui-notifications-container', standalone: true, imports: [CommonModule, NotificationComponent], changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
31607
|
+
trigger('enterExit', [
|
|
31608
|
+
transition(':enter', [
|
|
31609
|
+
animate('150ms', keyframes([
|
|
31610
|
+
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31611
|
+
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31612
|
+
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31613
|
+
])),
|
|
31614
|
+
]),
|
|
31615
|
+
transition(':leave', [
|
|
31616
|
+
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31617
|
+
]),
|
|
31618
|
+
]),
|
|
31619
|
+
], 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" }]
|
|
31620
|
+
}] });
|
|
31621
|
+
|
|
31256
31622
|
class FilterDropdownComponent {
|
|
31257
31623
|
constructor() {
|
|
31258
31624
|
this.searchFacade = inject(SearchFacade);
|
|
31259
31625
|
this.searchService = inject(SearchService);
|
|
31260
31626
|
this.fieldsService = inject(FieldsService);
|
|
31627
|
+
this.notificationsService = inject(NotificationsService);
|
|
31628
|
+
this.translateService = inject(TranslateService);
|
|
31629
|
+
this.spatialExtentMaxFileSize = getOptionalSearchConfig()?.SPATIAL_EXTENT_MAX_FILE_SIZE;
|
|
31261
31630
|
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([])));
|
|
31262
31631
|
this.selectedDateRange$ = this.selected$.pipe(map$1((selectedDateRange) => selectedDateRange));
|
|
31632
|
+
this.spatialExtentErrorNotificationId = null;
|
|
31263
31633
|
}
|
|
31264
31634
|
onSelectedValues(values) {
|
|
31265
31635
|
this.fieldsService
|
|
31266
31636
|
.buildFiltersFromFieldValues({ [this.fieldName]: values })
|
|
31267
31637
|
.subscribe((filters) => this.searchService.updateFilters(filters));
|
|
31268
31638
|
}
|
|
31639
|
+
onBboxChange(bbox) {
|
|
31640
|
+
console.log(bbox);
|
|
31641
|
+
this.clearSpatialExtentErrorNotification();
|
|
31642
|
+
}
|
|
31643
|
+
onSpatialExtentError(error) {
|
|
31644
|
+
this.clearSpatialExtentErrorNotification();
|
|
31645
|
+
this.spatialExtentErrorNotificationId =
|
|
31646
|
+
this.notificationsService.showNotification({
|
|
31647
|
+
type: 'error',
|
|
31648
|
+
title: this.translateService.instant('search.filters.spatialExtent.error.title'),
|
|
31649
|
+
text: this.translateService.instant(error.key, error.params),
|
|
31650
|
+
});
|
|
31651
|
+
}
|
|
31652
|
+
clearSpatialExtentErrorNotification() {
|
|
31653
|
+
if (this.spatialExtentErrorNotificationId === null)
|
|
31654
|
+
return;
|
|
31655
|
+
this.notificationsService.removeNotificationById(this.spatialExtentErrorNotificationId);
|
|
31656
|
+
this.spatialExtentErrorNotificationId = null;
|
|
31657
|
+
}
|
|
31269
31658
|
ngOnInit() {
|
|
31270
31659
|
this.fieldType = this.fieldsService.getFieldType(this.fieldName);
|
|
31271
31660
|
this.choices$ = this.fieldsService.getAvailableValues(this.fieldName).pipe(startWith$1([]), map$1((values) => values.map((v) => ({
|
|
@@ -31293,7 +31682,7 @@ class FilterDropdownComponent {
|
|
|
31293
31682
|
}
|
|
31294
31683
|
}
|
|
31295
31684
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31296
|
-
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 [startDate]=\"(selectedDateRange$ | async)?.start\"\n [endDate]=\"(selectedDateRange$ | async)?.end\"\n (startDateChange)=\"onStartDateChange($event)\"\n (endDateChange)=\"onEndDateChange($event)\"\n ></gn-ui-date-range-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", "startDate", "endDate"], outputs: ["startDateChange", "endDateChange"] }, { kind: "component", type: DropdownMultiselectComponent, selector: "gn-ui-dropdown-multiselect", inputs: ["title", "choices", "selected", "allowSearch", "maxRows", "searchInputValue"], outputs: ["selectValues"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31685
|
+
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 [startDate]=\"(selectedDateRange$ | async)?.start\"\n [endDate]=\"(selectedDateRange$ | async)?.end\"\n (startDateChange)=\"onStartDateChange($event)\"\n (endDateChange)=\"onEndDateChange($event)\"\n ></gn-ui-date-range-dropdown>\n} @else if (fieldType === 'spatialExtent') {\n <gn-ui-spatial-extent-dropdown\n [title]=\"title\"\n [maxFileSizeMb]=\"spatialExtentMaxFileSize\"\n (bboxChange)=\"onBboxChange($event)\"\n (errorChange)=\"onSpatialExtentError($event)\"\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", "startDate", "endDate"], outputs: ["startDateChange", "endDateChange"] }, { 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"], outputs: ["bboxChange", "errorChange"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31297
31686
|
}
|
|
31298
31687
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterDropdownComponent, decorators: [{
|
|
31299
31688
|
type: Component,
|
|
@@ -31301,7 +31690,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31301
31690
|
CommonModule,
|
|
31302
31691
|
DateRangeDropdownComponent,
|
|
31303
31692
|
DropdownMultiselectComponent,
|
|
31304
|
-
|
|
31693
|
+
SpatialExtentDropdownComponent,
|
|
31694
|
+
], template: "@if (fieldType === 'dateRange') {\n <gn-ui-date-range-dropdown\n [title]=\"title\"\n [startDate]=\"(selectedDateRange$ | async)?.start\"\n [endDate]=\"(selectedDateRange$ | async)?.end\"\n (startDateChange)=\"onStartDateChange($event)\"\n (endDateChange)=\"onEndDateChange($event)\"\n ></gn-ui-date-range-dropdown>\n} @else if (fieldType === 'spatialExtent') {\n <gn-ui-spatial-extent-dropdown\n [title]=\"title\"\n [maxFileSizeMb]=\"spatialExtentMaxFileSize\"\n (bboxChange)=\"onBboxChange($event)\"\n (errorChange)=\"onSpatialExtentError($event)\"\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" }]
|
|
31305
31695
|
}], propDecorators: { fieldName: [{
|
|
31306
31696
|
type: Input
|
|
31307
31697
|
}], title: [{
|
|
@@ -31771,11 +32161,7 @@ const SortByEnum = {
|
|
|
31771
32161
|
RELEVANCY: ['desc', '_score'],
|
|
31772
32162
|
QUALITY_SCORE: ['desc', 'qualityScore'],
|
|
31773
32163
|
CHANGE_DATE: ['desc', 'changeDate'],
|
|
31774
|
-
|
|
31775
|
-
['desc', 'revisionDateForResource'],
|
|
31776
|
-
['desc', 'publicationDateForResource'],
|
|
31777
|
-
['desc', 'creationDateForResource'],
|
|
31778
|
-
],
|
|
32164
|
+
RESOURCE_DATE: ['desc', 'resourceDate.date'],
|
|
31779
32165
|
};
|
|
31780
32166
|
|
|
31781
32167
|
class SortByComponent {
|
|
@@ -31789,7 +32175,7 @@ class SortByComponent {
|
|
|
31789
32175
|
},
|
|
31790
32176
|
{
|
|
31791
32177
|
label: marker('results.sortBy.dateStamp'),
|
|
31792
|
-
value: SortByEnum.
|
|
32178
|
+
value: SortByEnum.RESOURCE_DATE,
|
|
31793
32179
|
},
|
|
31794
32180
|
{
|
|
31795
32181
|
label: marker('results.sortBy.popularity'),
|
|
@@ -31841,74 +32227,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
31841
32227
|
args: ['gnUiSearchStateContainer']
|
|
31842
32228
|
}] } });
|
|
31843
32229
|
|
|
31844
|
-
class NotificationsService {
|
|
31845
|
-
constructor() {
|
|
31846
|
-
this.notifications$ = new BehaviorSubject([]);
|
|
31847
|
-
}
|
|
31848
|
-
showNotification(content, timeoutMs, error) {
|
|
31849
|
-
error && console.error(error);
|
|
31850
|
-
const id = Math.floor(Math.random() * 1000000);
|
|
31851
|
-
this.notifications$.next([...this.notifications$.value, { ...content, id }]);
|
|
31852
|
-
if (typeof timeoutMs === 'undefined')
|
|
31853
|
-
return;
|
|
31854
|
-
setTimeout(() => {
|
|
31855
|
-
this.removeNotificationById(id);
|
|
31856
|
-
}, timeoutMs);
|
|
31857
|
-
}
|
|
31858
|
-
removeNotificationById(id) {
|
|
31859
|
-
this.notifications$.next(this.notifications$.value.filter((n) => n.id !== id));
|
|
31860
|
-
}
|
|
31861
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
31862
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, providedIn: 'root' }); }
|
|
31863
|
-
}
|
|
31864
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsService, decorators: [{
|
|
31865
|
-
type: Injectable,
|
|
31866
|
-
args: [{
|
|
31867
|
-
providedIn: 'root',
|
|
31868
|
-
}]
|
|
31869
|
-
}] });
|
|
31870
|
-
|
|
31871
|
-
class NotificationsContainerComponent {
|
|
31872
|
-
constructor() {
|
|
31873
|
-
this.notificationsService = inject(NotificationsService);
|
|
31874
|
-
}
|
|
31875
|
-
trackById(index, notification) {
|
|
31876
|
-
return notification.id;
|
|
31877
|
-
}
|
|
31878
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31879
|
-
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: [
|
|
31880
|
-
trigger('enterExit', [
|
|
31881
|
-
transition(':enter', [
|
|
31882
|
-
animate('150ms', keyframes([
|
|
31883
|
-
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31884
|
-
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31885
|
-
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31886
|
-
])),
|
|
31887
|
-
]),
|
|
31888
|
-
transition(':leave', [
|
|
31889
|
-
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31890
|
-
]),
|
|
31891
|
-
]),
|
|
31892
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
31893
|
-
}
|
|
31894
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NotificationsContainerComponent, decorators: [{
|
|
31895
|
-
type: Component,
|
|
31896
|
-
args: [{ selector: 'gn-ui-notifications-container', standalone: true, imports: [CommonModule, NotificationComponent], changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
31897
|
-
trigger('enterExit', [
|
|
31898
|
-
transition(':enter', [
|
|
31899
|
-
animate('150ms', keyframes([
|
|
31900
|
-
style({ transform: 'scale(1)', opacity: 0 }),
|
|
31901
|
-
style({ transform: 'scale(1.03)', opacity: 0.5 }),
|
|
31902
|
-
style({ transform: 'scale(1)', opacity: 1 }),
|
|
31903
|
-
])),
|
|
31904
|
-
]),
|
|
31905
|
-
transition(':leave', [
|
|
31906
|
-
animate('200ms', style({ transform: 'translateX(50px)', opacity: 0 })),
|
|
31907
|
-
]),
|
|
31908
|
-
]),
|
|
31909
|
-
], 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" }]
|
|
31910
|
-
}] });
|
|
31911
|
-
|
|
31912
32230
|
class ResultsTableContainerComponent {
|
|
31913
32231
|
constructor() {
|
|
31914
32232
|
this.searchFacade = inject(SearchFacade);
|
|
@@ -32298,11 +32616,11 @@ class AddLayerFromFileComponent {
|
|
|
32298
32616
|
}, 5000);
|
|
32299
32617
|
}
|
|
32300
32618
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AddLayerFromFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32301
|
-
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" }] }); }
|
|
32619
|
+
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" }] }); }
|
|
32302
32620
|
}
|
|
32303
32621
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AddLayerFromFileComponent, decorators: [{
|
|
32304
32622
|
type: Component,
|
|
32305
|
-
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" }]
|
|
32623
|
+
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" }]
|
|
32306
32624
|
}] });
|
|
32307
32625
|
|
|
32308
32626
|
class LayersPanelComponent {
|
|
@@ -32467,8 +32785,7 @@ const closeMetadata = createAction('[Metadata view] close');
|
|
|
32467
32785
|
Related actions
|
|
32468
32786
|
*/
|
|
32469
32787
|
const setRelated = createAction('[Metadata view] Set related records', props());
|
|
32470
|
-
const
|
|
32471
|
-
const setSourceOf = createAction('[Metadata view] Set has sources', props());
|
|
32788
|
+
const setLinkedRecords = createAction('[Metadata view] Set associated records', props());
|
|
32472
32789
|
/*
|
|
32473
32790
|
ChartConfig actions
|
|
32474
32791
|
*/
|
|
@@ -32500,9 +32817,8 @@ var mdview_actions = /*#__PURE__*/Object.freeze({
|
|
|
32500
32817
|
loadUserFeedbacksSuccess: loadUserFeedbacksSuccess,
|
|
32501
32818
|
setChartConfig: setChartConfig,
|
|
32502
32819
|
setIncompleteMetadata: setIncompleteMetadata,
|
|
32503
|
-
|
|
32504
|
-
|
|
32505
|
-
setSources: setSources
|
|
32820
|
+
setLinkedRecords: setLinkedRecords,
|
|
32821
|
+
setRelated: setRelated
|
|
32506
32822
|
});
|
|
32507
32823
|
|
|
32508
32824
|
const METADATA_VIEW_FEATURE_STATE_KEY = 'metadataView';
|
|
@@ -32545,12 +32861,9 @@ on(loadFullMetadata, (state) => ({
|
|
|
32545
32861
|
on(setRelated, (state, { related }) => ({
|
|
32546
32862
|
...state,
|
|
32547
32863
|
related,
|
|
32548
|
-
})), on(
|
|
32864
|
+
})), on(setLinkedRecords, (state, { linkedRecords }) => ({
|
|
32549
32865
|
...state,
|
|
32550
|
-
|
|
32551
|
-
})), on(setSourceOf, (state, { sourceOf }) => ({
|
|
32552
|
-
...state,
|
|
32553
|
-
sourceOf,
|
|
32866
|
+
linkedRecords,
|
|
32554
32867
|
})),
|
|
32555
32868
|
/*
|
|
32556
32869
|
ChartConfig reducers
|
|
@@ -32612,8 +32925,7 @@ const getMetadataError = createSelector(getMdViewState, (state) => state.error);
|
|
|
32612
32925
|
Related selectors
|
|
32613
32926
|
*/
|
|
32614
32927
|
const getRelated = createSelector(getMdViewState, (state) => state.related);
|
|
32615
|
-
const
|
|
32616
|
-
const getSourceOf = createSelector(getMdViewState, (state) => state.sourceOf);
|
|
32928
|
+
const getLinkedRecords = createSelector(getMdViewState, (state) => state.linkedRecords);
|
|
32617
32929
|
/*
|
|
32618
32930
|
Metadata selectors
|
|
32619
32931
|
*/
|
|
@@ -32714,212 +33026,10 @@ function parseHeaders(httpHeaders) {
|
|
|
32714
33026
|
return result;
|
|
32715
33027
|
}
|
|
32716
33028
|
|
|
32717
|
-
|
|
32718
|
-
|
|
32719
|
-
|
|
32720
|
-
? fileExtensionMatches[1].toLowerCase()
|
|
32721
|
-
: null;
|
|
32722
|
-
// 1. type hint
|
|
32723
|
-
if (typeHint)
|
|
32724
|
-
return Promise.resolve(typeHint);
|
|
32725
|
-
// 2. content-type header
|
|
32726
|
-
const headers = await fetchHeaders(url);
|
|
32727
|
-
if ('supportedType' in headers)
|
|
32728
|
-
return headers.supportedType;
|
|
32729
|
-
// 3. file extension from url
|
|
32730
|
-
else if (SupportedTypes.indexOf(fileExtension) > -1)
|
|
32731
|
-
return fileExtension;
|
|
32732
|
-
// no type inferred or hinted
|
|
32733
|
-
if ('mimeType' in headers)
|
|
32734
|
-
throw FetchError.unsupportedType(headers.mimeType);
|
|
32735
|
-
else
|
|
32736
|
-
throw FetchError.unknownType();
|
|
32737
|
-
}
|
|
32738
|
-
function fetchHeaders(url) {
|
|
32739
|
-
return sharedFetch(url, 'HEAD')
|
|
32740
|
-
.catch((error) => {
|
|
32741
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32742
|
-
})
|
|
32743
|
-
.then((response) => {
|
|
32744
|
-
if (!response.ok) {
|
|
32745
|
-
throw FetchError.http(response.status);
|
|
32746
|
-
}
|
|
32747
|
-
return parseHeaders(response.headers);
|
|
32748
|
-
});
|
|
32749
|
-
}
|
|
32750
|
-
function fetchDataAsText(url, cacheActive) {
|
|
32751
|
-
const fetchFactory = () => sharedFetch(url)
|
|
32752
|
-
.catch((error) => {
|
|
32753
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32754
|
-
})
|
|
32755
|
-
.then(async (response) => {
|
|
32756
|
-
if (!response.ok) {
|
|
32757
|
-
const clonedResponse = response.clone();
|
|
32758
|
-
throw FetchError.http(response.status, await clonedResponse.text());
|
|
32759
|
-
}
|
|
32760
|
-
const clonedResponse = response.clone();
|
|
32761
|
-
return clonedResponse.text();
|
|
32762
|
-
});
|
|
32763
|
-
return cacheActive ? useCache(fetchFactory, url, 'asText') : fetchFactory();
|
|
32764
|
-
}
|
|
32765
|
-
function fetchDataAsArrayBuffer(url, cacheActive) {
|
|
32766
|
-
const fetchFactory = () => sharedFetch(url)
|
|
32767
|
-
.catch((error) => {
|
|
32768
|
-
throw FetchError.corsOrNetwork(error.message);
|
|
32769
|
-
})
|
|
32770
|
-
.then(async (response) => {
|
|
32771
|
-
if (!response.ok) {
|
|
32772
|
-
throw FetchError.http(response.status, await response.text());
|
|
32773
|
-
}
|
|
32774
|
-
// convert to a numeric array so that we can store the response in cache
|
|
32775
|
-
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
|
32776
|
-
});
|
|
32777
|
-
return (cacheActive ? useCache(fetchFactory, url, 'asArrayBuffer') : fetchFactory()).then((array) => {
|
|
32778
|
-
return new Uint8Array(array).buffer;
|
|
32779
|
-
});
|
|
32780
|
-
}
|
|
32781
|
-
function tryParseDate(input) {
|
|
32782
|
-
if (typeof input !== 'string')
|
|
32783
|
-
return null;
|
|
32784
|
-
function tryIso(value) {
|
|
32785
|
-
const parsed = parseISO(value);
|
|
32786
|
-
return isNaN(parsed.getDate()) ? null : parsed;
|
|
32787
|
-
}
|
|
32788
|
-
function tryFormat(value, format) {
|
|
32789
|
-
const parsed = parse$4(value, format, new Date());
|
|
32790
|
-
return isNaN(parsed.getDate()) ? null : parsed;
|
|
32791
|
-
}
|
|
32792
|
-
return (tryIso(input) ||
|
|
32793
|
-
tryFormat(input, 'dd/MM/yyyy') ||
|
|
32794
|
-
tryFormat(input, 'dd.MM.yyyy') ||
|
|
32795
|
-
tryFormat(input, 'MM/dd/yyyy') ||
|
|
32796
|
-
null);
|
|
32797
|
-
}
|
|
32798
|
-
function tryParseNumber(input) {
|
|
32799
|
-
if (isNaN(input))
|
|
32800
|
-
return null;
|
|
32801
|
-
const parsed = parseFloat(input);
|
|
32802
|
-
return isNaN(parsed) ? null : parsed;
|
|
32803
|
-
}
|
|
32804
|
-
function jsonToGeojsonFeature(object) {
|
|
32805
|
-
const { id, properties } = Object.keys(object)
|
|
32806
|
-
.map((property) => (property ? property : 'unknown')) //prevent empty strings
|
|
32807
|
-
.reduce((prev, curr) => curr.toLowerCase().endsWith('id')
|
|
32808
|
-
? {
|
|
32809
|
-
...prev,
|
|
32810
|
-
id: object[curr],
|
|
32811
|
-
}
|
|
32812
|
-
: {
|
|
32813
|
-
...prev,
|
|
32814
|
-
properties: { ...prev.properties, [curr]: object[curr] },
|
|
32815
|
-
}, { id: undefined, properties: {} });
|
|
32816
|
-
return {
|
|
32817
|
-
type: 'Feature',
|
|
32818
|
-
geometry: null,
|
|
32819
|
-
properties,
|
|
32820
|
-
...(id !== undefined && { id }),
|
|
32821
|
-
};
|
|
32822
|
-
}
|
|
32823
|
-
function mutateProperties(items, mutators) {
|
|
32824
|
-
const mutatorKeys = Object.keys(mutators);
|
|
32825
|
-
for (let i = 0, ii = items.length; i < ii; i++) {
|
|
32826
|
-
const item = items[i];
|
|
32827
|
-
for (const mutatorField of mutatorKeys) {
|
|
32828
|
-
if (!(mutatorField in item.properties))
|
|
32829
|
-
continue;
|
|
32830
|
-
item.properties[mutatorField] = mutators[mutatorField](item.properties[mutatorField]);
|
|
32831
|
-
}
|
|
32832
|
-
}
|
|
32833
|
-
return items;
|
|
32834
|
-
}
|
|
32835
|
-
const SAMPLE_SIZE = 20;
|
|
32836
|
-
/**
|
|
32837
|
-
* This will infer field types from a list of data items and cast the values accordingly
|
|
32838
|
-
* @param items
|
|
32839
|
-
* @param inferTypes
|
|
32840
|
-
*/
|
|
32841
|
-
function processItemProperties(items, inferTypes = false) {
|
|
32842
|
-
const foundFields = {};
|
|
32843
|
-
for (let i = 0, ii = Math.min(SAMPLE_SIZE, items.length); i < ii; i++) {
|
|
32844
|
-
const item = items[i];
|
|
32845
|
-
const fields = Object.keys(item.properties);
|
|
32846
|
-
for (const field of fields) {
|
|
32847
|
-
if (!(field in foundFields)) {
|
|
32848
|
-
foundFields[field] = {
|
|
32849
|
-
label: field,
|
|
32850
|
-
name: field,
|
|
32851
|
-
type: null,
|
|
32852
|
-
};
|
|
32853
|
-
}
|
|
32854
|
-
const value = item.properties[field];
|
|
32855
|
-
const info = foundFields[field];
|
|
32856
|
-
if (value === undefined || value === '' || value === null)
|
|
32857
|
-
continue;
|
|
32858
|
-
if (!inferTypes) {
|
|
32859
|
-
if (info.type === null && typeof value === 'number') {
|
|
32860
|
-
info.type = 'number';
|
|
32861
|
-
}
|
|
32862
|
-
else if (info.type === 'number' && typeof value !== 'number') {
|
|
32863
|
-
info.type = 'string';
|
|
32864
|
-
}
|
|
32865
|
-
continue;
|
|
32866
|
-
}
|
|
32867
|
-
const parsedNumber = tryParseNumber(value);
|
|
32868
|
-
if (info.type === null && parsedNumber !== null) {
|
|
32869
|
-
info.type = 'number';
|
|
32870
|
-
continue;
|
|
32871
|
-
}
|
|
32872
|
-
else if (info.type === 'number' && parsedNumber === null) {
|
|
32873
|
-
info.type = 'string';
|
|
32874
|
-
continue;
|
|
32875
|
-
}
|
|
32876
|
-
const parsedDate = tryParseDate(value);
|
|
32877
|
-
if (info.type === null && parsedDate !== null) {
|
|
32878
|
-
info.type = 'date';
|
|
32879
|
-
}
|
|
32880
|
-
else if (info.type === 'date' && parsedDate === null) {
|
|
32881
|
-
info.type = 'string';
|
|
32882
|
-
}
|
|
32883
|
-
}
|
|
32884
|
-
}
|
|
32885
|
-
const properties = [];
|
|
32886
|
-
const mutators = {};
|
|
32887
|
-
for (const field in foundFields) {
|
|
32888
|
-
const info = foundFields[field];
|
|
32889
|
-
if (info.type === 'number') {
|
|
32890
|
-
mutators[field] = tryParseNumber;
|
|
32891
|
-
}
|
|
32892
|
-
else if (info.type === 'date') {
|
|
32893
|
-
mutators[field] = tryParseDate;
|
|
32894
|
-
}
|
|
32895
|
-
properties.push({ ...info, type: info.type || 'string' });
|
|
32896
|
-
}
|
|
32897
|
-
if (inferTypes) {
|
|
32898
|
-
mutateProperties(items, mutators);
|
|
32899
|
-
}
|
|
32900
|
-
return { items, properties };
|
|
33029
|
+
const GEOMETRY_COLUMN_ALIAS = '__geometry__';
|
|
33030
|
+
function fieldToSql(name) {
|
|
33031
|
+
return `"${name.replace(/"/g, '""')}"`; // escape double quotes in field names
|
|
32901
33032
|
}
|
|
32902
|
-
/**
|
|
32903
|
-
* This creates a Proxy that allows reading and writing to the data item properties
|
|
32904
|
-
* as if it was a simple array of JSON objects
|
|
32905
|
-
* @param items
|
|
32906
|
-
*/
|
|
32907
|
-
function getJsonDataItemsProxy(items) {
|
|
32908
|
-
return new Proxy(items, {
|
|
32909
|
-
get(target, p) {
|
|
32910
|
-
if (typeof p === 'string' &&
|
|
32911
|
-
!Number.isNaN(parseInt(p)) &&
|
|
32912
|
-
target[p]?.properties) {
|
|
32913
|
-
return target[p].properties;
|
|
32914
|
-
}
|
|
32915
|
-
return target[p];
|
|
32916
|
-
},
|
|
32917
|
-
set() {
|
|
32918
|
-
throw new Error('This object is read-only');
|
|
32919
|
-
},
|
|
32920
|
-
});
|
|
32921
|
-
}
|
|
32922
|
-
|
|
32923
33033
|
function filterToSql(filter) {
|
|
32924
33034
|
const operator = filter[0];
|
|
32925
33035
|
const args = filter.slice(1);
|
|
@@ -32934,10 +33044,10 @@ function filterToSql(filter) {
|
|
|
32934
33044
|
case '=':
|
|
32935
33045
|
case '!=':
|
|
32936
33046
|
case 'like':
|
|
32937
|
-
return
|
|
33047
|
+
return `${fieldToSql(args[0])} ${operator.toUpperCase()} ${valueToSql(args[1])}`;
|
|
32938
33048
|
case 'in': {
|
|
32939
33049
|
const values = args.slice(1);
|
|
32940
|
-
return
|
|
33050
|
+
return `${fieldToSql(args[0])} IN (${values.map(valueToSql).join(', ')})`;
|
|
32941
33051
|
}
|
|
32942
33052
|
case 'and':
|
|
32943
33053
|
case 'or': {
|
|
@@ -32956,17 +33066,18 @@ function aggregationToSql(aggregation) {
|
|
|
32956
33066
|
const field = aggregation[1];
|
|
32957
33067
|
switch (operation) {
|
|
32958
33068
|
case 'average':
|
|
32959
|
-
return `AVG(
|
|
33069
|
+
return `CAST(AVG(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`average(${field})`)}`;
|
|
32960
33070
|
case 'sum':
|
|
32961
33071
|
case 'max':
|
|
32962
33072
|
case 'min':
|
|
32963
|
-
return
|
|
33073
|
+
return `CAST(${operation.toUpperCase()}(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`${operation}(${field})`)}`;
|
|
32964
33074
|
case 'count':
|
|
32965
|
-
return 'COUNT(*) as
|
|
33075
|
+
return 'CAST(COUNT(*) AS INTEGER) as "count()"'; // we don't need Bigint precision here
|
|
32966
33076
|
}
|
|
32967
33077
|
}
|
|
32968
33078
|
/**
|
|
32969
33079
|
* Leave arguments at null if not used
|
|
33080
|
+
* @param tableName
|
|
32970
33081
|
* @param selected
|
|
32971
33082
|
* @param filter
|
|
32972
33083
|
* @param sort
|
|
@@ -32975,22 +33086,25 @@ function aggregationToSql(aggregation) {
|
|
|
32975
33086
|
* @param groupBy
|
|
32976
33087
|
* @param aggregations
|
|
32977
33088
|
*/
|
|
32978
|
-
function generateSqlQuery(selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null) {
|
|
33089
|
+
function generateSqlQuery(tableName, selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null, geometryColumn = null) {
|
|
32979
33090
|
let sqlSelect = 'SELECT *';
|
|
32980
|
-
const sqlFrom =
|
|
33091
|
+
const sqlFrom = ` FROM ${tableName}`;
|
|
32981
33092
|
let sqlOrderBy = '';
|
|
32982
33093
|
let sqlWhere = '';
|
|
32983
33094
|
let sqlLimit = '';
|
|
32984
33095
|
let sqlGroupBy = '';
|
|
32985
33096
|
if (selected !== null) {
|
|
32986
|
-
sqlSelect = `SELECT ${selected.map(
|
|
33097
|
+
sqlSelect = `SELECT ${selected.map(fieldToSql).join(', ')}`;
|
|
33098
|
+
}
|
|
33099
|
+
if (geometryColumn !== null) {
|
|
33100
|
+
sqlSelect += `, ST_AsGeoJSON(${fieldToSql(geometryColumn)}) as ${GEOMETRY_COLUMN_ALIAS}`;
|
|
32987
33101
|
}
|
|
32988
33102
|
if (filter !== null) {
|
|
32989
33103
|
sqlWhere = ` WHERE ${filterToSql(filter)}`;
|
|
32990
33104
|
}
|
|
32991
33105
|
if (sort?.length) {
|
|
32992
33106
|
sqlOrderBy = ` ORDER BY ${sort
|
|
32993
|
-
.map((sort) =>
|
|
33107
|
+
.map((sort) => `${fieldToSql(sort[1])} ${sort[0].toUpperCase()}`)
|
|
32994
33108
|
.join(', ')}`;
|
|
32995
33109
|
}
|
|
32996
33110
|
if (startIndex !== null && count !== null) {
|
|
@@ -33000,17 +33114,212 @@ function generateSqlQuery(selected = null, filter = null, sort = null, startInde
|
|
|
33000
33114
|
sqlSelect = `SELECT ${aggregations.map(aggregationToSql).join(', ')}`;
|
|
33001
33115
|
const groupedByDistinct = groupBy.filter((group) => group[0] === 'distinct');
|
|
33002
33116
|
const sqlGroupByFields = groupedByDistinct
|
|
33003
|
-
.map((group) =>
|
|
33117
|
+
.map((group) => fieldToSql(group[1]))
|
|
33004
33118
|
.join(', ');
|
|
33005
33119
|
const sqlGroupBySelect = groupedByDistinct
|
|
33006
|
-
.map((group) =>
|
|
33120
|
+
.map((group) => `${fieldToSql(group[1])} as ${fieldToSql(`distinct(${group[1]})`)}`)
|
|
33007
33121
|
.join(', ');
|
|
33008
33122
|
if (sqlGroupByFields && sqlGroupBySelect) {
|
|
33009
33123
|
sqlGroupBy = ` GROUP BY ${sqlGroupByFields}`;
|
|
33010
33124
|
sqlSelect += `, ${sqlGroupBySelect}`;
|
|
33011
33125
|
}
|
|
33012
33126
|
}
|
|
33013
|
-
return sqlSelect + sqlFrom + sqlGroupBy +
|
|
33127
|
+
return sqlSelect + sqlFrom + sqlGroupBy + sqlWhere + sqlOrderBy + sqlLimit;
|
|
33128
|
+
}
|
|
33129
|
+
|
|
33130
|
+
function arrowTableToDataItems(table) {
|
|
33131
|
+
const fields = table.schema.fields;
|
|
33132
|
+
return table.toArray().map((row) => {
|
|
33133
|
+
const rowJson = row.toJSON();
|
|
33134
|
+
const feature = {
|
|
33135
|
+
type: 'Feature',
|
|
33136
|
+
geometry: null,
|
|
33137
|
+
properties: {},
|
|
33138
|
+
};
|
|
33139
|
+
const keys = Object.keys(rowJson);
|
|
33140
|
+
for (let i = 0; i < keys.length; i++) {
|
|
33141
|
+
const key = keys[i];
|
|
33142
|
+
const dataType = fields[i].type;
|
|
33143
|
+
let value = rowJson[key];
|
|
33144
|
+
// this might happen if we get an array inside a field
|
|
33145
|
+
if (value instanceof Vector) {
|
|
33146
|
+
value = Array.from(value);
|
|
33147
|
+
}
|
|
33148
|
+
// cast bigints to ints
|
|
33149
|
+
if (typeof value === 'bigint') {
|
|
33150
|
+
value = Number(value);
|
|
33151
|
+
}
|
|
33152
|
+
// rename columns with empty name
|
|
33153
|
+
if (!key) {
|
|
33154
|
+
feature.properties['unknown'] = value;
|
|
33155
|
+
continue;
|
|
33156
|
+
}
|
|
33157
|
+
// assign properties that look like an id to the geojson `id` field
|
|
33158
|
+
if (/^(object|feature)?_?id$/.test(key.toLowerCase()) &&
|
|
33159
|
+
(typeof value == 'string' || typeof value === 'number')) {
|
|
33160
|
+
feature.id = value;
|
|
33161
|
+
}
|
|
33162
|
+
// if a date is in timestamp (number) format, convert it to native
|
|
33163
|
+
if (typeof value === 'number' &&
|
|
33164
|
+
(DataType.isTimestamp(dataType) || DataType.isDate(dataType))) {
|
|
33165
|
+
value = new Date(value);
|
|
33166
|
+
}
|
|
33167
|
+
// if a binary field (most likely a geometry column): skip
|
|
33168
|
+
if (DataType.isBinary(dataType)) {
|
|
33169
|
+
continue;
|
|
33170
|
+
}
|
|
33171
|
+
// geometry column
|
|
33172
|
+
if (key === GEOMETRY_COLUMN_ALIAS && DataType.isUtf8(dataType)) {
|
|
33173
|
+
feature.geometry = JSON.parse(value);
|
|
33174
|
+
continue;
|
|
33175
|
+
}
|
|
33176
|
+
feature.properties[key] = value;
|
|
33177
|
+
}
|
|
33178
|
+
return feature;
|
|
33179
|
+
});
|
|
33180
|
+
}
|
|
33181
|
+
|
|
33182
|
+
// init code taken from https://github.com/duckdb/duckdb-wasm/blob/main/packages/duckdb-wasm/README.md
|
|
33183
|
+
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
|
|
33184
|
+
// from https://duckdb.org/docs/current/sql/data_types/overview
|
|
33185
|
+
const typesMapping = {
|
|
33186
|
+
INTEGER: 'number',
|
|
33187
|
+
SMALLINT: 'number',
|
|
33188
|
+
TINYINT: 'number',
|
|
33189
|
+
BIGINT: 'number',
|
|
33190
|
+
HUGEINT: 'number',
|
|
33191
|
+
UINTEGER: 'number',
|
|
33192
|
+
USMALLINT: 'number',
|
|
33193
|
+
UTINYINT: 'number',
|
|
33194
|
+
UBIGINT: 'number',
|
|
33195
|
+
UHUGEINT: 'number',
|
|
33196
|
+
DOUBLE: 'number',
|
|
33197
|
+
BIGNUM: 'number',
|
|
33198
|
+
DECIMAL: 'number',
|
|
33199
|
+
NUMERIC: 'number',
|
|
33200
|
+
FLOAT: 'number',
|
|
33201
|
+
REAL: 'number',
|
|
33202
|
+
'TIMESTAMP WITH TIME ZONE': 'date',
|
|
33203
|
+
TIMESTAMP: 'date',
|
|
33204
|
+
DATE: 'date',
|
|
33205
|
+
CHAR: 'string',
|
|
33206
|
+
VARCHAR: 'string',
|
|
33207
|
+
TEXT: 'string',
|
|
33208
|
+
UUID: 'string',
|
|
33209
|
+
BLOB: 'string',
|
|
33210
|
+
BIT: 'string',
|
|
33211
|
+
INTERVAL: 'string',
|
|
33212
|
+
LIST: 'string',
|
|
33213
|
+
BOOLEAN: 'boolean',
|
|
33214
|
+
};
|
|
33215
|
+
class Engine {
|
|
33216
|
+
async makeInit() {
|
|
33217
|
+
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
|
|
33218
|
+
let worker_url = bundle.mainWorker;
|
|
33219
|
+
// this is necessary to let browsers execute WASM code coming from a cross-origin host
|
|
33220
|
+
if (worker_url.startsWith('https://')) {
|
|
33221
|
+
worker_url = URL.createObjectURL(new Blob([`importScripts("${worker_url}");`], {
|
|
33222
|
+
type: 'text/javascript',
|
|
33223
|
+
}));
|
|
33224
|
+
}
|
|
33225
|
+
const worker = new Worker(worker_url);
|
|
33226
|
+
const logger = new duckdb.ConsoleLogger(duckdb.LogLevel.WARNING);
|
|
33227
|
+
this.db = new duckdb.AsyncDuckDB(logger, worker);
|
|
33228
|
+
await this.db.instantiate(bundle.mainModule, bundle.pthreadWorker);
|
|
33229
|
+
// setup duckdb options
|
|
33230
|
+
const conn = await this.db.connect();
|
|
33231
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
33232
|
+
await conn.query(`INSTALL spatial; LOAD spatial;`);
|
|
33233
|
+
await conn.query(`SET TimeZone = '${timezone}';`);
|
|
33234
|
+
await conn.query(`SET threads = 1;`);
|
|
33235
|
+
// await conn.query(`SET memory_limit = '2GB';`) // used for experimenting when we encounter memory issues
|
|
33236
|
+
await conn.query(`SET preserve_insertion_order = false;`); // this reduces memory usage when loading a dataset
|
|
33237
|
+
conn.close();
|
|
33238
|
+
return this;
|
|
33239
|
+
}
|
|
33240
|
+
isReady() {
|
|
33241
|
+
if (!this.init_) {
|
|
33242
|
+
this.init_ = this.makeInit();
|
|
33243
|
+
}
|
|
33244
|
+
return this.init_;
|
|
33245
|
+
}
|
|
33246
|
+
/**
|
|
33247
|
+
* Returns information about a dataset once it's loaded:
|
|
33248
|
+
* - a list of properties description
|
|
33249
|
+
* - the name of the dataset geometry column (null if no geometry present)
|
|
33250
|
+
* @param datasetId name of the table under which the dataset will be stored
|
|
33251
|
+
* @param loadQuery duckdb-specific query for creating a table out of the data
|
|
33252
|
+
* @param forceReload if true, any existing data will be dropped and redownloaded
|
|
33253
|
+
*/
|
|
33254
|
+
async loadFile(datasetId, loadQuery, forceReload = false) {
|
|
33255
|
+
const conn = await this.db.connect();
|
|
33256
|
+
let results;
|
|
33257
|
+
// either we want to recreate the table, or we keep it if it already exists
|
|
33258
|
+
const safeLoadQuery = forceReload
|
|
33259
|
+
? `DROP TABLE IF EXISTS ${datasetId};
|
|
33260
|
+
${loadQuery}`
|
|
33261
|
+
: loadQuery.replace(/CREATE TABLE(?! IF NOT EXISTS)/gi, 'CREATE TABLE IF NOT EXISTS');
|
|
33262
|
+
// create the table
|
|
33263
|
+
try {
|
|
33264
|
+
results = await conn.query(safeLoadQuery);
|
|
33265
|
+
}
|
|
33266
|
+
catch (e) {
|
|
33267
|
+
throw new FetchError('parse', `DuckDB encountered an error when loading the data: ${e.message}`);
|
|
33268
|
+
}
|
|
33269
|
+
// read rows count
|
|
33270
|
+
results = await conn.query(`SELECT count(*) FROM ${datasetId}`);
|
|
33271
|
+
const { 'count_star()': recordsCount } = results.toArray()[0].toJSON();
|
|
33272
|
+
// read columns
|
|
33273
|
+
results = await conn.query(`SELECT * FROM information_schema.columns WHERE table_name = '${datasetId}';`);
|
|
33274
|
+
let geometryColumn = null;
|
|
33275
|
+
const properties = results
|
|
33276
|
+
.toArray()
|
|
33277
|
+
.map((row) => {
|
|
33278
|
+
const rowObj = row.toJSON();
|
|
33279
|
+
if (rowObj['data_type'] === 'GEOMETRY') {
|
|
33280
|
+
// the geometry is not part of the properties
|
|
33281
|
+
// note: right now we only keep one geometry column name, but if there are multiple they will
|
|
33282
|
+
// all get discarded
|
|
33283
|
+
geometryColumn = rowObj['column_name'];
|
|
33284
|
+
return null;
|
|
33285
|
+
}
|
|
33286
|
+
return {
|
|
33287
|
+
name: rowObj['column_name'],
|
|
33288
|
+
label: rowObj['column_name'],
|
|
33289
|
+
type: typesMapping[rowObj['data_type']] ?? 'other',
|
|
33290
|
+
};
|
|
33291
|
+
})
|
|
33292
|
+
.filter((prop) => prop !== null);
|
|
33293
|
+
conn.close();
|
|
33294
|
+
return {
|
|
33295
|
+
properties,
|
|
33296
|
+
geometryColumn,
|
|
33297
|
+
rowsCount: Number(recordsCount),
|
|
33298
|
+
};
|
|
33299
|
+
}
|
|
33300
|
+
// register a Uint8 buffer using a handle in the duckdb instance
|
|
33301
|
+
async registerData(name, buffer) {
|
|
33302
|
+
return this.db.registerFileBuffer(name, buffer);
|
|
33303
|
+
}
|
|
33304
|
+
/**
|
|
33305
|
+
* @param query duckdb-specific query for fetching items
|
|
33306
|
+
*/
|
|
33307
|
+
async queryItems(query) {
|
|
33308
|
+
const conn = await this.db.connect();
|
|
33309
|
+
const results = await conn.query(query);
|
|
33310
|
+
conn.close();
|
|
33311
|
+
return arrowTableToDataItems(results);
|
|
33312
|
+
}
|
|
33313
|
+
close() {
|
|
33314
|
+
this.db?.terminate();
|
|
33315
|
+
}
|
|
33316
|
+
}
|
|
33317
|
+
let engine = null;
|
|
33318
|
+
async function getEngine() {
|
|
33319
|
+
if (!engine) {
|
|
33320
|
+
engine = new Engine();
|
|
33321
|
+
}
|
|
33322
|
+
return engine.isReady();
|
|
33014
33323
|
}
|
|
33015
33324
|
|
|
33016
33325
|
class BaseReader {
|
|
@@ -33023,10 +33332,18 @@ class BaseReader {
|
|
|
33023
33332
|
this.sort = null;
|
|
33024
33333
|
this.startIndex = null;
|
|
33025
33334
|
this.count = null;
|
|
33335
|
+
this.loadPromise_ = Promise.resolve();
|
|
33336
|
+
this.cacheEnabled = false;
|
|
33337
|
+
}
|
|
33338
|
+
enableCache(enabled) {
|
|
33339
|
+
this.cacheEnabled = enabled;
|
|
33026
33340
|
}
|
|
33027
33341
|
load() {
|
|
33028
33342
|
throw new Error('not implemented');
|
|
33029
33343
|
}
|
|
33344
|
+
get isLoaded() {
|
|
33345
|
+
return this.loadPromise_;
|
|
33346
|
+
}
|
|
33030
33347
|
get properties() {
|
|
33031
33348
|
throw new Error('not implemented');
|
|
33032
33349
|
}
|
|
@@ -33075,178 +33392,237 @@ class BaseReader {
|
|
|
33075
33392
|
}
|
|
33076
33393
|
}
|
|
33077
33394
|
|
|
33078
|
-
|
|
33079
|
-
|
|
33080
|
-
|
|
33081
|
-
|
|
33082
|
-
|
|
33083
|
-
|
|
33084
|
-
|
|
33085
|
-
|
|
33086
|
-
|
|
33087
|
-
|
|
33088
|
-
|
|
33089
|
-
|
|
33090
|
-
|
|
33395
|
+
/**
|
|
33396
|
+
* This reader handles file formats supported natively by DuckDB
|
|
33397
|
+
*/
|
|
33398
|
+
class BaseFileReader extends BaseReader {
|
|
33399
|
+
// a table id should not exceed 63 chars
|
|
33400
|
+
generateDatasetId() {
|
|
33401
|
+
// generate a hash out of the url
|
|
33402
|
+
let hash = 0;
|
|
33403
|
+
for (const char of this.url) {
|
|
33404
|
+
hash = (hash << 5) - hash + char.charCodeAt(0);
|
|
33405
|
+
hash = hash >>> 0; // make it unsigned
|
|
33406
|
+
}
|
|
33407
|
+
return `datafetcher_${hash.toString(16)}`;
|
|
33408
|
+
}
|
|
33409
|
+
async getLoadQuery() {
|
|
33091
33410
|
throw new Error('not implemented');
|
|
33092
33411
|
}
|
|
33093
|
-
load() {
|
|
33094
|
-
this.
|
|
33412
|
+
async load() {
|
|
33413
|
+
this.datasetId = this.generateDatasetId();
|
|
33414
|
+
this.loadPromise_ = getEngine()
|
|
33415
|
+
.then((engine) => {
|
|
33416
|
+
this.engine = engine;
|
|
33417
|
+
return this.getLoadQuery();
|
|
33418
|
+
})
|
|
33419
|
+
.then((loadQuery) => this.engine.loadFile(this.datasetId, loadQuery, !this.cacheEnabled))
|
|
33420
|
+
.then((datasetInfo) => {
|
|
33421
|
+
this.properties_ = datasetInfo.properties;
|
|
33422
|
+
this.geometryColumn = datasetInfo.geometryColumn;
|
|
33423
|
+
this.rowsCount = datasetInfo.rowsCount;
|
|
33424
|
+
// returns void for the loaded promise
|
|
33425
|
+
});
|
|
33095
33426
|
}
|
|
33096
33427
|
get properties() {
|
|
33097
|
-
return this.
|
|
33428
|
+
return this.isLoaded.then(() => this.properties_);
|
|
33098
33429
|
}
|
|
33099
33430
|
get info() {
|
|
33100
|
-
return this.
|
|
33101
|
-
itemsCount:
|
|
33431
|
+
return this.isLoaded.then(() => ({
|
|
33432
|
+
itemsCount: this.rowsCount,
|
|
33433
|
+
hasGeometry: !!this.geometryColumn,
|
|
33102
33434
|
}));
|
|
33103
33435
|
}
|
|
33104
33436
|
async read() {
|
|
33105
|
-
|
|
33106
|
-
//
|
|
33107
|
-
|
|
33108
|
-
|
|
33109
|
-
|
|
33110
|
-
this.sort == null &&
|
|
33111
|
-
this.filter == null &&
|
|
33112
|
-
this.startIndex == null &&
|
|
33113
|
-
this.count == null) {
|
|
33114
|
-
return items;
|
|
33115
|
-
}
|
|
33116
|
-
const jsonItems = getJsonDataItemsProxy(items);
|
|
33117
|
-
const query = generateSqlQuery(this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations);
|
|
33118
|
-
const result = await import('alasql').then((module) => module.default(query, [jsonItems]));
|
|
33119
|
-
return result.map(jsonToGeojsonFeature);
|
|
33120
|
-
}
|
|
33121
|
-
}
|
|
33122
|
-
|
|
33123
|
-
function parseCsv(text) {
|
|
33124
|
-
// first parse the header to guess the delimiter
|
|
33125
|
-
// note that we do that to not rely on Papaparse logic for guessing delimiter
|
|
33126
|
-
let delimiter;
|
|
33127
|
-
try {
|
|
33128
|
-
const header = text.split('\n')[0];
|
|
33129
|
-
const result = Papa.parse(header, {
|
|
33130
|
-
header: false,
|
|
33131
|
-
});
|
|
33132
|
-
delimiter = result.meta.delimiter;
|
|
33437
|
+
await this.isLoaded;
|
|
33438
|
+
// if only certain fields are selected, omit the geometry
|
|
33439
|
+
const geometryColumn = this.selected === null ? this.geometryColumn : null;
|
|
33440
|
+
const query = generateSqlQuery(this.datasetId, this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations, geometryColumn);
|
|
33441
|
+
return this.engine.queryItems(query);
|
|
33133
33442
|
}
|
|
33134
|
-
catch (e) {
|
|
33135
|
-
throw new Error('CSV parsing failed: the delimiter could not be guessed');
|
|
33136
|
-
}
|
|
33137
|
-
const parsed = Papa.parse(text, {
|
|
33138
|
-
header: true,
|
|
33139
|
-
skipEmptyLines: true,
|
|
33140
|
-
delimiter,
|
|
33141
|
-
});
|
|
33142
|
-
if (parsed.errors.length) {
|
|
33143
|
-
throw new Error('CSV parsing failed for the following reasons:\n' +
|
|
33144
|
-
parsed.errors
|
|
33145
|
-
.map((error) => `* ${error.message} at row ${error.row}, column ${error.index}`)
|
|
33146
|
-
.join('\n'));
|
|
33147
|
-
}
|
|
33148
|
-
const items = parsed.data.map(jsonToGeojsonFeature);
|
|
33149
|
-
return processItemProperties(items, true);
|
|
33150
33443
|
}
|
|
33444
|
+
|
|
33151
33445
|
class CsvReader extends BaseFileReader {
|
|
33152
|
-
|
|
33153
|
-
|
|
33446
|
+
async getLoadQuery() {
|
|
33447
|
+
// first we get a list of columns hich have a detected type of VARCHAR
|
|
33448
|
+
// 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
|
|
33449
|
+
return `
|
|
33450
|
+
SET VARIABLE strColumns = (SELECT list(name) FROM (SELECT unnest(Columns, recursive := true) FROM sniff_csv("${this.url}")) WHERE type = 'VARCHAR');
|
|
33451
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_csv("${this.url}",
|
|
33452
|
+
force_not_null = getvariable('strColumns'),
|
|
33453
|
+
auto_type_candidates = ['NULL', 'BOOLEAN', 'INTEGER', 'DOUBLE', 'DATE', 'VARCHAR']
|
|
33454
|
+
);`;
|
|
33154
33455
|
}
|
|
33155
33456
|
}
|
|
33156
33457
|
|
|
33157
|
-
/**
|
|
33158
|
-
* This parser only supports arrays of simple flat objects with properties
|
|
33159
|
-
* @param text
|
|
33160
|
-
*/
|
|
33161
|
-
function parseJson(text) {
|
|
33162
|
-
const parsed = JSON.parse(text);
|
|
33163
|
-
if (!Array.isArray(parsed)) {
|
|
33164
|
-
throw new Error('Could not parse JSON, expected an array at root level');
|
|
33165
|
-
}
|
|
33166
|
-
return processItemProperties(parsed.map(jsonToGeojsonFeature));
|
|
33167
|
-
}
|
|
33168
33458
|
class JsonReader extends BaseFileReader {
|
|
33169
|
-
|
|
33170
|
-
return
|
|
33459
|
+
async getLoadQuery() {
|
|
33460
|
+
return `
|
|
33461
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_json("${this.url}",
|
|
33462
|
+
maximum_object_size = 536870912 -- 500MB
|
|
33463
|
+
);`;
|
|
33171
33464
|
}
|
|
33172
33465
|
}
|
|
33173
33466
|
|
|
33174
|
-
/**
|
|
33175
|
-
* This parser supports both Geojson Feature collections or arrays
|
|
33176
|
-
* of Features
|
|
33177
|
-
* @param text
|
|
33178
|
-
*/
|
|
33179
|
-
function parseGeojson(text) {
|
|
33180
|
-
const parsed = JSON.parse(text);
|
|
33181
|
-
const features = parsed.type === 'FeatureCollection' ? parsed.features : parsed;
|
|
33182
|
-
if (!Array.isArray(features)) {
|
|
33183
|
-
throw new Error('Could not parse GeoJSON, expected a features collection or an array of features at root level');
|
|
33184
|
-
}
|
|
33185
|
-
return processItemProperties(features);
|
|
33186
|
-
}
|
|
33187
33467
|
class GeojsonReader extends BaseFileReader {
|
|
33188
|
-
|
|
33189
|
-
return
|
|
33468
|
+
async getLoadQuery() {
|
|
33469
|
+
return `
|
|
33470
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33471
|
+
allowed_drivers = ['GeoJSON']
|
|
33472
|
+
);`;
|
|
33190
33473
|
}
|
|
33191
33474
|
}
|
|
33192
33475
|
|
|
33476
|
+
async function inferDatasetType(url, typeHint) {
|
|
33477
|
+
const fileExtensionMatches = new URL(url, typeof window !== 'undefined' ? window.location.toString() : undefined).pathname.match(/\.(.+)$/);
|
|
33478
|
+
const fileExtension = fileExtensionMatches && fileExtensionMatches.length
|
|
33479
|
+
? fileExtensionMatches[1].toLowerCase()
|
|
33480
|
+
: null;
|
|
33481
|
+
// 1. type hint
|
|
33482
|
+
if (typeHint)
|
|
33483
|
+
return Promise.resolve(typeHint);
|
|
33484
|
+
// 2. content-type header
|
|
33485
|
+
const headers = await fetchHeaders(url);
|
|
33486
|
+
if ('supportedType' in headers)
|
|
33487
|
+
return headers.supportedType;
|
|
33488
|
+
// 3. file extension from url
|
|
33489
|
+
else if (SupportedTypes.indexOf(fileExtension) > -1)
|
|
33490
|
+
return fileExtension;
|
|
33491
|
+
// no type inferred or hinted
|
|
33492
|
+
if ('mimeType' in headers)
|
|
33493
|
+
throw FetchError.unsupportedType(headers.mimeType);
|
|
33494
|
+
else
|
|
33495
|
+
throw FetchError.unknownType();
|
|
33496
|
+
}
|
|
33497
|
+
function fetchHeaders(url) {
|
|
33498
|
+
return sharedFetch(url, 'HEAD')
|
|
33499
|
+
.catch((error) => {
|
|
33500
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33501
|
+
})
|
|
33502
|
+
.then((response) => {
|
|
33503
|
+
if (!response.ok) {
|
|
33504
|
+
throw FetchError.http(response.status);
|
|
33505
|
+
}
|
|
33506
|
+
return parseHeaders(response.headers);
|
|
33507
|
+
});
|
|
33508
|
+
}
|
|
33509
|
+
function fetchDataAsText(url, cacheActive) {
|
|
33510
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33511
|
+
.catch((error) => {
|
|
33512
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33513
|
+
})
|
|
33514
|
+
.then(async (response) => {
|
|
33515
|
+
if (!response.ok) {
|
|
33516
|
+
const clonedResponse = response.clone();
|
|
33517
|
+
throw FetchError.http(response.status, await clonedResponse.text());
|
|
33518
|
+
}
|
|
33519
|
+
const clonedResponse = response.clone();
|
|
33520
|
+
return clonedResponse.text();
|
|
33521
|
+
});
|
|
33522
|
+
return cacheActive ? useCache(fetchFactory, url, 'asText') : fetchFactory();
|
|
33523
|
+
}
|
|
33524
|
+
function fetchDataAsArrayBuffer(url, cacheActive) {
|
|
33525
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33526
|
+
.catch((error) => {
|
|
33527
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33528
|
+
})
|
|
33529
|
+
.then(async (response) => {
|
|
33530
|
+
if (!response.ok) {
|
|
33531
|
+
throw FetchError.http(response.status, await response.text());
|
|
33532
|
+
}
|
|
33533
|
+
// convert to a numeric array so that we can store the response in cache
|
|
33534
|
+
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
|
33535
|
+
});
|
|
33536
|
+
return (cacheActive ? useCache(fetchFactory, url, 'asArrayBuffer') : fetchFactory()).then((array) => {
|
|
33537
|
+
return new Uint8Array(array).buffer;
|
|
33538
|
+
});
|
|
33539
|
+
}
|
|
33193
33540
|
/**
|
|
33194
|
-
* This
|
|
33195
|
-
*
|
|
33196
|
-
* @param
|
|
33541
|
+
* This creates a Proxy that allows reading and writing to the data item properties
|
|
33542
|
+
* as if it was a simple array of JSON objects
|
|
33543
|
+
* @param items
|
|
33197
33544
|
*/
|
|
33198
|
-
function
|
|
33199
|
-
return
|
|
33200
|
-
|
|
33201
|
-
|
|
33202
|
-
|
|
33203
|
-
|
|
33204
|
-
|
|
33205
|
-
|
|
33206
|
-
|
|
33545
|
+
function getJsonDataItemsProxy(items) {
|
|
33546
|
+
return new Proxy(items, {
|
|
33547
|
+
get(target, p) {
|
|
33548
|
+
if (typeof p === 'string' &&
|
|
33549
|
+
!Number.isNaN(parseInt(p)) &&
|
|
33550
|
+
target[p]?.properties) {
|
|
33551
|
+
return target[p].properties;
|
|
33552
|
+
}
|
|
33553
|
+
return target[p];
|
|
33554
|
+
},
|
|
33555
|
+
set() {
|
|
33556
|
+
throw new Error('This object is read-only');
|
|
33557
|
+
},
|
|
33207
33558
|
});
|
|
33208
33559
|
}
|
|
33560
|
+
|
|
33209
33561
|
class ExcelReader extends BaseFileReader {
|
|
33210
|
-
|
|
33211
|
-
|
|
33562
|
+
async getLoadQuery() {
|
|
33563
|
+
// we download the file as an array buffer first, in order to be able to check if it's an XLS file
|
|
33564
|
+
let buffer = await fetchDataAsArrayBuffer(this.url, this.cacheEnabled);
|
|
33565
|
+
const bufferHandle = `B${this.datasetId}`;
|
|
33566
|
+
// checking against the magic number at the beginning of XLS files, see https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
33567
|
+
const magicNumber = new Uint8Array(buffer, 0, 8); // first 8 bytes
|
|
33568
|
+
const isXls = Array.from(magicNumber)
|
|
33569
|
+
.map((n) => n.toString(16).toUpperCase())
|
|
33570
|
+
.join(' ') === 'D0 CF 11 E0 A1 B1 1A E1';
|
|
33571
|
+
// uh oh, this is an XLS file (not supported by duckdb); convert it to CSV using the xlsx package
|
|
33572
|
+
if (isXls) {
|
|
33573
|
+
buffer = await import('xlsx').then(({ read, utils }) => {
|
|
33574
|
+
const workbook = read(buffer);
|
|
33575
|
+
const json = utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
|
|
33576
|
+
return new TextEncoder().encode(JSON.stringify(json)).buffer;
|
|
33577
|
+
});
|
|
33578
|
+
}
|
|
33579
|
+
const duckDbFn = isXls ? 'read_json' : 'read_xlsx';
|
|
33580
|
+
await this.engine.registerData(bufferHandle, new Uint8Array(buffer));
|
|
33581
|
+
return `
|
|
33582
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM ${duckDbFn}("${bufferHandle}", ignore_errors = true);`;
|
|
33583
|
+
}
|
|
33584
|
+
}
|
|
33585
|
+
|
|
33586
|
+
class GmlReader extends BaseFileReader {
|
|
33587
|
+
async getLoadQuery() {
|
|
33588
|
+
return `
|
|
33589
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33590
|
+
allowed_drivers = ['GML']
|
|
33591
|
+
);`;
|
|
33212
33592
|
}
|
|
33213
33593
|
}
|
|
33214
33594
|
|
|
33215
|
-
|
|
33216
|
-
|
|
33217
|
-
const
|
|
33595
|
+
const formatGeojson = new GeoJSON$1();
|
|
33596
|
+
function parseGeojson(text) {
|
|
33597
|
+
const parsed = JSON.parse(text);
|
|
33598
|
+
const features = parsed.type === 'FeatureCollection' ? parsed.features : parsed;
|
|
33599
|
+
if (!Array.isArray(features)) {
|
|
33600
|
+
throw new Error('Could not parse GeoJSON, expected a features collection or an array of features at root level');
|
|
33601
|
+
}
|
|
33602
|
+
return features;
|
|
33603
|
+
}
|
|
33604
|
+
function parseGml(text, featureType, version) {
|
|
33605
|
+
const parts = featureType.split(':');
|
|
33606
|
+
const regex = new RegExp(`xmlns:${parts[0]}=["']([^'"]*)["']`);
|
|
33218
33607
|
const match = regex.exec(text);
|
|
33219
33608
|
if (match && match.length >= 2) {
|
|
33220
|
-
const
|
|
33609
|
+
const wfs = new WFS({
|
|
33221
33610
|
featureNS: match[1],
|
|
33222
|
-
featureType:
|
|
33611
|
+
featureType: parts[1],
|
|
33223
33612
|
version: version,
|
|
33224
33613
|
});
|
|
33225
33614
|
let features;
|
|
33226
33615
|
try {
|
|
33227
|
-
features =
|
|
33616
|
+
features = wfs.readFeatures(text);
|
|
33228
33617
|
}
|
|
33229
33618
|
catch (e) {
|
|
33230
|
-
throw Error(
|
|
33619
|
+
throw Error(`Couldn't parse WFS with GML features: ${e.message}`);
|
|
33231
33620
|
}
|
|
33232
|
-
const geojsonItem =
|
|
33233
|
-
return
|
|
33621
|
+
const geojsonItem = formatGeojson.writeFeaturesObject(features);
|
|
33622
|
+
return geojsonItem.features;
|
|
33234
33623
|
}
|
|
33235
33624
|
throw Error("Couldn't retrieve namespace url");
|
|
33236
33625
|
}
|
|
33237
|
-
class GmlReader extends BaseFileReader {
|
|
33238
|
-
constructor(url, namespace, version, cacheActive = true) {
|
|
33239
|
-
super(url);
|
|
33240
|
-
this.url = url;
|
|
33241
|
-
this.namespace = namespace;
|
|
33242
|
-
this.version = version;
|
|
33243
|
-
this.cacheActive = cacheActive;
|
|
33244
|
-
}
|
|
33245
|
-
getData() {
|
|
33246
|
-
return fetchDataAsText(this.url, this.cacheActive).then((text) => parseGml(text, this.namespace, this.version));
|
|
33247
|
-
}
|
|
33248
|
-
}
|
|
33249
|
-
|
|
33250
33626
|
async function getWfsEndpoint(wfsUrl) {
|
|
33251
33627
|
try {
|
|
33252
33628
|
return await new WfsEndpoint(wfsUrl).isReady();
|
|
@@ -33274,21 +33650,65 @@ async function getWfsEndpoint(wfsUrl) {
|
|
|
33274
33650
|
}
|
|
33275
33651
|
}
|
|
33276
33652
|
}
|
|
33277
|
-
class WfsReader extends
|
|
33278
|
-
constructor(url,
|
|
33279
|
-
super(url
|
|
33280
|
-
this.endpoint =
|
|
33281
|
-
this.
|
|
33282
|
-
|
|
33653
|
+
class WfsReader extends BaseReader {
|
|
33654
|
+
constructor(url, featureTypeName) {
|
|
33655
|
+
super(url);
|
|
33656
|
+
this.endpoint = getWfsEndpoint(url);
|
|
33657
|
+
this.featureType = this.endpoint
|
|
33658
|
+
.then((endpoint) => {
|
|
33659
|
+
const featureTypes = endpoint.getFeatureTypes();
|
|
33660
|
+
return endpoint.getFeatureTypeFull(featureTypes.length === 1 && !featureTypeName
|
|
33661
|
+
? featureTypes[0].name
|
|
33662
|
+
: featureTypeName);
|
|
33663
|
+
})
|
|
33664
|
+
.then((featureType) => {
|
|
33665
|
+
if (!featureType) {
|
|
33666
|
+
throw new Error('wfs.featuretype.notfound');
|
|
33667
|
+
}
|
|
33668
|
+
return featureType;
|
|
33669
|
+
});
|
|
33670
|
+
}
|
|
33671
|
+
get backupReader() {
|
|
33672
|
+
if (this.backupReader_) {
|
|
33673
|
+
return this.backupReader_;
|
|
33674
|
+
}
|
|
33675
|
+
this.backupReader_ = Promise.all([this.endpoint, this.featureType]).then(([endpoint, featureType]) => {
|
|
33676
|
+
let reader;
|
|
33677
|
+
if (endpoint.supportsJson(featureType.name)) {
|
|
33678
|
+
reader = new GeojsonReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33679
|
+
asJson: true,
|
|
33680
|
+
outputCrs: 'EPSG:4326',
|
|
33681
|
+
}));
|
|
33682
|
+
}
|
|
33683
|
+
else {
|
|
33684
|
+
if (featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')) &&
|
|
33685
|
+
(featureType.defaultCrs === 'EPSG:4326' ||
|
|
33686
|
+
featureType.otherCrs?.includes('EPSG:4326'))) {
|
|
33687
|
+
reader = new GmlReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33688
|
+
outputFormat: featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')),
|
|
33689
|
+
outputCrs: 'EPSG:4326',
|
|
33690
|
+
}));
|
|
33691
|
+
}
|
|
33692
|
+
}
|
|
33693
|
+
reader.enableCache(this.cacheEnabled);
|
|
33694
|
+
reader.load();
|
|
33695
|
+
return reader;
|
|
33696
|
+
});
|
|
33697
|
+
return this.backupReader_;
|
|
33283
33698
|
}
|
|
33284
33699
|
get properties() {
|
|
33285
|
-
return this.
|
|
33286
|
-
.getFeatureTypeFull(this.featureTypeName)
|
|
33287
|
-
.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33700
|
+
return this.featureType.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33288
33701
|
const originalType = featureType.properties[prop];
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
|
|
33702
|
+
let type;
|
|
33703
|
+
if (originalType === 'float' || originalType === 'integer') {
|
|
33704
|
+
type = 'number';
|
|
33705
|
+
}
|
|
33706
|
+
else if (originalType === 'boolean') {
|
|
33707
|
+
type = 'string'; // we don't handle booleans yet in the data fetcher
|
|
33708
|
+
}
|
|
33709
|
+
else {
|
|
33710
|
+
type = originalType;
|
|
33711
|
+
}
|
|
33292
33712
|
return {
|
|
33293
33713
|
name: prop,
|
|
33294
33714
|
label: prop,
|
|
@@ -33297,83 +33717,63 @@ class WfsReader extends BaseCacheReader {
|
|
|
33297
33717
|
}));
|
|
33298
33718
|
}
|
|
33299
33719
|
get info() {
|
|
33300
|
-
return this.
|
|
33720
|
+
return this.featureType.then((result) => ({
|
|
33301
33721
|
itemsCount: result.objectCount,
|
|
33722
|
+
hasGeometry: !!result.geometryName,
|
|
33302
33723
|
}));
|
|
33303
33724
|
}
|
|
33304
|
-
|
|
33305
|
-
|
|
33306
|
-
const featureTypes = wfsEndpoint.getFeatureTypes();
|
|
33307
|
-
const featureType = wfsEndpoint.getFeatureTypeSummary(featureTypes.length === 1 && !featureTypeName
|
|
33308
|
-
? featureTypes[0].name
|
|
33309
|
-
: featureTypeName);
|
|
33310
|
-
if (!featureType) {
|
|
33311
|
-
throw new Error('wfs.featuretype.notfound');
|
|
33312
|
-
}
|
|
33313
|
-
if (wfsEndpoint.supportsStartIndex()) {
|
|
33314
|
-
return new WfsReader(wfsUrlEndpoint, wfsEndpoint, featureType.name);
|
|
33315
|
-
}
|
|
33316
|
-
else if (wfsEndpoint.supportsJson(featureType.name)) {
|
|
33317
|
-
return new GeojsonReader(wfsEndpoint.getFeatureUrl(featureType.name, {
|
|
33318
|
-
asJson: true,
|
|
33319
|
-
outputCrs: 'EPSG:4326',
|
|
33320
|
-
}));
|
|
33321
|
-
}
|
|
33322
|
-
else {
|
|
33323
|
-
if (featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')) &&
|
|
33324
|
-
(featureType.defaultCrs === 'EPSG:4326' ||
|
|
33325
|
-
featureType.otherCrs?.includes('EPSG:4326'))) {
|
|
33326
|
-
return new GmlReader(wfsEndpoint.getFeatureUrl(featureType.name, {
|
|
33327
|
-
outputFormat: featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')),
|
|
33328
|
-
outputCrs: 'EPSG:4326',
|
|
33329
|
-
}), featureType.name, wfsEndpoint.getVersion());
|
|
33330
|
-
}
|
|
33331
|
-
throw new Error('wfs.geojsongml.notsupported');
|
|
33332
|
-
}
|
|
33725
|
+
load() {
|
|
33726
|
+
// Nothing to load for Wfs
|
|
33333
33727
|
}
|
|
33334
|
-
async
|
|
33335
|
-
|
|
33336
|
-
|
|
33728
|
+
async read() {
|
|
33729
|
+
const endpoint = await this.endpoint;
|
|
33730
|
+
const featureType = await this.featureType;
|
|
33731
|
+
// if we can't use the WFS protocol we fall back to the backup reader
|
|
33732
|
+
if (this.aggregations || this.groupedBy || !endpoint.supportsStartIndex()) {
|
|
33733
|
+
const backupReader = await this.backupReader;
|
|
33734
|
+
backupReader.selectAll();
|
|
33735
|
+
if (this.selected) {
|
|
33736
|
+
backupReader.select(...this.selected);
|
|
33737
|
+
}
|
|
33738
|
+
if (this.aggregations) {
|
|
33739
|
+
backupReader.aggregate(...this.aggregations);
|
|
33740
|
+
}
|
|
33741
|
+
if (this.groupedBy) {
|
|
33742
|
+
backupReader.groupBy(...this.groupedBy);
|
|
33743
|
+
}
|
|
33744
|
+
if (this.sort) {
|
|
33745
|
+
backupReader.orderBy(...this.sort);
|
|
33746
|
+
}
|
|
33747
|
+
if (this.startIndex !== null && this.count !== null) {
|
|
33748
|
+
backupReader.limit(this.startIndex, this.count);
|
|
33749
|
+
}
|
|
33750
|
+
return backupReader.read();
|
|
33337
33751
|
}
|
|
33338
|
-
const asJson =
|
|
33752
|
+
const asJson = endpoint.supportsJson(featureType.name);
|
|
33339
33753
|
const attributes = this.selected ?? undefined;
|
|
33340
|
-
let
|
|
33754
|
+
let sortBy = null;
|
|
33755
|
+
if (this.sort) {
|
|
33756
|
+
const mapSort = (s) => [s[0] === 'desc' ? 'D' : 'A', s[1]];
|
|
33757
|
+
sortBy = Array.isArray(this.sort[0])
|
|
33758
|
+
? this.sort.map(mapSort)
|
|
33759
|
+
: mapSort(this.sort);
|
|
33760
|
+
}
|
|
33761
|
+
const url = endpoint.getFeatureUrl(featureType.name, {
|
|
33341
33762
|
...(this.startIndex !== null && { startIndex: this.startIndex }),
|
|
33342
33763
|
...(this.count !== null && { maxFeatures: this.count }),
|
|
33343
33764
|
asJson,
|
|
33344
33765
|
outputCrs: 'EPSG:4326',
|
|
33345
33766
|
attributes,
|
|
33346
|
-
|
|
33767
|
+
sortBy,
|
|
33347
33768
|
});
|
|
33348
|
-
|
|
33349
|
-
const finalUrl = new URL(url);
|
|
33350
|
-
const sorts = this.sort
|
|
33351
|
-
.map((fieldSort) => `${fieldSort[1]}+${fieldSort[0] === 'asc' ? 'A' : 'D'}`)
|
|
33352
|
-
.join(',');
|
|
33353
|
-
// Direct update on string url to prevent encoding of +A and +D
|
|
33354
|
-
url = `${url}${finalUrl.search ? '&' : ''}SORTBY=${sorts}`;
|
|
33355
|
-
}
|
|
33356
|
-
return fetchDataAsText(url, this.cacheActive).then((text) => asJson
|
|
33769
|
+
return fetchDataAsText(url, this.cacheEnabled).then((text) => asJson
|
|
33357
33770
|
? parseGeojson(text)
|
|
33358
|
-
: parseGml(text,
|
|
33359
|
-
}
|
|
33360
|
-
async getQueryData() {
|
|
33361
|
-
const items = (await this.getData()).items;
|
|
33362
|
-
const jsonItems = getJsonDataItemsProxy(items);
|
|
33363
|
-
const query = generateSqlQuery(this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations);
|
|
33364
|
-
const result = await import('alasql').then((module) => module.default(query, [jsonItems]));
|
|
33365
|
-
return result.map(jsonToGeojsonFeature);
|
|
33366
|
-
}
|
|
33367
|
-
load() {
|
|
33368
|
-
// Nothing to load for Wfs
|
|
33369
|
-
}
|
|
33370
|
-
async read() {
|
|
33371
|
-
return (await this.getData(this.aggregations, this.groupedBy)).items;
|
|
33771
|
+
: parseGml(text, featureType.name, endpoint.getVersion()));
|
|
33372
33772
|
}
|
|
33373
33773
|
}
|
|
33374
33774
|
|
|
33375
|
-
async function openDataset(url,
|
|
33376
|
-
const fileType = await inferDatasetType(url, typeHint);
|
|
33775
|
+
async function openDataset(url, options) {
|
|
33776
|
+
const fileType = await inferDatasetType(url, options?.typeHint);
|
|
33377
33777
|
let reader;
|
|
33378
33778
|
try {
|
|
33379
33779
|
switch (fileType) {
|
|
@@ -33390,18 +33790,18 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33390
33790
|
reader = new ExcelReader(url);
|
|
33391
33791
|
break;
|
|
33392
33792
|
case 'gml':
|
|
33393
|
-
reader = new GmlReader(url
|
|
33793
|
+
reader = new GmlReader(url);
|
|
33394
33794
|
break;
|
|
33395
33795
|
case 'wfs':
|
|
33396
|
-
reader =
|
|
33796
|
+
reader = new WfsReader(url, options?.wfsFeatureType);
|
|
33397
33797
|
break;
|
|
33398
33798
|
}
|
|
33399
|
-
reader.
|
|
33799
|
+
reader.enableCache(options?.enableCache ?? true);
|
|
33400
33800
|
reader.load();
|
|
33401
33801
|
return reader;
|
|
33402
33802
|
}
|
|
33403
33803
|
catch (e) {
|
|
33404
|
-
//WfsReader may already raise a FetchError
|
|
33804
|
+
// WfsReader may already raise a FetchError
|
|
33405
33805
|
if (e instanceof FetchError)
|
|
33406
33806
|
throw e;
|
|
33407
33807
|
else
|
|
@@ -33412,13 +33812,13 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33412
33812
|
* This fetches the full dataset at the given URL and parses it according to its mime type.
|
|
33413
33813
|
* All items in the dataset are converted to GeoJSON features, even if they do not bear any spatial geometry.
|
|
33414
33814
|
* File type can be either inferred (from the HTTP headers or the URL), or hinted using the 2nd argument
|
|
33415
|
-
* File type is determined
|
|
33815
|
+
* File type is determined like so:
|
|
33416
33816
|
* 1. if a type hint is given, use it
|
|
33417
33817
|
* 2. otherwise, look for a Content-Type header in the response with a supported mime type
|
|
33418
33818
|
* 3. if no valid mime type was found, look for an explicit file extension in the url (.csv, .geojson etc.)
|
|
33419
33819
|
*/
|
|
33420
|
-
async function readDataset(url,
|
|
33421
|
-
const reader = await openDataset(url,
|
|
33820
|
+
async function readDataset(url, options) {
|
|
33821
|
+
const reader = await openDataset(url, options);
|
|
33422
33822
|
try {
|
|
33423
33823
|
return await reader.read();
|
|
33424
33824
|
}
|
|
@@ -33649,9 +34049,11 @@ class DataService {
|
|
|
33649
34049
|
getDataset(link, cacheActive) {
|
|
33650
34050
|
if (link.type === 'service' && link.accessServiceProtocol === 'wfs') {
|
|
33651
34051
|
const wfsUrlEndpoint = this.proxy.getProxiedUrl(link.url.toString());
|
|
33652
|
-
return from(openDataset(wfsUrlEndpoint,
|
|
34052
|
+
return from(openDataset(wfsUrlEndpoint, {
|
|
34053
|
+
typeHint: 'wfs',
|
|
33653
34054
|
wfsFeatureType: link.name,
|
|
33654
|
-
|
|
34055
|
+
enableCache: cacheActive,
|
|
34056
|
+
}));
|
|
33655
34057
|
}
|
|
33656
34058
|
else if (link.type === 'download') {
|
|
33657
34059
|
const linkProxifiedUrl = this.proxy.getProxiedUrl(link.url.toString());
|
|
@@ -33659,12 +34061,15 @@ class DataService {
|
|
|
33659
34061
|
const supportedType = SupportedTypes.indexOf(format) > -1
|
|
33660
34062
|
? format
|
|
33661
34063
|
: undefined;
|
|
33662
|
-
return from(openDataset(linkProxifiedUrl,
|
|
34064
|
+
return from(openDataset(linkProxifiedUrl, {
|
|
34065
|
+
typeHint: supportedType,
|
|
34066
|
+
enableCache: cacheActive,
|
|
34067
|
+
})).pipe();
|
|
33663
34068
|
}
|
|
33664
34069
|
else if (link.type === 'service' &&
|
|
33665
34070
|
link.accessServiceProtocol === 'esriRest') {
|
|
33666
34071
|
const url = this.getDownloadUrlFromEsriRest(link.url.toString(), 'geojson');
|
|
33667
|
-
return from(openDataset(url, 'geojson',
|
|
34072
|
+
return from(openDataset(url, { typeHint: 'geojson', enableCache: cacheActive })).pipe();
|
|
33668
34073
|
}
|
|
33669
34074
|
else if (link.type === 'service' &&
|
|
33670
34075
|
link.accessServiceProtocol === 'ogcFeatures') {
|
|
@@ -33678,7 +34083,10 @@ class DataService {
|
|
|
33678
34083
|
}
|
|
33679
34084
|
const urlWithoutLimit = new URL(geojsonUrl);
|
|
33680
34085
|
urlWithoutLimit.searchParams.delete('limit');
|
|
33681
|
-
return openDataset(urlWithoutLimit.toString(),
|
|
34086
|
+
return openDataset(urlWithoutLimit.toString(), {
|
|
34087
|
+
typeHint: 'geojson',
|
|
34088
|
+
enableCache: cacheActive,
|
|
34089
|
+
});
|
|
33682
34090
|
}));
|
|
33683
34091
|
}
|
|
33684
34092
|
return throwError(() => 'protocol not supported');
|
|
@@ -33930,20 +34338,31 @@ class DataTableComponent {
|
|
|
33930
34338
|
this.eltRef = inject(ElementRef);
|
|
33931
34339
|
this.cdr = inject(ChangeDetectorRef);
|
|
33932
34340
|
this.translateService = inject(TranslateService);
|
|
33933
|
-
this.
|
|
34341
|
+
this.columnsFromFeatureCatalog = null;
|
|
34342
|
+
this.columnsFromDataset = [];
|
|
33934
34343
|
this.selected = new EventEmitter();
|
|
33935
|
-
this.properties$ = new BehaviorSubject(null);
|
|
33936
34344
|
this.loading$ = new BehaviorSubject(false);
|
|
33937
34345
|
this.error = null;
|
|
33938
34346
|
}
|
|
33939
34347
|
set featureAttributes(value) {
|
|
33940
|
-
this.
|
|
33941
|
-
|
|
34348
|
+
this.columnsFromFeatureCatalog = value.map((attrs) => ({
|
|
34349
|
+
name: attrs.value,
|
|
34350
|
+
label: attrs.label,
|
|
34351
|
+
}));
|
|
33942
34352
|
}
|
|
33943
34353
|
set dataset(value) {
|
|
33944
34354
|
this.dataset_ = value;
|
|
33945
34355
|
this.dataset_.load();
|
|
33946
|
-
this.dataset_.info.then((info) =>
|
|
34356
|
+
this.dataset_.info.then((info) => {
|
|
34357
|
+
this.count = info.itemsCount;
|
|
34358
|
+
this.cdr.detectChanges();
|
|
34359
|
+
});
|
|
34360
|
+
}
|
|
34361
|
+
get columns() {
|
|
34362
|
+
return this.columnsFromFeatureCatalog ?? this.columnsFromDataset;
|
|
34363
|
+
}
|
|
34364
|
+
get columnNames() {
|
|
34365
|
+
return this.columns.map((c) => c.name);
|
|
33947
34366
|
}
|
|
33948
34367
|
ngOnInit() {
|
|
33949
34368
|
this.dataSource = new DataTableDataSource();
|
|
@@ -33978,11 +34397,12 @@ class DataTableComponent {
|
|
|
33978
34397
|
}
|
|
33979
34398
|
async readData() {
|
|
33980
34399
|
this.loading$.next(true);
|
|
33981
|
-
// wait for properties to be read
|
|
33982
|
-
const properties = await firstValueFrom(this.properties$.pipe(filter((p) => !!p)));
|
|
33983
|
-
const propsWithoutGeom = properties.filter((p) => !p.toLowerCase().startsWith('geom'));
|
|
33984
|
-
this.dataset_.select(...propsWithoutGeom);
|
|
33985
34400
|
try {
|
|
34401
|
+
// wait for properties to be read
|
|
34402
|
+
if (!this.columnsFromFeatureCatalog) {
|
|
34403
|
+
this.columnsFromDataset = await this.dataset_.properties;
|
|
34404
|
+
}
|
|
34405
|
+
this.dataset_.select(...this.columnNames);
|
|
33986
34406
|
await this.dataSource.showData(this.dataset_.read());
|
|
33987
34407
|
this.error = null;
|
|
33988
34408
|
}
|
|
@@ -34012,7 +34432,7 @@ class DataTableComponent {
|
|
|
34012
34432
|
}
|
|
34013
34433
|
}
|
|
34014
34434
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
34015
|
-
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
|
|
34435
|
+
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 }); }
|
|
34016
34436
|
}
|
|
34017
34437
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
34018
34438
|
type: Component,
|
|
@@ -34024,10 +34444,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
34024
34444
|
CommonModule,
|
|
34025
34445
|
LoadingMaskComponent,
|
|
34026
34446
|
PopupAlertComponent,
|
|
34027
|
-
LetDirective,
|
|
34028
34447
|
TranslatePipe,
|
|
34029
34448
|
TranslateDirective,
|
|
34030
|
-
], 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
|
|
34449
|
+
], 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"] }]
|
|
34031
34450
|
}], propDecorators: { featureAttributes: [{
|
|
34032
34451
|
type: Input
|
|
34033
34452
|
}], dataset: [{
|
|
@@ -34130,7 +34549,7 @@ class ChartViewComponent {
|
|
|
34130
34549
|
}), shareReplay$1(1));
|
|
34131
34550
|
this.properties$ = combineLatest([this.dataset$, this.featureCatalog$]).pipe(switchMap$1(([dataset, catalog]) => this.setProperties(dataset, catalog)), shareReplay$1(1));
|
|
34132
34551
|
this.yChoices$ = this.properties$.pipe(map$1((properties) => properties
|
|
34133
|
-
.filter((prop) => prop.type === 'number'
|
|
34552
|
+
.filter((prop) => prop.type === 'number')
|
|
34134
34553
|
.map((prop) => ({ value: prop.name, label: prop.label || prop.name }))), tap$1((choices) => {
|
|
34135
34554
|
if (!choices.find((choice) => choice.value === this.yProperty$.value)) {
|
|
34136
34555
|
const newProp = choices[0]?.value || '';
|
|
@@ -34157,6 +34576,7 @@ class ChartViewComponent {
|
|
|
34157
34576
|
this.aggregation$,
|
|
34158
34577
|
]).pipe(filter$1(([_, x, y]) => !!x || !!y), switchMap$1(([dataset, xProp, yProp, aggregation]) => {
|
|
34159
34578
|
const fieldAgg = aggregation === 'count' ? ['count'] : [aggregation, yProp];
|
|
34579
|
+
this.loading = true;
|
|
34160
34580
|
return dataset
|
|
34161
34581
|
.groupBy(['distinct', xProp])
|
|
34162
34582
|
.aggregate(fieldAgg)
|
|
@@ -34398,6 +34818,7 @@ class GeoTableViewComponent {
|
|
|
34398
34818
|
}));
|
|
34399
34819
|
}
|
|
34400
34820
|
async initMapContext() {
|
|
34821
|
+
this.dataset.load();
|
|
34401
34822
|
this.dataset.selectAll();
|
|
34402
34823
|
return {
|
|
34403
34824
|
layers: [
|
|
@@ -34571,8 +34992,7 @@ class MdViewFacade {
|
|
|
34571
34992
|
}));
|
|
34572
34993
|
this.error$ = this.store.pipe(select(getMetadataError));
|
|
34573
34994
|
this.related$ = this.store.pipe(select(getRelated));
|
|
34574
|
-
this.
|
|
34575
|
-
this.sourceOf$ = this.store.pipe(select(getSourceOf));
|
|
34995
|
+
this.linkedRecords$ = this.store.pipe(select(getLinkedRecords));
|
|
34576
34996
|
this.chartConfig$ = this.store.pipe(select(getChartConfig));
|
|
34577
34997
|
this.allLinks$ = this.metadata$.pipe(map$1((record) => 'onlineResources' in record ? record.onlineResources : []), shareReplay$1(1));
|
|
34578
34998
|
this.resourceDoi$ = this.metadata$.pipe(map$1((record) => {
|
|
@@ -34691,12 +35111,9 @@ class MdViewEffects {
|
|
|
34691
35111
|
this.loadRelatedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getSimilarRecords(full)), map$1((related) => {
|
|
34692
35112
|
return setRelated({ related });
|
|
34693
35113
|
}), catchError(() => of(setRelated({ related: null })))));
|
|
34694
|
-
this.
|
|
34695
|
-
return
|
|
34696
|
-
}), catchError(() => of(
|
|
34697
|
-
this.loadSourceOf$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getSourceOf(full)), map$1((sourceOf) => {
|
|
34698
|
-
return setSourceOf({ sourceOf });
|
|
34699
|
-
}), catchError(() => of(setSourceOf({ sourceOf: null })))));
|
|
35114
|
+
this.loadLinkedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getLinkedRecords(full)), map$1((linkedRecords) => {
|
|
35115
|
+
return setLinkedRecords({ linkedRecords });
|
|
35116
|
+
}), catchError(() => of(setLinkedRecords({ linkedRecords: null })))));
|
|
34700
35117
|
/*
|
|
34701
35118
|
UserFeedback effects
|
|
34702
35119
|
*/
|
|
@@ -36430,6 +36847,11 @@ const DEFAULT_CONFIGURATION = {
|
|
|
36430
36847
|
},
|
|
36431
36848
|
hidden: '${record.kind == "service"}',
|
|
36432
36849
|
},
|
|
36850
|
+
{
|
|
36851
|
+
model: 'associatedRecords',
|
|
36852
|
+
formFieldConfig: {},
|
|
36853
|
+
hidden: '${record.kind == "service"}',
|
|
36854
|
+
},
|
|
36433
36855
|
],
|
|
36434
36856
|
},
|
|
36435
36857
|
// Section: Geographical coverage
|
|
@@ -37567,7 +37989,7 @@ class FormFieldTemporalExtentsComponent {
|
|
|
37567
37989
|
provideNgIconsConfig({
|
|
37568
37990
|
size: '1.5rem',
|
|
37569
37991
|
}),
|
|
37570
|
-
], ngImport: i0, template: "<div class=\"flex gap-2
|
|
37992
|
+
], 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 }); }
|
|
37571
37993
|
}
|
|
37572
37994
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldTemporalExtentsComponent, decorators: [{
|
|
37573
37995
|
type: Component,
|
|
@@ -37584,7 +38006,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37584
38006
|
provideNgIconsConfig({
|
|
37585
38007
|
size: '1.5rem',
|
|
37586
38008
|
}),
|
|
37587
|
-
], template: "<div class=\"flex gap-2
|
|
38009
|
+
], 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"] }]
|
|
37588
38010
|
}], propDecorators: { value: [{
|
|
37589
38011
|
type: Input
|
|
37590
38012
|
}], valueChange: [{
|
|
@@ -37800,6 +38222,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37800
38222
|
], 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" }]
|
|
37801
38223
|
}] });
|
|
37802
38224
|
|
|
38225
|
+
class FormFieldAssociatedRecordsComponent {
|
|
38226
|
+
constructor() {
|
|
38227
|
+
this.valueChange = new EventEmitter();
|
|
38228
|
+
}
|
|
38229
|
+
get list() {
|
|
38230
|
+
return this.value ?? [];
|
|
38231
|
+
}
|
|
38232
|
+
get first() {
|
|
38233
|
+
return this.list[0];
|
|
38234
|
+
}
|
|
38235
|
+
get rest() {
|
|
38236
|
+
return this.list.slice(1);
|
|
38237
|
+
}
|
|
38238
|
+
get hasParentLink() {
|
|
38239
|
+
return this.list.length > 0;
|
|
38240
|
+
}
|
|
38241
|
+
get uniqueIdentifier() {
|
|
38242
|
+
return this.first?.uniqueIdentifier ?? '';
|
|
38243
|
+
}
|
|
38244
|
+
get selectedType() {
|
|
38245
|
+
return this.first?.associationType;
|
|
38246
|
+
}
|
|
38247
|
+
get choices() {
|
|
38248
|
+
return associationTypeValues.map((value) => ({
|
|
38249
|
+
value,
|
|
38250
|
+
label: `domain.record.associationType.${value}`,
|
|
38251
|
+
}));
|
|
38252
|
+
}
|
|
38253
|
+
onToggle(checked) {
|
|
38254
|
+
this.valueChange.emit(checked
|
|
38255
|
+
? [
|
|
38256
|
+
{
|
|
38257
|
+
uniqueIdentifier: '',
|
|
38258
|
+
associationType: associationTypeValues[0],
|
|
38259
|
+
},
|
|
38260
|
+
...this.rest,
|
|
38261
|
+
]
|
|
38262
|
+
: this.rest);
|
|
38263
|
+
}
|
|
38264
|
+
onUniqueIdentifierChange(uniqueIdentifier) {
|
|
38265
|
+
this.valueChange.emit(uniqueIdentifier
|
|
38266
|
+
? [{ ...this.first, uniqueIdentifier }, ...this.rest]
|
|
38267
|
+
: this.rest);
|
|
38268
|
+
}
|
|
38269
|
+
onTypeChange(associationType) {
|
|
38270
|
+
this.valueChange.emit([
|
|
38271
|
+
{ ...this.first, associationType: associationType },
|
|
38272
|
+
...this.rest,
|
|
38273
|
+
]);
|
|
38274
|
+
}
|
|
38275
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
38276
|
+
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 }); }
|
|
38277
|
+
}
|
|
38278
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, decorators: [{
|
|
38279
|
+
type: Component,
|
|
38280
|
+
args: [{ selector: 'gn-ui-form-field-associated-records', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
38281
|
+
CheckToggleComponent,
|
|
38282
|
+
TextInputComponent,
|
|
38283
|
+
DropdownSelectorComponent,
|
|
38284
|
+
FormFieldWrapperComponent,
|
|
38285
|
+
TranslatePipe,
|
|
38286
|
+
], 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" }]
|
|
38287
|
+
}], propDecorators: { value: [{
|
|
38288
|
+
type: Input
|
|
38289
|
+
}], valueChange: [{
|
|
38290
|
+
type: Output
|
|
38291
|
+
}] } });
|
|
38292
|
+
|
|
37803
38293
|
class ContactCardComponent {
|
|
37804
38294
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContactCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
37805
38295
|
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 }); }
|
|
@@ -39185,6 +39675,9 @@ class FormFieldComponent {
|
|
|
39185
39675
|
get valueAsUpdateFrequency() {
|
|
39186
39676
|
return this.value;
|
|
39187
39677
|
}
|
|
39678
|
+
get valueAsAssociatedRecords() {
|
|
39679
|
+
return this.value;
|
|
39680
|
+
}
|
|
39188
39681
|
get valueAsTemporalExtents() {
|
|
39189
39682
|
return this.value;
|
|
39190
39683
|
}
|
|
@@ -39224,7 +39717,7 @@ class FormFieldComponent {
|
|
|
39224
39717
|
}
|
|
39225
39718
|
}
|
|
39226
39719
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
39227
|
-
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 }); }
|
|
39720
|
+
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 }); }
|
|
39228
39721
|
}
|
|
39229
39722
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
39230
39723
|
type: Component,
|
|
@@ -39236,6 +39729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39236
39729
|
FormFieldLicenseComponent,
|
|
39237
39730
|
FormFieldDateComponent,
|
|
39238
39731
|
FormFieldUpdateFrequencyComponent,
|
|
39732
|
+
FormFieldAssociatedRecordsComponent,
|
|
39239
39733
|
FormFieldTemporalExtentsComponent,
|
|
39240
39734
|
FormFieldSimpleComponent,
|
|
39241
39735
|
FormFieldRichComponent,
|
|
@@ -39253,7 +39747,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39253
39747
|
FormFieldTopicsComponent,
|
|
39254
39748
|
TextFieldModule,
|
|
39255
39749
|
NgIconComponent,
|
|
39256
|
-
], 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"] }]
|
|
39750
|
+
], 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"] }]
|
|
39257
39751
|
}], propDecorators: { uniqueIdentifier: [{
|
|
39258
39752
|
type: Input
|
|
39259
39753
|
}], recordKind: [{
|
|
@@ -39838,7 +40332,7 @@ class RouterService {
|
|
|
39838
40332
|
return ROUTER_ROUTE_ORGANIZATION;
|
|
39839
40333
|
}
|
|
39840
40334
|
getDefaultSort() {
|
|
39841
|
-
return SortByEnum.
|
|
40335
|
+
return SortByEnum.RESOURCE_DATE;
|
|
39842
40336
|
}
|
|
39843
40337
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39844
40338
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, providedIn: 'root' }); }
|
|
@@ -40255,5 +40749,5 @@ const CHART_TYPE_VALUES = [
|
|
|
40255
40749
|
* Generated bundle index. Do not edit.
|
|
40256
40750
|
*/
|
|
40257
40751
|
|
|
40258
|
-
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, 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 };
|
|
40752
|
+
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_BASEMAP_LAYER, DEFAULT_CONFIGURATION, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RECORD_CONVERTER, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DEFAULT_SPATIAL_EXTENT_STYLE, DISABLE_AUTH, DISABLE_DRAFT, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldFocusDirective, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingComponent, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, I18nInterceptor, ISO_TOPICS, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KeywordBadgeComponent, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, MAX_UPLOAD_SIZE_MB, METADATA_LANGUAGE, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapStyleService, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, OPEN_DATA_LICENSE, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OnlineResourceCardComponent, OnlineServiceResourceInputComponent, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_DATASET_URL_TOKEN, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESULTS_LAYOUT_CONFIG, REUSE_LIGHT_CONFIGURATION, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordStatusValues, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, 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, SpatialExtentSearchField, 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, 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, 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 };
|
|
40259
40753
|
//# sourceMappingURL=geonetwork-ui.mjs.map
|