geonetwork-ui 2.10.0 → 2.11.0-dev.68d9eaa3a
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 +883 -632
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +101 -54
- package/index.d.ts.map +1 -1
- package/package.json +8 -8
- 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/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/sort-by/sort-by.component.ts +1 -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/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/translations/de.json +14 -1
- package/translations/en.json +14 -1
- package/translations/es.json +13 -0
- package/translations/fr.json +14 -1
- package/translations/it.json +14 -1
- package/translations/nl.json +13 -0
- package/translations/pt.json +13 -0
- package/translations/sk.json +14 -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';
|
|
@@ -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;
|
|
@@ -20338,7 +20389,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
20338
20389
|
}] } });
|
|
20339
20390
|
|
|
20340
20391
|
var name = "geonetwork-ui";
|
|
20341
|
-
var version = "2.
|
|
20392
|
+
var version = "2.11.0-dev.68d9eaa3a";
|
|
20342
20393
|
var engines = {
|
|
20343
20394
|
node: ">=24"
|
|
20344
20395
|
};
|
|
@@ -20377,11 +20428,12 @@ var peerDependencies = {
|
|
|
20377
20428
|
};
|
|
20378
20429
|
var dependencies = {
|
|
20379
20430
|
"@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/
|
|
20431
|
+
"@camptocamp/ogc-client": "1.3.1-dev.200c02a",
|
|
20432
|
+
"@duckdb/duckdb-wasm": "~1.32.0",
|
|
20433
|
+
"@geospatial-sdk/core": "0.0.5-dev.78",
|
|
20434
|
+
"@geospatial-sdk/geocoding": "0.0.5-dev.78",
|
|
20435
|
+
"@geospatial-sdk/legend": "0.0.5-dev.78",
|
|
20436
|
+
"@geospatial-sdk/openlayers": "0.0.5-dev.78",
|
|
20385
20437
|
"@ltd/j-toml": "~1.38.0",
|
|
20386
20438
|
"@messageformat/core": "~3.4.0",
|
|
20387
20439
|
"@ng-icons/core": "~32.5.0",
|
|
@@ -20389,7 +20441,7 @@ var dependencies = {
|
|
|
20389
20441
|
"@ng-icons/material-icons": "~32.5.0",
|
|
20390
20442
|
"@ng-icons/tabler-icons": "~32.4.0",
|
|
20391
20443
|
"@rgrove/parse-xml": "4.2.0",
|
|
20392
|
-
|
|
20444
|
+
"apache-arrow": "~17.0.0",
|
|
20393
20445
|
"chart.js": "~4.5.1",
|
|
20394
20446
|
"chroma-js": "~3.2.0",
|
|
20395
20447
|
"date-fns": "4.1.0",
|
|
@@ -20402,7 +20454,6 @@ var dependencies = {
|
|
|
20402
20454
|
"ngx-dropzone": "~3.1.0",
|
|
20403
20455
|
"ngx-translate-messageformat-compiler": "~7.2.0",
|
|
20404
20456
|
ol: "~10.8.0",
|
|
20405
|
-
papaparse: "~5.5.3",
|
|
20406
20457
|
proj4: "~2.20.4",
|
|
20407
20458
|
rdflib: "~2.3.5",
|
|
20408
20459
|
semver: "~7.7.4",
|
|
@@ -20647,6 +20698,7 @@ class ElasticsearchService {
|
|
|
20647
20698
|
values: uuids,
|
|
20648
20699
|
},
|
|
20649
20700
|
},
|
|
20701
|
+
size: uuids.length,
|
|
20650
20702
|
};
|
|
20651
20703
|
}
|
|
20652
20704
|
getRelatedRecordPayload(record, size = 6, _source = [...ES_SOURCE_SUMMARY, 'createDate']) {
|
|
@@ -20697,10 +20749,28 @@ class ElasticsearchService {
|
|
|
20697
20749
|
};
|
|
20698
20750
|
}
|
|
20699
20751
|
buildPayloadSort(sortBy) {
|
|
20700
|
-
if (sortBy ===
|
|
20752
|
+
if (!sortBy || sortBy.length === 0)
|
|
20701
20753
|
return undefined;
|
|
20702
|
-
const fields = Array.isArray(sortBy[0])
|
|
20703
|
-
|
|
20754
|
+
const fields = Array.isArray(sortBy[0])
|
|
20755
|
+
? sortBy
|
|
20756
|
+
: [sortBy];
|
|
20757
|
+
return fields.map((field) => {
|
|
20758
|
+
// Sort by nested array of dates only works with the explicit syntax
|
|
20759
|
+
if (field[1].endsWith('.date')) {
|
|
20760
|
+
const nestedPath = field[1].slice(0, field[1].lastIndexOf('.date'));
|
|
20761
|
+
return {
|
|
20762
|
+
[field[1]]: {
|
|
20763
|
+
order: field[0],
|
|
20764
|
+
mode: field[0] === 'desc' ? 'max' : 'min',
|
|
20765
|
+
missing: '_last',
|
|
20766
|
+
nested: {
|
|
20767
|
+
path: nestedPath,
|
|
20768
|
+
},
|
|
20769
|
+
},
|
|
20770
|
+
};
|
|
20771
|
+
}
|
|
20772
|
+
return { [field[1]]: field[0] };
|
|
20773
|
+
});
|
|
20704
20774
|
}
|
|
20705
20775
|
injectLangInQueryStringFields(queryFieldsPriority) {
|
|
20706
20776
|
const queryLang = this.getQueryLang();
|
|
@@ -21180,7 +21250,7 @@ class Gn4Repository {
|
|
|
21180
21250
|
}
|
|
21181
21251
|
getRecord(uniqueIdentifier) {
|
|
21182
21252
|
return this.gn4SearchApi
|
|
21183
|
-
.search('bucket', ['fcats', 'hassources'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21253
|
+
.search('bucket', ['fcats', 'hassources', 'siblings', 'associated'], JSON.stringify(this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])))
|
|
21184
21254
|
.pipe(map$1((results) => results.hits.hits[0]), switchMap((record) => record ? this.gn4Mapper.readRecord(record) : of(null)));
|
|
21185
21255
|
}
|
|
21186
21256
|
getMultipleRecords(uniqueIdentifiers) {
|
|
@@ -21234,19 +21304,28 @@ class Gn4Repository {
|
|
|
21234
21304
|
.search('bucket', null, JSON.stringify(this.gn4SearchHelper.getRelatedRecordPayload(similarTo, 3)))
|
|
21235
21305
|
.pipe(switchMap((results) => this.gn4Mapper.readRecords(results.hits.hits)));
|
|
21236
21306
|
}
|
|
21237
|
-
|
|
21238
|
-
const
|
|
21239
|
-
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
21247
|
-
|
|
21307
|
+
getLinkedRecords(record) {
|
|
21308
|
+
const siblings = (record.extras?.['siblings'] ?? []);
|
|
21309
|
+
const relations = [
|
|
21310
|
+
['source', (record.extras?.['sourcesIdentifiers'] ?? [])],
|
|
21311
|
+
['sourceOf', (record.extras?.['sourceOfIdentifiers'] ?? [])],
|
|
21312
|
+
['sibling', siblings.map(({ uniqueIdentifier }) => uniqueIdentifier)],
|
|
21313
|
+
[
|
|
21314
|
+
'associated',
|
|
21315
|
+
(record.extras?.['associatedIdentifiers'] ?? []),
|
|
21316
|
+
],
|
|
21317
|
+
];
|
|
21318
|
+
const requested = relations.filter(([, identifiers]) => identifiers.length > 0);
|
|
21319
|
+
if (requested.length === 0) {
|
|
21320
|
+
return of([]);
|
|
21248
21321
|
}
|
|
21249
|
-
return
|
|
21322
|
+
return forkJoin(requested.map(([relation, identifiers]) => this.getMultipleRecords(identifiers).pipe(map$1((records) => (records ?? []).map((record) => ({
|
|
21323
|
+
record,
|
|
21324
|
+
relation,
|
|
21325
|
+
associationType: relation === 'sibling'
|
|
21326
|
+
? siblings.find(({ uniqueIdentifier }) => uniqueIdentifier === record.uniqueIdentifier)?.associationType
|
|
21327
|
+
: undefined,
|
|
21328
|
+
}))), catchError(() => of([]))))).pipe(map$1((groups) => groups.flat()));
|
|
21250
21329
|
}
|
|
21251
21330
|
aggregate(params) {
|
|
21252
21331
|
// if aggregations are empty, return an empty object right away
|
|
@@ -31771,11 +31850,7 @@ const SortByEnum = {
|
|
|
31771
31850
|
RELEVANCY: ['desc', '_score'],
|
|
31772
31851
|
QUALITY_SCORE: ['desc', 'qualityScore'],
|
|
31773
31852
|
CHANGE_DATE: ['desc', 'changeDate'],
|
|
31774
|
-
|
|
31775
|
-
['desc', 'revisionDateForResource'],
|
|
31776
|
-
['desc', 'publicationDateForResource'],
|
|
31777
|
-
['desc', 'creationDateForResource'],
|
|
31778
|
-
],
|
|
31853
|
+
RESOURCE_DATE: ['desc', 'resourceDate.date'],
|
|
31779
31854
|
};
|
|
31780
31855
|
|
|
31781
31856
|
class SortByComponent {
|
|
@@ -31789,7 +31864,7 @@ class SortByComponent {
|
|
|
31789
31864
|
},
|
|
31790
31865
|
{
|
|
31791
31866
|
label: marker('results.sortBy.dateStamp'),
|
|
31792
|
-
value: SortByEnum.
|
|
31867
|
+
value: SortByEnum.RESOURCE_DATE,
|
|
31793
31868
|
},
|
|
31794
31869
|
{
|
|
31795
31870
|
label: marker('results.sortBy.popularity'),
|
|
@@ -32467,8 +32542,7 @@ const closeMetadata = createAction('[Metadata view] close');
|
|
|
32467
32542
|
Related actions
|
|
32468
32543
|
*/
|
|
32469
32544
|
const setRelated = createAction('[Metadata view] Set related records', props());
|
|
32470
|
-
const
|
|
32471
|
-
const setSourceOf = createAction('[Metadata view] Set has sources', props());
|
|
32545
|
+
const setLinkedRecords = createAction('[Metadata view] Set associated records', props());
|
|
32472
32546
|
/*
|
|
32473
32547
|
ChartConfig actions
|
|
32474
32548
|
*/
|
|
@@ -32500,9 +32574,8 @@ var mdview_actions = /*#__PURE__*/Object.freeze({
|
|
|
32500
32574
|
loadUserFeedbacksSuccess: loadUserFeedbacksSuccess,
|
|
32501
32575
|
setChartConfig: setChartConfig,
|
|
32502
32576
|
setIncompleteMetadata: setIncompleteMetadata,
|
|
32503
|
-
|
|
32504
|
-
|
|
32505
|
-
setSources: setSources
|
|
32577
|
+
setLinkedRecords: setLinkedRecords,
|
|
32578
|
+
setRelated: setRelated
|
|
32506
32579
|
});
|
|
32507
32580
|
|
|
32508
32581
|
const METADATA_VIEW_FEATURE_STATE_KEY = 'metadataView';
|
|
@@ -32545,12 +32618,9 @@ on(loadFullMetadata, (state) => ({
|
|
|
32545
32618
|
on(setRelated, (state, { related }) => ({
|
|
32546
32619
|
...state,
|
|
32547
32620
|
related,
|
|
32548
|
-
})), on(
|
|
32549
|
-
...state,
|
|
32550
|
-
sources,
|
|
32551
|
-
})), on(setSourceOf, (state, { sourceOf }) => ({
|
|
32621
|
+
})), on(setLinkedRecords, (state, { linkedRecords }) => ({
|
|
32552
32622
|
...state,
|
|
32553
|
-
|
|
32623
|
+
linkedRecords,
|
|
32554
32624
|
})),
|
|
32555
32625
|
/*
|
|
32556
32626
|
ChartConfig reducers
|
|
@@ -32612,8 +32682,7 @@ const getMetadataError = createSelector(getMdViewState, (state) => state.error);
|
|
|
32612
32682
|
Related selectors
|
|
32613
32683
|
*/
|
|
32614
32684
|
const getRelated = createSelector(getMdViewState, (state) => state.related);
|
|
32615
|
-
const
|
|
32616
|
-
const getSourceOf = createSelector(getMdViewState, (state) => state.sourceOf);
|
|
32685
|
+
const getLinkedRecords = createSelector(getMdViewState, (state) => state.linkedRecords);
|
|
32617
32686
|
/*
|
|
32618
32687
|
Metadata selectors
|
|
32619
32688
|
*/
|
|
@@ -32714,212 +32783,10 @@ function parseHeaders(httpHeaders) {
|
|
|
32714
32783
|
return result;
|
|
32715
32784
|
}
|
|
32716
32785
|
|
|
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;
|
|
32786
|
+
const GEOMETRY_COLUMN_ALIAS = '__geometry__';
|
|
32787
|
+
function fieldToSql(name) {
|
|
32788
|
+
return `"${name.replace(/"/g, '""')}"`; // escape double quotes in field names
|
|
32834
32789
|
}
|
|
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 };
|
|
32901
|
-
}
|
|
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
32790
|
function filterToSql(filter) {
|
|
32924
32791
|
const operator = filter[0];
|
|
32925
32792
|
const args = filter.slice(1);
|
|
@@ -32934,10 +32801,10 @@ function filterToSql(filter) {
|
|
|
32934
32801
|
case '=':
|
|
32935
32802
|
case '!=':
|
|
32936
32803
|
case 'like':
|
|
32937
|
-
return
|
|
32804
|
+
return `${fieldToSql(args[0])} ${operator.toUpperCase()} ${valueToSql(args[1])}`;
|
|
32938
32805
|
case 'in': {
|
|
32939
32806
|
const values = args.slice(1);
|
|
32940
|
-
return
|
|
32807
|
+
return `${fieldToSql(args[0])} IN (${values.map(valueToSql).join(', ')})`;
|
|
32941
32808
|
}
|
|
32942
32809
|
case 'and':
|
|
32943
32810
|
case 'or': {
|
|
@@ -32956,17 +32823,18 @@ function aggregationToSql(aggregation) {
|
|
|
32956
32823
|
const field = aggregation[1];
|
|
32957
32824
|
switch (operation) {
|
|
32958
32825
|
case 'average':
|
|
32959
|
-
return `AVG(
|
|
32826
|
+
return `CAST(AVG(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`average(${field})`)}`;
|
|
32960
32827
|
case 'sum':
|
|
32961
32828
|
case 'max':
|
|
32962
32829
|
case 'min':
|
|
32963
|
-
return
|
|
32830
|
+
return `CAST(${operation.toUpperCase()}(${fieldToSql(field)}) AS DOUBLE) as ${fieldToSql(`${operation}(${field})`)}`;
|
|
32964
32831
|
case 'count':
|
|
32965
|
-
return 'COUNT(*) as
|
|
32832
|
+
return 'CAST(COUNT(*) AS INTEGER) as "count()"'; // we don't need Bigint precision here
|
|
32966
32833
|
}
|
|
32967
32834
|
}
|
|
32968
32835
|
/**
|
|
32969
32836
|
* Leave arguments at null if not used
|
|
32837
|
+
* @param tableName
|
|
32970
32838
|
* @param selected
|
|
32971
32839
|
* @param filter
|
|
32972
32840
|
* @param sort
|
|
@@ -32975,22 +32843,25 @@ function aggregationToSql(aggregation) {
|
|
|
32975
32843
|
* @param groupBy
|
|
32976
32844
|
* @param aggregations
|
|
32977
32845
|
*/
|
|
32978
|
-
function generateSqlQuery(selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null) {
|
|
32846
|
+
function generateSqlQuery(tableName, selected = null, filter = null, sort = null, startIndex = null, count = null, groupBy = null, aggregations = null, geometryColumn = null) {
|
|
32979
32847
|
let sqlSelect = 'SELECT *';
|
|
32980
|
-
const sqlFrom =
|
|
32848
|
+
const sqlFrom = ` FROM ${tableName}`;
|
|
32981
32849
|
let sqlOrderBy = '';
|
|
32982
32850
|
let sqlWhere = '';
|
|
32983
32851
|
let sqlLimit = '';
|
|
32984
32852
|
let sqlGroupBy = '';
|
|
32985
32853
|
if (selected !== null) {
|
|
32986
|
-
sqlSelect = `SELECT ${selected.map(
|
|
32854
|
+
sqlSelect = `SELECT ${selected.map(fieldToSql).join(', ')}`;
|
|
32855
|
+
}
|
|
32856
|
+
if (geometryColumn !== null) {
|
|
32857
|
+
sqlSelect += `, ST_AsGeoJSON(${fieldToSql(geometryColumn)}) as ${GEOMETRY_COLUMN_ALIAS}`;
|
|
32987
32858
|
}
|
|
32988
32859
|
if (filter !== null) {
|
|
32989
32860
|
sqlWhere = ` WHERE ${filterToSql(filter)}`;
|
|
32990
32861
|
}
|
|
32991
32862
|
if (sort?.length) {
|
|
32992
32863
|
sqlOrderBy = ` ORDER BY ${sort
|
|
32993
|
-
.map((sort) =>
|
|
32864
|
+
.map((sort) => `${fieldToSql(sort[1])} ${sort[0].toUpperCase()}`)
|
|
32994
32865
|
.join(', ')}`;
|
|
32995
32866
|
}
|
|
32996
32867
|
if (startIndex !== null && count !== null) {
|
|
@@ -33000,17 +32871,212 @@ function generateSqlQuery(selected = null, filter = null, sort = null, startInde
|
|
|
33000
32871
|
sqlSelect = `SELECT ${aggregations.map(aggregationToSql).join(', ')}`;
|
|
33001
32872
|
const groupedByDistinct = groupBy.filter((group) => group[0] === 'distinct');
|
|
33002
32873
|
const sqlGroupByFields = groupedByDistinct
|
|
33003
|
-
.map((group) =>
|
|
32874
|
+
.map((group) => fieldToSql(group[1]))
|
|
33004
32875
|
.join(', ');
|
|
33005
32876
|
const sqlGroupBySelect = groupedByDistinct
|
|
33006
|
-
.map((group) =>
|
|
32877
|
+
.map((group) => `${fieldToSql(group[1])} as ${fieldToSql(`distinct(${group[1]})`)}`)
|
|
33007
32878
|
.join(', ');
|
|
33008
32879
|
if (sqlGroupByFields && sqlGroupBySelect) {
|
|
33009
32880
|
sqlGroupBy = ` GROUP BY ${sqlGroupByFields}`;
|
|
33010
32881
|
sqlSelect += `, ${sqlGroupBySelect}`;
|
|
33011
32882
|
}
|
|
33012
32883
|
}
|
|
33013
|
-
return sqlSelect + sqlFrom + sqlGroupBy +
|
|
32884
|
+
return sqlSelect + sqlFrom + sqlGroupBy + sqlWhere + sqlOrderBy + sqlLimit;
|
|
32885
|
+
}
|
|
32886
|
+
|
|
32887
|
+
function arrowTableToDataItems(table) {
|
|
32888
|
+
const fields = table.schema.fields;
|
|
32889
|
+
return table.toArray().map((row) => {
|
|
32890
|
+
const rowJson = row.toJSON();
|
|
32891
|
+
const feature = {
|
|
32892
|
+
type: 'Feature',
|
|
32893
|
+
geometry: null,
|
|
32894
|
+
properties: {},
|
|
32895
|
+
};
|
|
32896
|
+
const keys = Object.keys(rowJson);
|
|
32897
|
+
for (let i = 0; i < keys.length; i++) {
|
|
32898
|
+
const key = keys[i];
|
|
32899
|
+
const dataType = fields[i].type;
|
|
32900
|
+
let value = rowJson[key];
|
|
32901
|
+
// this might happen if we get an array inside a field
|
|
32902
|
+
if (value instanceof Vector) {
|
|
32903
|
+
value = Array.from(value);
|
|
32904
|
+
}
|
|
32905
|
+
// cast bigints to ints
|
|
32906
|
+
if (typeof value === 'bigint') {
|
|
32907
|
+
value = Number(value);
|
|
32908
|
+
}
|
|
32909
|
+
// rename columns with empty name
|
|
32910
|
+
if (!key) {
|
|
32911
|
+
feature.properties['unknown'] = value;
|
|
32912
|
+
continue;
|
|
32913
|
+
}
|
|
32914
|
+
// assign properties that look like an id to the geojson `id` field
|
|
32915
|
+
if (/^(object|feature)?_?id$/.test(key.toLowerCase()) &&
|
|
32916
|
+
(typeof value == 'string' || typeof value === 'number')) {
|
|
32917
|
+
feature.id = value;
|
|
32918
|
+
}
|
|
32919
|
+
// if a date is in timestamp (number) format, convert it to native
|
|
32920
|
+
if (typeof value === 'number' &&
|
|
32921
|
+
(DataType.isTimestamp(dataType) || DataType.isDate(dataType))) {
|
|
32922
|
+
value = new Date(value);
|
|
32923
|
+
}
|
|
32924
|
+
// if a binary field (most likely a geometry column): skip
|
|
32925
|
+
if (DataType.isBinary(dataType)) {
|
|
32926
|
+
continue;
|
|
32927
|
+
}
|
|
32928
|
+
// geometry column
|
|
32929
|
+
if (key === GEOMETRY_COLUMN_ALIAS && DataType.isUtf8(dataType)) {
|
|
32930
|
+
feature.geometry = JSON.parse(value);
|
|
32931
|
+
continue;
|
|
32932
|
+
}
|
|
32933
|
+
feature.properties[key] = value;
|
|
32934
|
+
}
|
|
32935
|
+
return feature;
|
|
32936
|
+
});
|
|
32937
|
+
}
|
|
32938
|
+
|
|
32939
|
+
// init code taken from https://github.com/duckdb/duckdb-wasm/blob/main/packages/duckdb-wasm/README.md
|
|
32940
|
+
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
|
|
32941
|
+
// from https://duckdb.org/docs/current/sql/data_types/overview
|
|
32942
|
+
const typesMapping = {
|
|
32943
|
+
INTEGER: 'number',
|
|
32944
|
+
SMALLINT: 'number',
|
|
32945
|
+
TINYINT: 'number',
|
|
32946
|
+
BIGINT: 'number',
|
|
32947
|
+
HUGEINT: 'number',
|
|
32948
|
+
UINTEGER: 'number',
|
|
32949
|
+
USMALLINT: 'number',
|
|
32950
|
+
UTINYINT: 'number',
|
|
32951
|
+
UBIGINT: 'number',
|
|
32952
|
+
UHUGEINT: 'number',
|
|
32953
|
+
DOUBLE: 'number',
|
|
32954
|
+
BIGNUM: 'number',
|
|
32955
|
+
DECIMAL: 'number',
|
|
32956
|
+
NUMERIC: 'number',
|
|
32957
|
+
FLOAT: 'number',
|
|
32958
|
+
REAL: 'number',
|
|
32959
|
+
'TIMESTAMP WITH TIME ZONE': 'date',
|
|
32960
|
+
TIMESTAMP: 'date',
|
|
32961
|
+
DATE: 'date',
|
|
32962
|
+
CHAR: 'string',
|
|
32963
|
+
VARCHAR: 'string',
|
|
32964
|
+
TEXT: 'string',
|
|
32965
|
+
UUID: 'string',
|
|
32966
|
+
BLOB: 'string',
|
|
32967
|
+
BIT: 'string',
|
|
32968
|
+
INTERVAL: 'string',
|
|
32969
|
+
LIST: 'string',
|
|
32970
|
+
BOOLEAN: 'boolean',
|
|
32971
|
+
};
|
|
32972
|
+
class Engine {
|
|
32973
|
+
async makeInit() {
|
|
32974
|
+
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
|
|
32975
|
+
let worker_url = bundle.mainWorker;
|
|
32976
|
+
// this is necessary to let browsers execute WASM code coming from a cross-origin host
|
|
32977
|
+
if (worker_url.startsWith('https://')) {
|
|
32978
|
+
worker_url = URL.createObjectURL(new Blob([`importScripts("${worker_url}");`], {
|
|
32979
|
+
type: 'text/javascript',
|
|
32980
|
+
}));
|
|
32981
|
+
}
|
|
32982
|
+
const worker = new Worker(worker_url);
|
|
32983
|
+
const logger = new duckdb.ConsoleLogger(duckdb.LogLevel.WARNING);
|
|
32984
|
+
this.db = new duckdb.AsyncDuckDB(logger, worker);
|
|
32985
|
+
await this.db.instantiate(bundle.mainModule, bundle.pthreadWorker);
|
|
32986
|
+
// setup duckdb options
|
|
32987
|
+
const conn = await this.db.connect();
|
|
32988
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
32989
|
+
await conn.query(`INSTALL spatial; LOAD spatial;`);
|
|
32990
|
+
await conn.query(`SET TimeZone = '${timezone}';`);
|
|
32991
|
+
await conn.query(`SET threads = 1;`);
|
|
32992
|
+
// await conn.query(`SET memory_limit = '2GB';`) // used for experimenting when we encounter memory issues
|
|
32993
|
+
await conn.query(`SET preserve_insertion_order = false;`); // this reduces memory usage when loading a dataset
|
|
32994
|
+
conn.close();
|
|
32995
|
+
return this;
|
|
32996
|
+
}
|
|
32997
|
+
isReady() {
|
|
32998
|
+
if (!this.init_) {
|
|
32999
|
+
this.init_ = this.makeInit();
|
|
33000
|
+
}
|
|
33001
|
+
return this.init_;
|
|
33002
|
+
}
|
|
33003
|
+
/**
|
|
33004
|
+
* Returns information about a dataset once it's loaded:
|
|
33005
|
+
* - a list of properties description
|
|
33006
|
+
* - the name of the dataset geometry column (null if no geometry present)
|
|
33007
|
+
* @param datasetId name of the table under which the dataset will be stored
|
|
33008
|
+
* @param loadQuery duckdb-specific query for creating a table out of the data
|
|
33009
|
+
* @param forceReload if true, any existing data will be dropped and redownloaded
|
|
33010
|
+
*/
|
|
33011
|
+
async loadFile(datasetId, loadQuery, forceReload = false) {
|
|
33012
|
+
const conn = await this.db.connect();
|
|
33013
|
+
let results;
|
|
33014
|
+
// either we want to recreate the table, or we keep it if it already exists
|
|
33015
|
+
const safeLoadQuery = forceReload
|
|
33016
|
+
? `DROP TABLE IF EXISTS ${datasetId};
|
|
33017
|
+
${loadQuery}`
|
|
33018
|
+
: loadQuery.replace(/CREATE TABLE(?! IF NOT EXISTS)/gi, 'CREATE TABLE IF NOT EXISTS');
|
|
33019
|
+
// create the table
|
|
33020
|
+
try {
|
|
33021
|
+
results = await conn.query(safeLoadQuery);
|
|
33022
|
+
}
|
|
33023
|
+
catch (e) {
|
|
33024
|
+
throw new FetchError('parse', `DuckDB encountered an error when loading the data: ${e.message}`);
|
|
33025
|
+
}
|
|
33026
|
+
// read rows count
|
|
33027
|
+
results = await conn.query(`SELECT count(*) FROM ${datasetId}`);
|
|
33028
|
+
const { 'count_star()': recordsCount } = results.toArray()[0].toJSON();
|
|
33029
|
+
// read columns
|
|
33030
|
+
results = await conn.query(`SELECT * FROM information_schema.columns WHERE table_name = '${datasetId}';`);
|
|
33031
|
+
let geometryColumn = null;
|
|
33032
|
+
const properties = results
|
|
33033
|
+
.toArray()
|
|
33034
|
+
.map((row) => {
|
|
33035
|
+
const rowObj = row.toJSON();
|
|
33036
|
+
if (rowObj['data_type'] === 'GEOMETRY') {
|
|
33037
|
+
// the geometry is not part of the properties
|
|
33038
|
+
// note: right now we only keep one geometry column name, but if there are multiple they will
|
|
33039
|
+
// all get discarded
|
|
33040
|
+
geometryColumn = rowObj['column_name'];
|
|
33041
|
+
return null;
|
|
33042
|
+
}
|
|
33043
|
+
return {
|
|
33044
|
+
name: rowObj['column_name'],
|
|
33045
|
+
label: rowObj['column_name'],
|
|
33046
|
+
type: typesMapping[rowObj['data_type']] ?? 'other',
|
|
33047
|
+
};
|
|
33048
|
+
})
|
|
33049
|
+
.filter((prop) => prop !== null);
|
|
33050
|
+
conn.close();
|
|
33051
|
+
return {
|
|
33052
|
+
properties,
|
|
33053
|
+
geometryColumn,
|
|
33054
|
+
rowsCount: Number(recordsCount),
|
|
33055
|
+
};
|
|
33056
|
+
}
|
|
33057
|
+
// register a Uint8 buffer using a handle in the duckdb instance
|
|
33058
|
+
async registerData(name, buffer) {
|
|
33059
|
+
return this.db.registerFileBuffer(name, buffer);
|
|
33060
|
+
}
|
|
33061
|
+
/**
|
|
33062
|
+
* @param query duckdb-specific query for fetching items
|
|
33063
|
+
*/
|
|
33064
|
+
async queryItems(query) {
|
|
33065
|
+
const conn = await this.db.connect();
|
|
33066
|
+
const results = await conn.query(query);
|
|
33067
|
+
conn.close();
|
|
33068
|
+
return arrowTableToDataItems(results);
|
|
33069
|
+
}
|
|
33070
|
+
close() {
|
|
33071
|
+
this.db?.terminate();
|
|
33072
|
+
}
|
|
33073
|
+
}
|
|
33074
|
+
let engine = null;
|
|
33075
|
+
async function getEngine() {
|
|
33076
|
+
if (!engine) {
|
|
33077
|
+
engine = new Engine();
|
|
33078
|
+
}
|
|
33079
|
+
return engine.isReady();
|
|
33014
33080
|
}
|
|
33015
33081
|
|
|
33016
33082
|
class BaseReader {
|
|
@@ -33023,10 +33089,18 @@ class BaseReader {
|
|
|
33023
33089
|
this.sort = null;
|
|
33024
33090
|
this.startIndex = null;
|
|
33025
33091
|
this.count = null;
|
|
33092
|
+
this.loadPromise_ = Promise.resolve();
|
|
33093
|
+
this.cacheEnabled = false;
|
|
33094
|
+
}
|
|
33095
|
+
enableCache(enabled) {
|
|
33096
|
+
this.cacheEnabled = enabled;
|
|
33026
33097
|
}
|
|
33027
33098
|
load() {
|
|
33028
33099
|
throw new Error('not implemented');
|
|
33029
33100
|
}
|
|
33101
|
+
get isLoaded() {
|
|
33102
|
+
return this.loadPromise_;
|
|
33103
|
+
}
|
|
33030
33104
|
get properties() {
|
|
33031
33105
|
throw new Error('not implemented');
|
|
33032
33106
|
}
|
|
@@ -33075,178 +33149,237 @@ class BaseReader {
|
|
|
33075
33149
|
}
|
|
33076
33150
|
}
|
|
33077
33151
|
|
|
33078
|
-
|
|
33079
|
-
|
|
33080
|
-
|
|
33081
|
-
|
|
33082
|
-
|
|
33083
|
-
|
|
33084
|
-
|
|
33085
|
-
|
|
33086
|
-
|
|
33087
|
-
|
|
33088
|
-
|
|
33089
|
-
|
|
33090
|
-
|
|
33152
|
+
/**
|
|
33153
|
+
* This reader handles file formats supported natively by DuckDB
|
|
33154
|
+
*/
|
|
33155
|
+
class BaseFileReader extends BaseReader {
|
|
33156
|
+
// a table id should not exceed 63 chars
|
|
33157
|
+
generateDatasetId() {
|
|
33158
|
+
// generate a hash out of the url
|
|
33159
|
+
let hash = 0;
|
|
33160
|
+
for (const char of this.url) {
|
|
33161
|
+
hash = (hash << 5) - hash + char.charCodeAt(0);
|
|
33162
|
+
hash = hash >>> 0; // make it unsigned
|
|
33163
|
+
}
|
|
33164
|
+
return `datafetcher_${hash.toString(16)}`;
|
|
33165
|
+
}
|
|
33166
|
+
async getLoadQuery() {
|
|
33091
33167
|
throw new Error('not implemented');
|
|
33092
33168
|
}
|
|
33093
|
-
load() {
|
|
33094
|
-
this.
|
|
33169
|
+
async load() {
|
|
33170
|
+
this.datasetId = this.generateDatasetId();
|
|
33171
|
+
this.loadPromise_ = getEngine()
|
|
33172
|
+
.then((engine) => {
|
|
33173
|
+
this.engine = engine;
|
|
33174
|
+
return this.getLoadQuery();
|
|
33175
|
+
})
|
|
33176
|
+
.then((loadQuery) => this.engine.loadFile(this.datasetId, loadQuery, !this.cacheEnabled))
|
|
33177
|
+
.then((datasetInfo) => {
|
|
33178
|
+
this.properties_ = datasetInfo.properties;
|
|
33179
|
+
this.geometryColumn = datasetInfo.geometryColumn;
|
|
33180
|
+
this.rowsCount = datasetInfo.rowsCount;
|
|
33181
|
+
// returns void for the loaded promise
|
|
33182
|
+
});
|
|
33095
33183
|
}
|
|
33096
33184
|
get properties() {
|
|
33097
|
-
return this.
|
|
33185
|
+
return this.isLoaded.then(() => this.properties_);
|
|
33098
33186
|
}
|
|
33099
33187
|
get info() {
|
|
33100
|
-
return this.
|
|
33101
|
-
itemsCount:
|
|
33188
|
+
return this.isLoaded.then(() => ({
|
|
33189
|
+
itemsCount: this.rowsCount,
|
|
33190
|
+
hasGeometry: !!this.geometryColumn,
|
|
33102
33191
|
}));
|
|
33103
33192
|
}
|
|
33104
33193
|
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;
|
|
33194
|
+
await this.isLoaded;
|
|
33195
|
+
// if only certain fields are selected, omit the geometry
|
|
33196
|
+
const geometryColumn = this.selected === null ? this.geometryColumn : null;
|
|
33197
|
+
const query = generateSqlQuery(this.datasetId, this.selected, this.filter, this.sort, this.startIndex, this.count, this.groupedBy, this.aggregations, geometryColumn);
|
|
33198
|
+
return this.engine.queryItems(query);
|
|
33133
33199
|
}
|
|
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
33200
|
}
|
|
33201
|
+
|
|
33151
33202
|
class CsvReader extends BaseFileReader {
|
|
33152
|
-
|
|
33153
|
-
|
|
33203
|
+
async getLoadQuery() {
|
|
33204
|
+
// first we get a list of columns hich have a detected type of VARCHAR
|
|
33205
|
+
// 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
|
|
33206
|
+
return `
|
|
33207
|
+
SET VARIABLE strColumns = (SELECT list(name) FROM (SELECT unnest(Columns, recursive := true) FROM sniff_csv("${this.url}")) WHERE type = 'VARCHAR');
|
|
33208
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_csv("${this.url}",
|
|
33209
|
+
force_not_null = getvariable('strColumns'),
|
|
33210
|
+
auto_type_candidates = ['NULL', 'BOOLEAN', 'INTEGER', 'DOUBLE', 'DATE', 'VARCHAR']
|
|
33211
|
+
);`;
|
|
33154
33212
|
}
|
|
33155
33213
|
}
|
|
33156
33214
|
|
|
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
33215
|
class JsonReader extends BaseFileReader {
|
|
33169
|
-
|
|
33170
|
-
return
|
|
33216
|
+
async getLoadQuery() {
|
|
33217
|
+
return `
|
|
33218
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_json("${this.url}",
|
|
33219
|
+
maximum_object_size = 536870912 -- 500MB
|
|
33220
|
+
);`;
|
|
33171
33221
|
}
|
|
33172
33222
|
}
|
|
33173
33223
|
|
|
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
33224
|
class GeojsonReader extends BaseFileReader {
|
|
33188
|
-
|
|
33189
|
-
return
|
|
33225
|
+
async getLoadQuery() {
|
|
33226
|
+
return `
|
|
33227
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33228
|
+
allowed_drivers = ['GeoJSON']
|
|
33229
|
+
);`;
|
|
33190
33230
|
}
|
|
33191
33231
|
}
|
|
33192
33232
|
|
|
33233
|
+
async function inferDatasetType(url, typeHint) {
|
|
33234
|
+
const fileExtensionMatches = new URL(url, typeof window !== 'undefined' ? window.location.toString() : undefined).pathname.match(/\.(.+)$/);
|
|
33235
|
+
const fileExtension = fileExtensionMatches && fileExtensionMatches.length
|
|
33236
|
+
? fileExtensionMatches[1].toLowerCase()
|
|
33237
|
+
: null;
|
|
33238
|
+
// 1. type hint
|
|
33239
|
+
if (typeHint)
|
|
33240
|
+
return Promise.resolve(typeHint);
|
|
33241
|
+
// 2. content-type header
|
|
33242
|
+
const headers = await fetchHeaders(url);
|
|
33243
|
+
if ('supportedType' in headers)
|
|
33244
|
+
return headers.supportedType;
|
|
33245
|
+
// 3. file extension from url
|
|
33246
|
+
else if (SupportedTypes.indexOf(fileExtension) > -1)
|
|
33247
|
+
return fileExtension;
|
|
33248
|
+
// no type inferred or hinted
|
|
33249
|
+
if ('mimeType' in headers)
|
|
33250
|
+
throw FetchError.unsupportedType(headers.mimeType);
|
|
33251
|
+
else
|
|
33252
|
+
throw FetchError.unknownType();
|
|
33253
|
+
}
|
|
33254
|
+
function fetchHeaders(url) {
|
|
33255
|
+
return sharedFetch(url, 'HEAD')
|
|
33256
|
+
.catch((error) => {
|
|
33257
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33258
|
+
})
|
|
33259
|
+
.then((response) => {
|
|
33260
|
+
if (!response.ok) {
|
|
33261
|
+
throw FetchError.http(response.status);
|
|
33262
|
+
}
|
|
33263
|
+
return parseHeaders(response.headers);
|
|
33264
|
+
});
|
|
33265
|
+
}
|
|
33266
|
+
function fetchDataAsText(url, cacheActive) {
|
|
33267
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33268
|
+
.catch((error) => {
|
|
33269
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33270
|
+
})
|
|
33271
|
+
.then(async (response) => {
|
|
33272
|
+
if (!response.ok) {
|
|
33273
|
+
const clonedResponse = response.clone();
|
|
33274
|
+
throw FetchError.http(response.status, await clonedResponse.text());
|
|
33275
|
+
}
|
|
33276
|
+
const clonedResponse = response.clone();
|
|
33277
|
+
return clonedResponse.text();
|
|
33278
|
+
});
|
|
33279
|
+
return cacheActive ? useCache(fetchFactory, url, 'asText') : fetchFactory();
|
|
33280
|
+
}
|
|
33281
|
+
function fetchDataAsArrayBuffer(url, cacheActive) {
|
|
33282
|
+
const fetchFactory = () => sharedFetch(url)
|
|
33283
|
+
.catch((error) => {
|
|
33284
|
+
throw FetchError.corsOrNetwork(error.message);
|
|
33285
|
+
})
|
|
33286
|
+
.then(async (response) => {
|
|
33287
|
+
if (!response.ok) {
|
|
33288
|
+
throw FetchError.http(response.status, await response.text());
|
|
33289
|
+
}
|
|
33290
|
+
// convert to a numeric array so that we can store the response in cache
|
|
33291
|
+
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
|
33292
|
+
});
|
|
33293
|
+
return (cacheActive ? useCache(fetchFactory, url, 'asArrayBuffer') : fetchFactory()).then((array) => {
|
|
33294
|
+
return new Uint8Array(array).buffer;
|
|
33295
|
+
});
|
|
33296
|
+
}
|
|
33193
33297
|
/**
|
|
33194
|
-
* This
|
|
33195
|
-
*
|
|
33196
|
-
* @param
|
|
33298
|
+
* This creates a Proxy that allows reading and writing to the data item properties
|
|
33299
|
+
* as if it was a simple array of JSON objects
|
|
33300
|
+
* @param items
|
|
33197
33301
|
*/
|
|
33198
|
-
function
|
|
33199
|
-
return
|
|
33200
|
-
|
|
33201
|
-
|
|
33202
|
-
|
|
33203
|
-
|
|
33204
|
-
|
|
33205
|
-
|
|
33206
|
-
|
|
33302
|
+
function getJsonDataItemsProxy(items) {
|
|
33303
|
+
return new Proxy(items, {
|
|
33304
|
+
get(target, p) {
|
|
33305
|
+
if (typeof p === 'string' &&
|
|
33306
|
+
!Number.isNaN(parseInt(p)) &&
|
|
33307
|
+
target[p]?.properties) {
|
|
33308
|
+
return target[p].properties;
|
|
33309
|
+
}
|
|
33310
|
+
return target[p];
|
|
33311
|
+
},
|
|
33312
|
+
set() {
|
|
33313
|
+
throw new Error('This object is read-only');
|
|
33314
|
+
},
|
|
33207
33315
|
});
|
|
33208
33316
|
}
|
|
33317
|
+
|
|
33209
33318
|
class ExcelReader extends BaseFileReader {
|
|
33210
|
-
|
|
33211
|
-
|
|
33319
|
+
async getLoadQuery() {
|
|
33320
|
+
// we download the file as an array buffer first, in order to be able to check if it's an XLS file
|
|
33321
|
+
let buffer = await fetchDataAsArrayBuffer(this.url, this.cacheEnabled);
|
|
33322
|
+
const bufferHandle = `B${this.datasetId}`;
|
|
33323
|
+
// checking against the magic number at the beginning of XLS files, see https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
33324
|
+
const magicNumber = new Uint8Array(buffer, 0, 8); // first 8 bytes
|
|
33325
|
+
const isXls = Array.from(magicNumber)
|
|
33326
|
+
.map((n) => n.toString(16).toUpperCase())
|
|
33327
|
+
.join(' ') === 'D0 CF 11 E0 A1 B1 1A E1';
|
|
33328
|
+
// uh oh, this is an XLS file (not supported by duckdb); convert it to CSV using the xlsx package
|
|
33329
|
+
if (isXls) {
|
|
33330
|
+
buffer = await import('xlsx').then(({ read, utils }) => {
|
|
33331
|
+
const workbook = read(buffer);
|
|
33332
|
+
const json = utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
|
|
33333
|
+
return new TextEncoder().encode(JSON.stringify(json)).buffer;
|
|
33334
|
+
});
|
|
33335
|
+
}
|
|
33336
|
+
const duckDbFn = isXls ? 'read_json' : 'read_xlsx';
|
|
33337
|
+
await this.engine.registerData(bufferHandle, new Uint8Array(buffer));
|
|
33338
|
+
return `
|
|
33339
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM ${duckDbFn}("${bufferHandle}", ignore_errors = true);`;
|
|
33340
|
+
}
|
|
33341
|
+
}
|
|
33342
|
+
|
|
33343
|
+
class GmlReader extends BaseFileReader {
|
|
33344
|
+
async getLoadQuery() {
|
|
33345
|
+
return `
|
|
33346
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
33347
|
+
allowed_drivers = ['GML']
|
|
33348
|
+
);`;
|
|
33212
33349
|
}
|
|
33213
33350
|
}
|
|
33214
33351
|
|
|
33215
|
-
|
|
33216
|
-
|
|
33217
|
-
const
|
|
33352
|
+
const formatGeojson = new GeoJSON$1();
|
|
33353
|
+
function parseGeojson(text) {
|
|
33354
|
+
const parsed = JSON.parse(text);
|
|
33355
|
+
const features = parsed.type === 'FeatureCollection' ? parsed.features : parsed;
|
|
33356
|
+
if (!Array.isArray(features)) {
|
|
33357
|
+
throw new Error('Could not parse GeoJSON, expected a features collection or an array of features at root level');
|
|
33358
|
+
}
|
|
33359
|
+
return features;
|
|
33360
|
+
}
|
|
33361
|
+
function parseGml(text, featureType, version) {
|
|
33362
|
+
const parts = featureType.split(':');
|
|
33363
|
+
const regex = new RegExp(`xmlns:${parts[0]}=["']([^'"]*)["']`);
|
|
33218
33364
|
const match = regex.exec(text);
|
|
33219
33365
|
if (match && match.length >= 2) {
|
|
33220
|
-
const
|
|
33366
|
+
const wfs = new WFS({
|
|
33221
33367
|
featureNS: match[1],
|
|
33222
|
-
featureType:
|
|
33368
|
+
featureType: parts[1],
|
|
33223
33369
|
version: version,
|
|
33224
33370
|
});
|
|
33225
33371
|
let features;
|
|
33226
33372
|
try {
|
|
33227
|
-
features =
|
|
33373
|
+
features = wfs.readFeatures(text);
|
|
33228
33374
|
}
|
|
33229
33375
|
catch (e) {
|
|
33230
|
-
throw Error(
|
|
33376
|
+
throw Error(`Couldn't parse WFS with GML features: ${e.message}`);
|
|
33231
33377
|
}
|
|
33232
|
-
const geojsonItem =
|
|
33233
|
-
return
|
|
33378
|
+
const geojsonItem = formatGeojson.writeFeaturesObject(features);
|
|
33379
|
+
return geojsonItem.features;
|
|
33234
33380
|
}
|
|
33235
33381
|
throw Error("Couldn't retrieve namespace url");
|
|
33236
33382
|
}
|
|
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
33383
|
async function getWfsEndpoint(wfsUrl) {
|
|
33251
33384
|
try {
|
|
33252
33385
|
return await new WfsEndpoint(wfsUrl).isReady();
|
|
@@ -33274,21 +33407,65 @@ async function getWfsEndpoint(wfsUrl) {
|
|
|
33274
33407
|
}
|
|
33275
33408
|
}
|
|
33276
33409
|
}
|
|
33277
|
-
class WfsReader extends
|
|
33278
|
-
constructor(url,
|
|
33279
|
-
super(url
|
|
33280
|
-
this.endpoint =
|
|
33281
|
-
this.
|
|
33282
|
-
|
|
33410
|
+
class WfsReader extends BaseReader {
|
|
33411
|
+
constructor(url, featureTypeName) {
|
|
33412
|
+
super(url);
|
|
33413
|
+
this.endpoint = getWfsEndpoint(url);
|
|
33414
|
+
this.featureType = this.endpoint
|
|
33415
|
+
.then((endpoint) => {
|
|
33416
|
+
const featureTypes = endpoint.getFeatureTypes();
|
|
33417
|
+
return endpoint.getFeatureTypeFull(featureTypes.length === 1 && !featureTypeName
|
|
33418
|
+
? featureTypes[0].name
|
|
33419
|
+
: featureTypeName);
|
|
33420
|
+
})
|
|
33421
|
+
.then((featureType) => {
|
|
33422
|
+
if (!featureType) {
|
|
33423
|
+
throw new Error('wfs.featuretype.notfound');
|
|
33424
|
+
}
|
|
33425
|
+
return featureType;
|
|
33426
|
+
});
|
|
33427
|
+
}
|
|
33428
|
+
get backupReader() {
|
|
33429
|
+
if (this.backupReader_) {
|
|
33430
|
+
return this.backupReader_;
|
|
33431
|
+
}
|
|
33432
|
+
this.backupReader_ = Promise.all([this.endpoint, this.featureType]).then(([endpoint, featureType]) => {
|
|
33433
|
+
let reader;
|
|
33434
|
+
if (endpoint.supportsJson(featureType.name)) {
|
|
33435
|
+
reader = new GeojsonReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33436
|
+
asJson: true,
|
|
33437
|
+
outputCrs: 'EPSG:4326',
|
|
33438
|
+
}));
|
|
33439
|
+
}
|
|
33440
|
+
else {
|
|
33441
|
+
if (featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')) &&
|
|
33442
|
+
(featureType.defaultCrs === 'EPSG:4326' ||
|
|
33443
|
+
featureType.otherCrs?.includes('EPSG:4326'))) {
|
|
33444
|
+
reader = new GmlReader(endpoint.getFeatureUrl(featureType.name, {
|
|
33445
|
+
outputFormat: featureType.outputFormats.find((f) => f.toLowerCase().includes('gml')),
|
|
33446
|
+
outputCrs: 'EPSG:4326',
|
|
33447
|
+
}));
|
|
33448
|
+
}
|
|
33449
|
+
}
|
|
33450
|
+
reader.enableCache(this.cacheEnabled);
|
|
33451
|
+
reader.load();
|
|
33452
|
+
return reader;
|
|
33453
|
+
});
|
|
33454
|
+
return this.backupReader_;
|
|
33283
33455
|
}
|
|
33284
33456
|
get properties() {
|
|
33285
|
-
return this.
|
|
33286
|
-
.getFeatureTypeFull(this.featureTypeName)
|
|
33287
|
-
.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33457
|
+
return this.featureType.then((featureType) => Object.keys(featureType.properties).map((prop) => {
|
|
33288
33458
|
const originalType = featureType.properties[prop];
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
|
|
33459
|
+
let type;
|
|
33460
|
+
if (originalType === 'float' || originalType === 'integer') {
|
|
33461
|
+
type = 'number';
|
|
33462
|
+
}
|
|
33463
|
+
else if (originalType === 'boolean') {
|
|
33464
|
+
type = 'string'; // we don't handle booleans yet in the data fetcher
|
|
33465
|
+
}
|
|
33466
|
+
else {
|
|
33467
|
+
type = originalType;
|
|
33468
|
+
}
|
|
33292
33469
|
return {
|
|
33293
33470
|
name: prop,
|
|
33294
33471
|
label: prop,
|
|
@@ -33297,83 +33474,63 @@ class WfsReader extends BaseCacheReader {
|
|
|
33297
33474
|
}));
|
|
33298
33475
|
}
|
|
33299
33476
|
get info() {
|
|
33300
|
-
return this.
|
|
33477
|
+
return this.featureType.then((result) => ({
|
|
33301
33478
|
itemsCount: result.objectCount,
|
|
33479
|
+
hasGeometry: !!result.geometryName,
|
|
33302
33480
|
}));
|
|
33303
33481
|
}
|
|
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
|
-
}
|
|
33482
|
+
load() {
|
|
33483
|
+
// Nothing to load for Wfs
|
|
33333
33484
|
}
|
|
33334
|
-
async
|
|
33335
|
-
|
|
33336
|
-
|
|
33485
|
+
async read() {
|
|
33486
|
+
const endpoint = await this.endpoint;
|
|
33487
|
+
const featureType = await this.featureType;
|
|
33488
|
+
// if we can't use the WFS protocol we fall back to the backup reader
|
|
33489
|
+
if (this.aggregations || this.groupedBy || !endpoint.supportsStartIndex()) {
|
|
33490
|
+
const backupReader = await this.backupReader;
|
|
33491
|
+
backupReader.selectAll();
|
|
33492
|
+
if (this.selected) {
|
|
33493
|
+
backupReader.select(...this.selected);
|
|
33494
|
+
}
|
|
33495
|
+
if (this.aggregations) {
|
|
33496
|
+
backupReader.aggregate(...this.aggregations);
|
|
33497
|
+
}
|
|
33498
|
+
if (this.groupedBy) {
|
|
33499
|
+
backupReader.groupBy(...this.groupedBy);
|
|
33500
|
+
}
|
|
33501
|
+
if (this.sort) {
|
|
33502
|
+
backupReader.orderBy(...this.sort);
|
|
33503
|
+
}
|
|
33504
|
+
if (this.startIndex !== null && this.count !== null) {
|
|
33505
|
+
backupReader.limit(this.startIndex, this.count);
|
|
33506
|
+
}
|
|
33507
|
+
return backupReader.read();
|
|
33337
33508
|
}
|
|
33338
|
-
const asJson =
|
|
33509
|
+
const asJson = endpoint.supportsJson(featureType.name);
|
|
33339
33510
|
const attributes = this.selected ?? undefined;
|
|
33340
|
-
let
|
|
33511
|
+
let sortBy = null;
|
|
33512
|
+
if (this.sort) {
|
|
33513
|
+
const mapSort = (s) => [s[0] === 'desc' ? 'D' : 'A', s[1]];
|
|
33514
|
+
sortBy = Array.isArray(this.sort[0])
|
|
33515
|
+
? this.sort.map(mapSort)
|
|
33516
|
+
: mapSort(this.sort);
|
|
33517
|
+
}
|
|
33518
|
+
const url = endpoint.getFeatureUrl(featureType.name, {
|
|
33341
33519
|
...(this.startIndex !== null && { startIndex: this.startIndex }),
|
|
33342
33520
|
...(this.count !== null && { maxFeatures: this.count }),
|
|
33343
33521
|
asJson,
|
|
33344
33522
|
outputCrs: 'EPSG:4326',
|
|
33345
33523
|
attributes,
|
|
33346
|
-
|
|
33524
|
+
sortBy,
|
|
33347
33525
|
});
|
|
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
|
|
33526
|
+
return fetchDataAsText(url, this.cacheEnabled).then((text) => asJson
|
|
33357
33527
|
? 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;
|
|
33528
|
+
: parseGml(text, featureType.name, endpoint.getVersion()));
|
|
33372
33529
|
}
|
|
33373
33530
|
}
|
|
33374
33531
|
|
|
33375
|
-
async function openDataset(url,
|
|
33376
|
-
const fileType = await inferDatasetType(url, typeHint);
|
|
33532
|
+
async function openDataset(url, options) {
|
|
33533
|
+
const fileType = await inferDatasetType(url, options?.typeHint);
|
|
33377
33534
|
let reader;
|
|
33378
33535
|
try {
|
|
33379
33536
|
switch (fileType) {
|
|
@@ -33390,18 +33547,18 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33390
33547
|
reader = new ExcelReader(url);
|
|
33391
33548
|
break;
|
|
33392
33549
|
case 'gml':
|
|
33393
|
-
reader = new GmlReader(url
|
|
33550
|
+
reader = new GmlReader(url);
|
|
33394
33551
|
break;
|
|
33395
33552
|
case 'wfs':
|
|
33396
|
-
reader =
|
|
33553
|
+
reader = new WfsReader(url, options?.wfsFeatureType);
|
|
33397
33554
|
break;
|
|
33398
33555
|
}
|
|
33399
|
-
reader.
|
|
33556
|
+
reader.enableCache(options?.enableCache ?? true);
|
|
33400
33557
|
reader.load();
|
|
33401
33558
|
return reader;
|
|
33402
33559
|
}
|
|
33403
33560
|
catch (e) {
|
|
33404
|
-
//WfsReader may already raise a FetchError
|
|
33561
|
+
// WfsReader may already raise a FetchError
|
|
33405
33562
|
if (e instanceof FetchError)
|
|
33406
33563
|
throw e;
|
|
33407
33564
|
else
|
|
@@ -33412,13 +33569,13 @@ async function openDataset(url, typeHint, options, cacheActive) {
|
|
|
33412
33569
|
* This fetches the full dataset at the given URL and parses it according to its mime type.
|
|
33413
33570
|
* All items in the dataset are converted to GeoJSON features, even if they do not bear any spatial geometry.
|
|
33414
33571
|
* File type can be either inferred (from the HTTP headers or the URL), or hinted using the 2nd argument
|
|
33415
|
-
* File type is determined
|
|
33572
|
+
* File type is determined like so:
|
|
33416
33573
|
* 1. if a type hint is given, use it
|
|
33417
33574
|
* 2. otherwise, look for a Content-Type header in the response with a supported mime type
|
|
33418
33575
|
* 3. if no valid mime type was found, look for an explicit file extension in the url (.csv, .geojson etc.)
|
|
33419
33576
|
*/
|
|
33420
|
-
async function readDataset(url,
|
|
33421
|
-
const reader = await openDataset(url,
|
|
33577
|
+
async function readDataset(url, options) {
|
|
33578
|
+
const reader = await openDataset(url, options);
|
|
33422
33579
|
try {
|
|
33423
33580
|
return await reader.read();
|
|
33424
33581
|
}
|
|
@@ -33649,9 +33806,11 @@ class DataService {
|
|
|
33649
33806
|
getDataset(link, cacheActive) {
|
|
33650
33807
|
if (link.type === 'service' && link.accessServiceProtocol === 'wfs') {
|
|
33651
33808
|
const wfsUrlEndpoint = this.proxy.getProxiedUrl(link.url.toString());
|
|
33652
|
-
return from(openDataset(wfsUrlEndpoint,
|
|
33809
|
+
return from(openDataset(wfsUrlEndpoint, {
|
|
33810
|
+
typeHint: 'wfs',
|
|
33653
33811
|
wfsFeatureType: link.name,
|
|
33654
|
-
|
|
33812
|
+
enableCache: cacheActive,
|
|
33813
|
+
}));
|
|
33655
33814
|
}
|
|
33656
33815
|
else if (link.type === 'download') {
|
|
33657
33816
|
const linkProxifiedUrl = this.proxy.getProxiedUrl(link.url.toString());
|
|
@@ -33659,12 +33818,15 @@ class DataService {
|
|
|
33659
33818
|
const supportedType = SupportedTypes.indexOf(format) > -1
|
|
33660
33819
|
? format
|
|
33661
33820
|
: undefined;
|
|
33662
|
-
return from(openDataset(linkProxifiedUrl,
|
|
33821
|
+
return from(openDataset(linkProxifiedUrl, {
|
|
33822
|
+
typeHint: supportedType,
|
|
33823
|
+
enableCache: cacheActive,
|
|
33824
|
+
})).pipe();
|
|
33663
33825
|
}
|
|
33664
33826
|
else if (link.type === 'service' &&
|
|
33665
33827
|
link.accessServiceProtocol === 'esriRest') {
|
|
33666
33828
|
const url = this.getDownloadUrlFromEsriRest(link.url.toString(), 'geojson');
|
|
33667
|
-
return from(openDataset(url, 'geojson',
|
|
33829
|
+
return from(openDataset(url, { typeHint: 'geojson', enableCache: cacheActive })).pipe();
|
|
33668
33830
|
}
|
|
33669
33831
|
else if (link.type === 'service' &&
|
|
33670
33832
|
link.accessServiceProtocol === 'ogcFeatures') {
|
|
@@ -33678,7 +33840,10 @@ class DataService {
|
|
|
33678
33840
|
}
|
|
33679
33841
|
const urlWithoutLimit = new URL(geojsonUrl);
|
|
33680
33842
|
urlWithoutLimit.searchParams.delete('limit');
|
|
33681
|
-
return openDataset(urlWithoutLimit.toString(),
|
|
33843
|
+
return openDataset(urlWithoutLimit.toString(), {
|
|
33844
|
+
typeHint: 'geojson',
|
|
33845
|
+
enableCache: cacheActive,
|
|
33846
|
+
});
|
|
33682
33847
|
}));
|
|
33683
33848
|
}
|
|
33684
33849
|
return throwError(() => 'protocol not supported');
|
|
@@ -33930,20 +34095,31 @@ class DataTableComponent {
|
|
|
33930
34095
|
this.eltRef = inject(ElementRef);
|
|
33931
34096
|
this.cdr = inject(ChangeDetectorRef);
|
|
33932
34097
|
this.translateService = inject(TranslateService);
|
|
33933
|
-
this.
|
|
34098
|
+
this.columnsFromFeatureCatalog = null;
|
|
34099
|
+
this.columnsFromDataset = [];
|
|
33934
34100
|
this.selected = new EventEmitter();
|
|
33935
|
-
this.properties$ = new BehaviorSubject(null);
|
|
33936
34101
|
this.loading$ = new BehaviorSubject(false);
|
|
33937
34102
|
this.error = null;
|
|
33938
34103
|
}
|
|
33939
34104
|
set featureAttributes(value) {
|
|
33940
|
-
this.
|
|
33941
|
-
|
|
34105
|
+
this.columnsFromFeatureCatalog = value.map((attrs) => ({
|
|
34106
|
+
name: attrs.value,
|
|
34107
|
+
label: attrs.label,
|
|
34108
|
+
}));
|
|
33942
34109
|
}
|
|
33943
34110
|
set dataset(value) {
|
|
33944
34111
|
this.dataset_ = value;
|
|
33945
34112
|
this.dataset_.load();
|
|
33946
|
-
this.dataset_.info.then((info) =>
|
|
34113
|
+
this.dataset_.info.then((info) => {
|
|
34114
|
+
this.count = info.itemsCount;
|
|
34115
|
+
this.cdr.detectChanges();
|
|
34116
|
+
});
|
|
34117
|
+
}
|
|
34118
|
+
get columns() {
|
|
34119
|
+
return this.columnsFromFeatureCatalog ?? this.columnsFromDataset;
|
|
34120
|
+
}
|
|
34121
|
+
get columnNames() {
|
|
34122
|
+
return this.columns.map((c) => c.name);
|
|
33947
34123
|
}
|
|
33948
34124
|
ngOnInit() {
|
|
33949
34125
|
this.dataSource = new DataTableDataSource();
|
|
@@ -33978,11 +34154,12 @@ class DataTableComponent {
|
|
|
33978
34154
|
}
|
|
33979
34155
|
async readData() {
|
|
33980
34156
|
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
34157
|
try {
|
|
34158
|
+
// wait for properties to be read
|
|
34159
|
+
if (!this.columnsFromFeatureCatalog) {
|
|
34160
|
+
this.columnsFromDataset = await this.dataset_.properties;
|
|
34161
|
+
}
|
|
34162
|
+
this.dataset_.select(...this.columnNames);
|
|
33986
34163
|
await this.dataSource.showData(this.dataset_.read());
|
|
33987
34164
|
this.error = null;
|
|
33988
34165
|
}
|
|
@@ -34012,7 +34189,7 @@ class DataTableComponent {
|
|
|
34012
34189
|
}
|
|
34013
34190
|
}
|
|
34014
34191
|
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
|
|
34192
|
+
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
34193
|
}
|
|
34017
34194
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
34018
34195
|
type: Component,
|
|
@@ -34024,10 +34201,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
34024
34201
|
CommonModule,
|
|
34025
34202
|
LoadingMaskComponent,
|
|
34026
34203
|
PopupAlertComponent,
|
|
34027
|
-
LetDirective,
|
|
34028
34204
|
TranslatePipe,
|
|
34029
34205
|
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
|
|
34206
|
+
], 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
34207
|
}], propDecorators: { featureAttributes: [{
|
|
34032
34208
|
type: Input
|
|
34033
34209
|
}], dataset: [{
|
|
@@ -34130,7 +34306,7 @@ class ChartViewComponent {
|
|
|
34130
34306
|
}), shareReplay$1(1));
|
|
34131
34307
|
this.properties$ = combineLatest([this.dataset$, this.featureCatalog$]).pipe(switchMap$1(([dataset, catalog]) => this.setProperties(dataset, catalog)), shareReplay$1(1));
|
|
34132
34308
|
this.yChoices$ = this.properties$.pipe(map$1((properties) => properties
|
|
34133
|
-
.filter((prop) => prop.type === 'number'
|
|
34309
|
+
.filter((prop) => prop.type === 'number')
|
|
34134
34310
|
.map((prop) => ({ value: prop.name, label: prop.label || prop.name }))), tap$1((choices) => {
|
|
34135
34311
|
if (!choices.find((choice) => choice.value === this.yProperty$.value)) {
|
|
34136
34312
|
const newProp = choices[0]?.value || '';
|
|
@@ -34157,6 +34333,7 @@ class ChartViewComponent {
|
|
|
34157
34333
|
this.aggregation$,
|
|
34158
34334
|
]).pipe(filter$1(([_, x, y]) => !!x || !!y), switchMap$1(([dataset, xProp, yProp, aggregation]) => {
|
|
34159
34335
|
const fieldAgg = aggregation === 'count' ? ['count'] : [aggregation, yProp];
|
|
34336
|
+
this.loading = true;
|
|
34160
34337
|
return dataset
|
|
34161
34338
|
.groupBy(['distinct', xProp])
|
|
34162
34339
|
.aggregate(fieldAgg)
|
|
@@ -34398,6 +34575,7 @@ class GeoTableViewComponent {
|
|
|
34398
34575
|
}));
|
|
34399
34576
|
}
|
|
34400
34577
|
async initMapContext() {
|
|
34578
|
+
this.dataset.load();
|
|
34401
34579
|
this.dataset.selectAll();
|
|
34402
34580
|
return {
|
|
34403
34581
|
layers: [
|
|
@@ -34571,8 +34749,7 @@ class MdViewFacade {
|
|
|
34571
34749
|
}));
|
|
34572
34750
|
this.error$ = this.store.pipe(select(getMetadataError));
|
|
34573
34751
|
this.related$ = this.store.pipe(select(getRelated));
|
|
34574
|
-
this.
|
|
34575
|
-
this.sourceOf$ = this.store.pipe(select(getSourceOf));
|
|
34752
|
+
this.linkedRecords$ = this.store.pipe(select(getLinkedRecords));
|
|
34576
34753
|
this.chartConfig$ = this.store.pipe(select(getChartConfig));
|
|
34577
34754
|
this.allLinks$ = this.metadata$.pipe(map$1((record) => 'onlineResources' in record ? record.onlineResources : []), shareReplay$1(1));
|
|
34578
34755
|
this.resourceDoi$ = this.metadata$.pipe(map$1((record) => {
|
|
@@ -34691,12 +34868,9 @@ class MdViewEffects {
|
|
|
34691
34868
|
this.loadRelatedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getSimilarRecords(full)), map$1((related) => {
|
|
34692
34869
|
return setRelated({ related });
|
|
34693
34870
|
}), 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 })))));
|
|
34871
|
+
this.loadLinkedRecords$ = createEffect(() => this.actions$.pipe(ofType(loadFullMetadataSuccess), switchMap$1(({ full }) => this.recordsRepository.getLinkedRecords(full)), map$1((linkedRecords) => {
|
|
34872
|
+
return setLinkedRecords({ linkedRecords });
|
|
34873
|
+
}), catchError(() => of(setLinkedRecords({ linkedRecords: null })))));
|
|
34700
34874
|
/*
|
|
34701
34875
|
UserFeedback effects
|
|
34702
34876
|
*/
|
|
@@ -36430,6 +36604,11 @@ const DEFAULT_CONFIGURATION = {
|
|
|
36430
36604
|
},
|
|
36431
36605
|
hidden: '${record.kind == "service"}',
|
|
36432
36606
|
},
|
|
36607
|
+
{
|
|
36608
|
+
model: 'associatedRecords',
|
|
36609
|
+
formFieldConfig: {},
|
|
36610
|
+
hidden: '${record.kind == "service"}',
|
|
36611
|
+
},
|
|
36433
36612
|
],
|
|
36434
36613
|
},
|
|
36435
36614
|
// Section: Geographical coverage
|
|
@@ -37567,7 +37746,7 @@ class FormFieldTemporalExtentsComponent {
|
|
|
37567
37746
|
provideNgIconsConfig({
|
|
37568
37747
|
size: '1.5rem',
|
|
37569
37748
|
}),
|
|
37570
|
-
], ngImport: i0, template: "<div class=\"flex gap-2
|
|
37749
|
+
], 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
37750
|
}
|
|
37572
37751
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldTemporalExtentsComponent, decorators: [{
|
|
37573
37752
|
type: Component,
|
|
@@ -37584,7 +37763,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37584
37763
|
provideNgIconsConfig({
|
|
37585
37764
|
size: '1.5rem',
|
|
37586
37765
|
}),
|
|
37587
|
-
], template: "<div class=\"flex gap-2
|
|
37766
|
+
], 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
37767
|
}], propDecorators: { value: [{
|
|
37589
37768
|
type: Input
|
|
37590
37769
|
}], valueChange: [{
|
|
@@ -37800,6 +37979,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
37800
37979
|
], 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
37980
|
}] });
|
|
37802
37981
|
|
|
37982
|
+
class FormFieldAssociatedRecordsComponent {
|
|
37983
|
+
constructor() {
|
|
37984
|
+
this.valueChange = new EventEmitter();
|
|
37985
|
+
}
|
|
37986
|
+
get list() {
|
|
37987
|
+
return this.value ?? [];
|
|
37988
|
+
}
|
|
37989
|
+
get first() {
|
|
37990
|
+
return this.list[0];
|
|
37991
|
+
}
|
|
37992
|
+
get rest() {
|
|
37993
|
+
return this.list.slice(1);
|
|
37994
|
+
}
|
|
37995
|
+
get hasParentLink() {
|
|
37996
|
+
return this.list.length > 0;
|
|
37997
|
+
}
|
|
37998
|
+
get uniqueIdentifier() {
|
|
37999
|
+
return this.first?.uniqueIdentifier ?? '';
|
|
38000
|
+
}
|
|
38001
|
+
get selectedType() {
|
|
38002
|
+
return this.first?.associationType;
|
|
38003
|
+
}
|
|
38004
|
+
get choices() {
|
|
38005
|
+
return associationTypeValues.map((value) => ({
|
|
38006
|
+
value,
|
|
38007
|
+
label: `domain.record.associationType.${value}`,
|
|
38008
|
+
}));
|
|
38009
|
+
}
|
|
38010
|
+
onToggle(checked) {
|
|
38011
|
+
this.valueChange.emit(checked
|
|
38012
|
+
? [
|
|
38013
|
+
{
|
|
38014
|
+
uniqueIdentifier: '',
|
|
38015
|
+
associationType: associationTypeValues[0],
|
|
38016
|
+
},
|
|
38017
|
+
...this.rest,
|
|
38018
|
+
]
|
|
38019
|
+
: this.rest);
|
|
38020
|
+
}
|
|
38021
|
+
onUniqueIdentifierChange(uniqueIdentifier) {
|
|
38022
|
+
this.valueChange.emit(uniqueIdentifier
|
|
38023
|
+
? [{ ...this.first, uniqueIdentifier }, ...this.rest]
|
|
38024
|
+
: this.rest);
|
|
38025
|
+
}
|
|
38026
|
+
onTypeChange(associationType) {
|
|
38027
|
+
this.valueChange.emit([
|
|
38028
|
+
{ ...this.first, associationType: associationType },
|
|
38029
|
+
...this.rest,
|
|
38030
|
+
]);
|
|
38031
|
+
}
|
|
38032
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
38033
|
+
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 }); }
|
|
38034
|
+
}
|
|
38035
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldAssociatedRecordsComponent, decorators: [{
|
|
38036
|
+
type: Component,
|
|
38037
|
+
args: [{ selector: 'gn-ui-form-field-associated-records', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
38038
|
+
CheckToggleComponent,
|
|
38039
|
+
TextInputComponent,
|
|
38040
|
+
DropdownSelectorComponent,
|
|
38041
|
+
FormFieldWrapperComponent,
|
|
38042
|
+
TranslatePipe,
|
|
38043
|
+
], 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" }]
|
|
38044
|
+
}], propDecorators: { value: [{
|
|
38045
|
+
type: Input
|
|
38046
|
+
}], valueChange: [{
|
|
38047
|
+
type: Output
|
|
38048
|
+
}] } });
|
|
38049
|
+
|
|
37803
38050
|
class ContactCardComponent {
|
|
37804
38051
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContactCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
37805
38052
|
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 +39432,9 @@ class FormFieldComponent {
|
|
|
39185
39432
|
get valueAsUpdateFrequency() {
|
|
39186
39433
|
return this.value;
|
|
39187
39434
|
}
|
|
39435
|
+
get valueAsAssociatedRecords() {
|
|
39436
|
+
return this.value;
|
|
39437
|
+
}
|
|
39188
39438
|
get valueAsTemporalExtents() {
|
|
39189
39439
|
return this.value;
|
|
39190
39440
|
}
|
|
@@ -39224,7 +39474,7 @@ class FormFieldComponent {
|
|
|
39224
39474
|
}
|
|
39225
39475
|
}
|
|
39226
39476
|
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 }); }
|
|
39477
|
+
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
39478
|
}
|
|
39229
39479
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
39230
39480
|
type: Component,
|
|
@@ -39236,6 +39486,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39236
39486
|
FormFieldLicenseComponent,
|
|
39237
39487
|
FormFieldDateComponent,
|
|
39238
39488
|
FormFieldUpdateFrequencyComponent,
|
|
39489
|
+
FormFieldAssociatedRecordsComponent,
|
|
39239
39490
|
FormFieldTemporalExtentsComponent,
|
|
39240
39491
|
FormFieldSimpleComponent,
|
|
39241
39492
|
FormFieldRichComponent,
|
|
@@ -39253,7 +39504,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
39253
39504
|
FormFieldTopicsComponent,
|
|
39254
39505
|
TextFieldModule,
|
|
39255
39506
|
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"] }]
|
|
39507
|
+
], 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
39508
|
}], propDecorators: { uniqueIdentifier: [{
|
|
39258
39509
|
type: Input
|
|
39259
39510
|
}], recordKind: [{
|
|
@@ -39838,7 +40089,7 @@ class RouterService {
|
|
|
39838
40089
|
return ROUTER_ROUTE_ORGANIZATION;
|
|
39839
40090
|
}
|
|
39840
40091
|
getDefaultSort() {
|
|
39841
|
-
return SortByEnum.
|
|
40092
|
+
return SortByEnum.RESOURCE_DATE;
|
|
39842
40093
|
}
|
|
39843
40094
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39844
40095
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RouterService, providedIn: 'root' }); }
|
|
@@ -40255,5 +40506,5 @@ const CHART_TYPE_VALUES = [
|
|
|
40255
40506
|
* Generated bundle index. Do not edit.
|
|
40256
40507
|
*/
|
|
40257
40508
|
|
|
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 };
|
|
40509
|
+
export { ADD_RESULTS, ADD_SEARCH, AVAILABLE_LICENSES, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, ButtonComponent, CHART_TYPE_VALUES, CLEAR_ERROR, CLEAR_RESULTS, CarouselComponent, CatalogTitleComponent, CellPopinComponent, ChartComponent, ChartViewComponent, CheckToggleComponent, CheckboxComponent, ClearError, ClearResults, ColorScaleComponent, ConfirmationDialogComponent, ContactDetailsComponent, ContactDetailsFormComponent, ContactPillComponent, ContentGhostComponent, CopyTextButtonComponent, DEFAULT_CONFIGURATION, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RECORD_CONVERTER, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DEFAULT_SPATIAL_EXTENT_STYLE, DISABLE_AUTH, DISABLE_DRAFT, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldFocusDirective, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingComponent, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, I18nInterceptor, ISO_TOPICS, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KeywordBadgeComponent, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, MAX_UPLOAD_SIZE_MB, METADATA_LANGUAGE, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapStyleService, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, OPEN_DATA_LICENSE, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OnlineResourceCardComponent, OnlineServiceResourceInputComponent, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_DATASET_URL_TOKEN, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESULTS_LAYOUT_CONFIG, REUSE_LIGHT_CONFIGURATION, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordStatusValues, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, ResourceTypeLegacyField, ResultsHitsContainerComponent, ResultsHitsNumberComponent, ResultsHitsSearchKindComponent, ResultsLayoutComponent, ResultsLayoutConfigItem, ResultsListComponent, ResultsListContainerComponent, ResultsListItemComponent, ResultsTableComponent, ResultsTableContainerComponent, ReusePresentationForms, RoleLabels, RoleValues, RouterEffects, RouterFacade, RouterService, SEARCH_FEATURE_KEY, SETTINGS_URL, SET_CONFIG_AGGREGATIONS, SET_CONFIG_FILTERS, SET_CONFIG_REQUEST_FIELDS, SET_ERROR, SET_FAVORITES_ONLY, SET_FILTERS, SET_INCLUDE_ON_AGGREGATION, SET_PAGE_SIZE, SET_RESULTS_AGGREGATIONS, SET_RESULTS_HITS, SET_RESULTS_LAYOUT, SET_SEARCH, SET_SORT_BY, SET_SPATIAL_FILTER_ENABLED, SPATIAL_SCOPES, SearchEffects, SearchFacade, SearchFeatureCatalogComponent, SearchFiltersSummaryComponent, SearchFiltersSummaryItemComponent, SearchInputComponent, SearchRouterContainerDirective, SearchService, SearchStateContainerDirective, SelectionService, ServiceCapabilitiesComponent, SetConfigAggregations, SetConfigFilters, SetConfigRequestFields, SetError, SetFavoritesOnly, SetFilters, SetIncludeOnAggregation, SetPageSize, SetResultsAggregations, SetResultsHits, SetResultsLayout, SetSearch, SetSortBy, SetSpatialFilterEnabled, SimpleSearchField, SiteTitleComponent, SortByComponent, SortByEnum, SortableListComponent, SourceLabelComponent, SourcesService, SpatialExtentComponent, SpinningLoaderComponent, StacItemsResultGridComponent, StacViewComponent, StarToggleComponent, StickyHeaderComponent, SupportedTypes, SwitchToggleComponent, THUMBNAIL_PLACEHOLDER, TRANSLATE_DEBUG_CONFIG, TRANSLATE_DEFAULT_CONFIG, TRANSLATE_WITH_OVERRIDES_CONFIG, TableViewComponent, TextAreaComponent, TextInputComponent, ThemeService, ThumbnailComponent, TranslatedSearchField, TruncatedTextComponent, UPDATE_CONFIG_AGGREGATIONS, UPDATE_FILTERS, UPDATE_REQUEST_AGGREGATION_TERM, UpdateConfigAggregations, UpdateFilters, UrlInputComponent, UserFeedbackItemComponent, UserPreviewComponent, UserSearchField, VECTOR_STYLE_DEFAULT, ViewportIntersectorComponent, WEB_COMPONENT_EMBEDDER_URL, XmlParseError, _reset, allChildrenElement, appConfigWithTranslationFixture, appendChildTree, appendChildren, assertValidXml, associationTypeValues, bboxToPolygon, blockModelFixture, bytesToMegabytes, canEditRecord, checkFileFormat, clearSelectedFeatures, createChild, createDocument, createElement, createFuzzyFilter, createNestedChild, createNestedElement, createSpatialExtentLayer, currentPage, defaultMapStyleFixture, defaultMapStyleHlFixture, downgradeImage, downsizeImage, draftSaveSuccess, dragPanCondition, dropEmptyTranslations, editorReducer, emptyBlockModelFixture, findChildElement, findChildOrCreate, findChildrenElement, findConverterForDocument, findNestedChildOrCreate, findNestedElement, findNestedElements, findParent, firstChildElement, formatDate, formatUserInfo, getAddressLines, getAllKeysValidator, getArrayItem, getAsArray, getAsUrl, getBadgeColor, getCustomTranslations, getError, getFavoritesOnly, getFileFormat, getFileFormatFromServiceOutput, getFirstValue, getFormatPriority, getGeometryBoundingBox, getGeometryFromGeoJSON, getGlobalConfig, getIndividualDisplayName, getIsMobile, getJsonDataItemsProxy, getKeywordHierarchyPath, getLayers, getLinkId, getLinkLabel, getLinkPriority, getMapContext, getMapContextLayerFromConfig, getMapState, getMetadataQualityConfig, getMimeTypeForFormat, getNamespace, getOptionalEditorConfig, getOptionalMapConfig, getOptionalSearchConfig, getPageSize, getQualityValidators, getResourceType, getReusePresentationForm, getReuseType, getRootElement, getSearchConfigAggregations, getSearchFilters, getSearchResults, getSearchResultsAggregations, getSearchResultsHits, getSearchResultsLayout, getSearchResultsLoading, getSearchSortBy, getSearchState, getSearchStateSearch, getSelectedFeatures, getSpatialFilterEnabled, getTemporalRangeUnion, getThemeConfig, handleScrollOnNavigation, hasRecordChangedSinceDraft, hasRecordChangedSinceDraftSuccess, initSearch, initialEditorState, initialMapState, initialState, isConfigLoaded, isDateRange, isFormatInQueryParam, isPublished, itemModelFixture, kindToCodeListValue, loadAppConfig, malformedConfigFixture, mapConfigFixture, mapContact, mapKeywords, mapLogo, mapOrganization, mapReducer, markRecordAsChanged, matchesNoApplicableConstraint, matchesNoKnownConstraint, megabytesToBytes, mimeTypeToFormat, minimalAppConfigFixture, missingMandatoryConfigFixture, mouseWheelZoomCondition, noDuplicateFileName, okAppConfigFixture, openDataset, openRecord, organizationsServiceFactory, parse, parseXmlString, placeholder, prioritizePageScroll, propagateToDocumentOnly, provideGn4, provideI18n, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, readText, reducer$2 as reducer, reducerSearch, removeAllChildren, removeChildren, removeChildrenByName, removeSearchParams, removeWhitespace, renameElements, saveRecord, saveRecordFailure, saveRecordSuccess, selectCanEditRecord, selectCurrentPage, selectEditorConfig, selectEditorState, selectFallback, selectFallbackFields, selectField, selectHasRecordChanged, selectIsPublished, selectRecord, selectRecordChangedSinceSave, selectRecordSaveError, selectRecordSaving, selectRecordSections, selectRecordSource, selectTranslatedField, selectTranslatedValue, setContext, setCurrentPage, setEditorConfiguration, setFieldVisibility, setFocusedField, setSelectedFeatures, setTextContent, sortByFromString, sortByToString, sortByToStrings, spatialExtentToGeometry, spatialExtentsToFeatureCollection, stripHtml, stripNamespace, toDate, toIndividual, toLang2, toLang3, totalPages, undoRecordDraft, unrecognizedKeysConfigFixture, updateFrequencyCodeValues, updateLanguages, updateRecordField, updateRecordLanguages, wmsLayerFlatten, writeAttribute, wrongLanguageCodeConfigFixture, xmlToString };
|
|
40259
40510
|
//# sourceMappingURL=geonetwork-ui.mjs.map
|