geonetwork-ui 2.9.0-dev.2757b04b7 → 2.9.0-dev.27de12f92
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 +701 -566
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +254 -162
- package/index.d.ts.map +1 -1
- package/package.json +7 -8
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +5 -1
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +1 -0
- package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.html +10 -12
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +33 -11
- package/src/libs/feature/editor/src/index.ts +8 -7
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +6 -1
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +5 -1
- package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +4 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +2 -2
- package/src/libs/feature/record/src/lib/external-viewer-button/external-viewer-button.component.ts +2 -0
- package/src/libs/feature/record/src/lib/gpf-api-dl/gpf-api-dl.component.html +4 -4
- package/src/libs/feature/record/src/lib/gpf-api-dl/gpf-api-dl.component.ts +3 -4
- package/src/libs/feature/record/src/lib/map-view/map-view.component.html +10 -18
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +96 -9
- package/src/libs/feature/record/src/lib/state/mdview.facade.ts +1 -1
- package/src/libs/feature/router/src/lib/default/router.module.ts +3 -3
- package/src/libs/feature/router/src/lib/default/router.service.ts +2 -2
- package/src/libs/feature/router/src/lib/default/services/router-search.service.ts +12 -3
- package/src/libs/feature/router/src/lib/default/state/router.effects.ts +34 -4
- package/src/libs/feature/search/src/lib/state/reducer.ts +3 -0
- package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +9 -3
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +5 -5
- package/src/libs/ui/elements/src/lib/api-card/api-card.component.html +2 -2
- package/src/libs/ui/elements/src/lib/application-banner/application-banner.component.ts +2 -3
- package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.ts +5 -3
- package/src/libs/ui/elements/src/lib/image-input/image-input.component.html +5 -2
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +63 -56
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.scss +5 -5
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +11 -8
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.ts +3 -3
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.html +1 -1
- package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +7 -5
- package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.ts +1 -1
- package/src/libs/ui/map/src/lib/map-utils.ts +1 -1
- package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.html +19 -16
- package/src/libs/util/app-config/src/lib/app-config.ts +10 -2
- package/src/libs/util/app-config/src/lib/fixtures.ts +1 -0
- package/src/libs/util/app-config/src/lib/model.ts +2 -0
- package/src/libs/util/shared/src/lib/gn-ui-version.ts +5 -4
- package/src/libs/util/shared/src/lib/links/link-utils.ts +8 -4
- package/src/libs/util/shared/src/lib/services/theme.service.ts +9 -23
- package/tailwind.base.config.js +3 -2
- package/translations/de.json +6 -3
- package/translations/en.json +8 -5
- package/translations/es.json +3 -0
- package/translations/fr.json +8 -5
- package/translations/it.json +8 -5
- package/translations/nl.json +3 -0
- package/translations/pt.json +3 -0
- package/translations/sk.json +4 -1
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
ChangeDetectionStrategy,
|
|
3
3
|
ChangeDetectorRef,
|
|
4
4
|
Component,
|
|
5
|
-
Input,
|
|
6
5
|
inject,
|
|
6
|
+
Input,
|
|
7
7
|
} from '@angular/core'
|
|
8
8
|
import { TranslateDirective, TranslateService } from '@ngx-translate/core'
|
|
9
9
|
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
|
|
@@ -67,13 +67,15 @@ export class DownloadsListComponent {
|
|
|
67
67
|
): DatasetDownloadDistribution[] {
|
|
68
68
|
const preferredLinks = new Map<string, DatasetDownloadDistribution>()
|
|
69
69
|
|
|
70
|
-
links.forEach((link) => {
|
|
70
|
+
links.forEach((link, index) => {
|
|
71
71
|
const format = getFileFormat(link)
|
|
72
72
|
const withoutNameSpace = (link.name || link.description || '').replace(
|
|
73
73
|
/^.*?:/,
|
|
74
74
|
''
|
|
75
75
|
)
|
|
76
|
-
const uniqueKey =
|
|
76
|
+
const uniqueKey = link.accessServiceProtocol
|
|
77
|
+
? `${format}-${withoutNameSpace}`
|
|
78
|
+
: index.toString() // direct download links should not be deduplicated
|
|
77
79
|
if (!preferredLinks.has(uniqueKey)) {
|
|
78
80
|
preferredLinks.set(uniqueKey, link)
|
|
79
81
|
} else {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
@if (previewUrl) {
|
|
2
|
-
<div class="w-
|
|
3
|
-
<gn-ui-image-overlay-preview
|
|
2
|
+
<div class="w-[314px] h-full flex flex-col gap-2">
|
|
3
|
+
<gn-ui-image-overlay-preview
|
|
4
|
+
class="w-[314px] h-[314px]"
|
|
5
|
+
[imageUrl]="previewUrl"
|
|
6
|
+
>
|
|
4
7
|
</gn-ui-image-overlay-preview>
|
|
5
8
|
@if (showAltTextInput) {
|
|
6
9
|
<gn-ui-text-input
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</div>
|
|
15
15
|
}
|
|
16
16
|
<div class="grow pt-1" [ngClass]="shouldShowThumbnail ? 'sm:w-0' : ''">
|
|
17
|
-
<div class="flex flex-col gap-2 h-full">
|
|
17
|
+
<div class="flex flex-col gap-2" [class.h-full]="size !== 'M'">
|
|
18
18
|
<h4
|
|
19
19
|
class="record-card__title"
|
|
20
20
|
data-cy="recordTitle"
|
|
@@ -32,63 +32,70 @@
|
|
|
32
32
|
[title]="abstract"
|
|
33
33
|
></gn-ui-markdown-parser>
|
|
34
34
|
</div>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
@if (size !== 'M') {
|
|
36
|
+
<ng-container [ngTemplateOutlet]="footerTpl"></ng-container>
|
|
37
|
+
}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
@if (size === 'M') {
|
|
41
|
+
<ng-container [ngTemplateOutlet]="footerTpl"></ng-container>
|
|
42
|
+
}
|
|
43
|
+
</a>
|
|
44
|
+
|
|
45
|
+
<ng-template #footerTpl>
|
|
46
|
+
<div class="record-card__footer">
|
|
47
|
+
@if (record.ownerOrganization?.name) {
|
|
48
|
+
<div
|
|
49
|
+
data-cy="recordOrg"
|
|
50
|
+
class="grow flex flex-row gap-1 items-center text-primary-lighter"
|
|
51
|
+
[ngClass]="displayContactIconOnly ? 'justify-center' : ''"
|
|
52
|
+
>
|
|
53
|
+
<ng-icon
|
|
54
|
+
name="iconoirBank"
|
|
55
|
+
class="text-primary -translate-y-[0.5px] shrink-0"
|
|
56
|
+
[title]="record.ownerOrganization.name"
|
|
57
|
+
></ng-icon>
|
|
58
|
+
@if (!displayContactIconOnly) {
|
|
59
|
+
<span
|
|
60
|
+
data-cy="recordOrgName"
|
|
61
|
+
class="line-clamp-1"
|
|
62
|
+
[title]="record.ownerOrganization.name"
|
|
63
|
+
>{{ record.ownerOrganization.name }}</span
|
|
41
64
|
>
|
|
42
|
-
<ng-icon
|
|
43
|
-
name="iconoirBank"
|
|
44
|
-
class="text-primary -translate-y-[0.5px] shrink-0"
|
|
45
|
-
[title]="record.ownerOrganization.name"
|
|
46
|
-
></ng-icon>
|
|
47
|
-
@if (!displayContactIconOnly) {
|
|
48
|
-
<span
|
|
49
|
-
data-cy="recordOrgName"
|
|
50
|
-
class="line-clamp-1"
|
|
51
|
-
[title]="record.ownerOrganization.name"
|
|
52
|
-
>{{ record.ownerOrganization.name }}</span
|
|
53
|
-
>
|
|
54
|
-
}
|
|
55
|
-
</div>
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
66
|
+
</div>
|
|
67
|
+
}
|
|
68
|
+
<div class="record-card__footer__other">
|
|
69
|
+
<div class="xs:border-r last:border-r-0 flex grow gap-4 px-4 last:pr-0">
|
|
70
|
+
<gn-ui-kind-badge
|
|
71
|
+
[extraClass]="'text-[1.2em]'"
|
|
72
|
+
[styling]="'gray'"
|
|
73
|
+
[kind]="record?.kind"
|
|
74
|
+
[contentTemplate]="customTemplate"
|
|
75
|
+
class="pt-1"
|
|
76
|
+
>
|
|
77
|
+
<ng-template #customTemplate></ng-template
|
|
78
|
+
></gn-ui-kind-badge>
|
|
79
|
+
@if (metadataQualityDisplay) {
|
|
80
|
+
<gn-ui-metadata-quality
|
|
81
|
+
class="flex items-center min-w-[113px]"
|
|
82
|
+
[smaller]="true"
|
|
83
|
+
[metadata]="record"
|
|
84
|
+
[metadataQualityDisplay]="metadataQualityDisplay"
|
|
85
|
+
[popoverDisplay]="true"
|
|
86
|
+
></gn-ui-metadata-quality>
|
|
87
|
+
}
|
|
88
|
+
</div>
|
|
89
|
+
<div
|
|
90
|
+
class="flex justify-center"
|
|
91
|
+
data-cy="recordFav"
|
|
92
|
+
[ngClass]="displayContactIconOnly ? 'px-1' : 'px-4'"
|
|
93
|
+
>
|
|
94
|
+
<ng-container
|
|
95
|
+
[ngTemplateOutlet]="favoriteTemplate"
|
|
96
|
+
[ngTemplateOutletContext]="{ $implicit: record }"
|
|
97
|
+
></ng-container>
|
|
91
98
|
</div>
|
|
92
99
|
</div>
|
|
93
100
|
</div>
|
|
94
|
-
</
|
|
101
|
+
</ng-template>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
&.size-M {
|
|
9
|
-
@apply max-w-[940px]
|
|
9
|
+
@apply max-w-[940px] gap-4 flex-wrap;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
&.size-S {
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
@apply border rounded-lg overflow-hidden shrink-0;
|
|
29
29
|
|
|
30
30
|
.size-L & {
|
|
31
|
-
@apply w-
|
|
31
|
+
@apply w-[184px] h-[184px];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.size-M & {
|
|
35
|
-
@apply w-
|
|
35
|
+
@apply w-[138px] h-[138px];
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
.size-M & {
|
|
47
|
-
@apply line-clamp-2
|
|
47
|
+
@apply line-clamp-2;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
.size-S & {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
.size-M & {
|
|
67
|
-
@apply line-clamp-3
|
|
67
|
+
@apply line-clamp-3;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
.size-S & {
|
|
@@ -29,16 +29,19 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
@if (shownOrganization?.website) {
|
|
31
31
|
<div>
|
|
32
|
-
<
|
|
33
|
-
[href]="shownOrganization.website"
|
|
34
|
-
target="_blank"
|
|
35
|
-
class="contact-website text-sm cursor-pointer hover:underline transition-all"
|
|
36
|
-
>{{ shownOrganization.website }}
|
|
32
|
+
<div class="flex items-center mt-1">
|
|
37
33
|
<ng-icon
|
|
38
|
-
class="!w-
|
|
34
|
+
class="!w-5 !h-5 !text-[20px] opacity-75 shrink-0"
|
|
39
35
|
name="matOpenInNew"
|
|
40
36
|
></ng-icon>
|
|
41
|
-
|
|
37
|
+
<a
|
|
38
|
+
[href]="shownOrganization.website"
|
|
39
|
+
target="_blank"
|
|
40
|
+
class="contact-website text-sm cursor-pointer hover:underline transition-all ml-2"
|
|
41
|
+
>
|
|
42
|
+
{{ shownOrganization.website }}
|
|
43
|
+
</a>
|
|
44
|
+
</div>
|
|
42
45
|
</div>
|
|
43
46
|
}
|
|
44
47
|
</div>
|
|
@@ -82,7 +85,7 @@
|
|
|
82
85
|
class="!w-5 !h-5 !text-[20px] opacity-75 shrink-0"
|
|
83
86
|
name="matPersonOutline"
|
|
84
87
|
></ng-icon>
|
|
85
|
-
<div class="flex flex-col ml-2">
|
|
88
|
+
<div class="flex flex-col ml-2" data-cy="contact-full-name">
|
|
86
89
|
<p class="text-sm">
|
|
87
90
|
{{ contacts[0]?.firstName || '' }}
|
|
88
91
|
{{ contacts[0]?.lastName || '' }}
|
|
@@ -52,9 +52,9 @@ export class MetadataContactComponent {
|
|
|
52
52
|
|
|
53
53
|
get contacts() {
|
|
54
54
|
return (
|
|
55
|
-
(this.metadata.kind === '
|
|
56
|
-
? this.metadata.
|
|
57
|
-
: this.metadata.
|
|
55
|
+
(this.metadata.kind === 'service'
|
|
56
|
+
? this.metadata.contacts
|
|
57
|
+
: this.metadata.contactsForResource) || []
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</div>
|
|
7
7
|
<button
|
|
8
8
|
(click)="resetUrl()"
|
|
9
|
-
class="bg-primary
|
|
9
|
+
class="bg-primary/50 inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded capitalize text-primary-lightest hover:bg-primary transition-colors"
|
|
10
10
|
>
|
|
11
11
|
<p class="text-[13px] uppercase" translate>
|
|
12
12
|
record.metadata.api.form.reset
|
package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.html
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@if (apiLinks.length > 0) {
|
|
2
2
|
<div style="height: 652px" id="preview">
|
|
3
|
-
<div class="bg-primary
|
|
3
|
+
<div class="bg-primary/10 overflow-visible" style="height: 420px">
|
|
4
4
|
<div class="container-lg px-4 lg:mx-auto">
|
|
5
5
|
<div>
|
|
6
6
|
<div class="gn-ui-section-title mb-6" translate>
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
filter,
|
|
30
30
|
finalize,
|
|
31
31
|
map,
|
|
32
|
+
shareReplay,
|
|
32
33
|
switchMap,
|
|
33
34
|
take,
|
|
34
35
|
tap,
|
|
@@ -139,9 +140,8 @@ export class AutocompleteComponent
|
|
|
139
140
|
ngOnChanges(changes: SimpleChanges): void {
|
|
140
141
|
const { value } = changes
|
|
141
142
|
if (value) {
|
|
142
|
-
const previousTextValue = this.displayWithFnInternal(value.previousValue)
|
|
143
143
|
const currentTextValue = this.displayWithFnInternal(value.currentValue)
|
|
144
|
-
if (
|
|
144
|
+
if (currentTextValue !== this.control.value) {
|
|
145
145
|
if (currentTextValue) {
|
|
146
146
|
this.searchActive = true
|
|
147
147
|
this.isSearchActive.emit(true)
|
|
@@ -160,8 +160,8 @@ export class AutocompleteComponent
|
|
|
160
160
|
this.inputCleared.pipe(map(() => '')),
|
|
161
161
|
this.control.valueChanges.pipe(
|
|
162
162
|
filter((value) => typeof value === 'string'),
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
debounceTime(400),
|
|
164
|
+
distinctUntilChanged()
|
|
165
165
|
)
|
|
166
166
|
)
|
|
167
167
|
|
|
@@ -181,7 +181,8 @@ export class AutocompleteComponent
|
|
|
181
181
|
this.searching = true
|
|
182
182
|
this.error = null
|
|
183
183
|
}),
|
|
184
|
-
switchMap((value) => this.action(value)),
|
|
184
|
+
switchMap((value) => this.action(value)), // this can trigger http requests
|
|
185
|
+
shareReplay(1), // share the loaded suggestions to avoid multiple requests
|
|
185
186
|
tap((suggestions) => {
|
|
186
187
|
// forcing the panel to open if there are suggestions
|
|
187
188
|
if (suggestions.length > 0 && !this.searchActive) {
|
|
@@ -288,6 +289,7 @@ export class AutocompleteComponent
|
|
|
288
289
|
|
|
289
290
|
clear(): void {
|
|
290
291
|
this.inputRef.nativeElement.value = ''
|
|
292
|
+
this.control.setValue('')
|
|
291
293
|
this.searchActive = false
|
|
292
294
|
this.isSearchActive.emit(false)
|
|
293
295
|
this.inputCleared.emit()
|
|
@@ -50,7 +50,7 @@ export function dragPanCondition(
|
|
|
50
50
|
|
|
51
51
|
export function mouseWheelZoomCondition(
|
|
52
52
|
this: MouseWheelZoom,
|
|
53
|
-
event: MapBrowserEvent<
|
|
53
|
+
event: MapBrowserEvent<WheelEvent>
|
|
54
54
|
) {
|
|
55
55
|
if (!platformModifierKeyOnly(event) && event.type === 'wheel') {
|
|
56
56
|
this.getMap().dispatchEvent('mapmuted')
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
></gn-ui-thumbnail>
|
|
31
31
|
}
|
|
32
32
|
</div>
|
|
33
|
-
<div class="flex flex-col overflow-hidden items-start">
|
|
33
|
+
<div class="flex flex-col overflow-hidden items-start grow">
|
|
34
34
|
@if (hasOrganization) {
|
|
35
35
|
<span
|
|
36
36
|
class="font-bold transition duration-200 text-primary truncate max-w-full"
|
|
@@ -51,32 +51,35 @@
|
|
|
51
51
|
>
|
|
52
52
|
</p>
|
|
53
53
|
</div>
|
|
54
|
-
|
|
55
|
-
<div class="pt-5 pb-5 px-10 relative">
|
|
56
|
-
<div class="absolute top-[0.85em] right-[0.85em]">
|
|
54
|
+
<div class="ml-3 shrink-0">
|
|
57
55
|
<ng-container
|
|
58
56
|
[ngTemplateOutlet]="favoriteTemplate"
|
|
59
57
|
[ngTemplateOutletContext]="{ $implicit: record }"
|
|
60
58
|
></ng-container>
|
|
61
59
|
</div>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
</div>
|
|
61
|
+
<div class="pt-5 pb-5 px-10 relative">
|
|
62
|
+
<div class="flex flex-col sm:flex-row gap-4 mb-3">
|
|
63
|
+
@if (record.overviews?.[0]) {
|
|
64
|
+
<gn-ui-thumbnail
|
|
65
|
+
class="block shrink-0 w-[120px] h-[120px] border border-gray-100 rounded-lg overflow-hidden"
|
|
66
|
+
[thumbnailUrl]="record.overviews?.[0]?.url.toString()"
|
|
67
|
+
[fit]="'cover'"
|
|
68
|
+
></gn-ui-thumbnail>
|
|
69
|
+
}
|
|
70
|
+
<h1
|
|
71
|
+
class="font-title text-black text-[21px] font-medium"
|
|
72
|
+
data-cy="recordTitle"
|
|
73
|
+
>
|
|
74
|
+
{{ record.title }}
|
|
75
|
+
</h1>
|
|
76
|
+
</div>
|
|
68
77
|
<p class="line-clamp-3">
|
|
69
78
|
<gn-ui-markdown-parser
|
|
70
79
|
[textContent]="abstract"
|
|
71
80
|
[whitoutStyles]="true"
|
|
72
81
|
/>
|
|
73
82
|
</p>
|
|
74
|
-
@if (record.overviews?.[0]) {
|
|
75
|
-
<gn-ui-thumbnail
|
|
76
|
-
class="block mt-3 w-full h-[136px] border border-gray-100 rounded-lg overflow-hidden"
|
|
77
|
-
[thumbnailUrl]="record.overviews?.[0]?.url.toString()"
|
|
78
|
-
></gn-ui-thumbnail>
|
|
79
|
-
}
|
|
80
83
|
@if (isDownloadable || isViewable) {
|
|
81
84
|
<div class="flex flex-row mt-3">
|
|
82
85
|
@if (isDownloadable) {
|
|
@@ -70,8 +70,11 @@ export function getCustomTranslations(langCode: string): CustomTranslations {
|
|
|
70
70
|
|
|
71
71
|
let appConfigLoaded = false
|
|
72
72
|
|
|
73
|
-
export function loadAppConfig() {
|
|
74
|
-
|
|
73
|
+
export function loadAppConfig(configUrl = 'assets/configuration/default.toml') {
|
|
74
|
+
console.log(
|
|
75
|
+
`[geonetwork-ui] Loading application configuration from ${configUrl}`
|
|
76
|
+
)
|
|
77
|
+
return fetch(configUrl)
|
|
75
78
|
.then((resp) => {
|
|
76
79
|
if (!resp.ok) throw new Error('Configuration file could not be loaded')
|
|
77
80
|
return resp.text()
|
|
@@ -94,6 +97,7 @@ export function loadAppConfig() {
|
|
|
94
97
|
['geonetwork4_api_url'],
|
|
95
98
|
[
|
|
96
99
|
'datahub_url',
|
|
100
|
+
'edit_url_template',
|
|
97
101
|
'proxy_path',
|
|
98
102
|
'metadata_language',
|
|
99
103
|
'login_url',
|
|
@@ -119,6 +123,7 @@ export function loadAppConfig() {
|
|
|
119
123
|
: ({
|
|
120
124
|
GN4_API_URL: parsedGlobalSection.geonetwork4_api_url,
|
|
121
125
|
DATAHUB_URL: parsedGlobalSection.datahub_url,
|
|
126
|
+
EDIT_URL_TEMPLATE: parsedGlobalSection.edit_url_template,
|
|
122
127
|
PROXY_PATH: parsedGlobalSection.proxy_path,
|
|
123
128
|
METADATA_LANGUAGE: parsedGlobalSection.metadata_language
|
|
124
129
|
? (
|
|
@@ -229,6 +234,7 @@ export function loadAppConfig() {
|
|
|
229
234
|
'record_kind_quick_filter',
|
|
230
235
|
'filter_geometry_data',
|
|
231
236
|
'filter_geometry_url',
|
|
237
|
+
'do_not_use_default_search_preset',
|
|
232
238
|
'search_preset',
|
|
233
239
|
'advanced_filters',
|
|
234
240
|
'limit',
|
|
@@ -252,6 +258,8 @@ export function loadAppConfig() {
|
|
|
252
258
|
parsedSearchSection.record_kind_quick_filter,
|
|
253
259
|
FILTER_GEOMETRY_DATA: parsedSearchSection.filter_geometry_data,
|
|
254
260
|
FILTER_GEOMETRY_URL: parsedSearchSection.filter_geometry_url,
|
|
261
|
+
DO_NOT_USE_DEFAULT_SEARCH_PRESET:
|
|
262
|
+
!!parsedSearchSection.do_not_use_default_search_preset,
|
|
255
263
|
SEARCH_PRESET: parsedSearchParams.map((param) => ({
|
|
256
264
|
sort: param.sort,
|
|
257
265
|
name: param.name,
|
|
@@ -40,6 +40,7 @@ fonts_stylesheet_url = "https://fonts.googleapis.com/css2?family=Open+Sans"
|
|
|
40
40
|
[search]
|
|
41
41
|
record_kind_quick_filter = false
|
|
42
42
|
filter_geometry_url = 'https://my.domain.org/geom.json'
|
|
43
|
+
do_not_use_default_search_preset = false
|
|
43
44
|
advanced_filters = ['publicationYear', 'documentStandard', 'inspireKeyword', 'topic', 'license']
|
|
44
45
|
|
|
45
46
|
[[search_preset]]
|
|
@@ -3,6 +3,7 @@ import { Geometry } from 'geojson'
|
|
|
3
3
|
export interface GlobalConfig {
|
|
4
4
|
GN4_API_URL: string
|
|
5
5
|
DATAHUB_URL?: string
|
|
6
|
+
EDIT_URL_TEMPLATE?: string
|
|
6
7
|
PROXY_PATH?: string
|
|
7
8
|
METADATA_LANGUAGE?: string
|
|
8
9
|
LOGIN_URL?: string
|
|
@@ -58,6 +59,7 @@ export interface SearchConfig {
|
|
|
58
59
|
RECORD_KIND_QUICK_FILTER?: boolean
|
|
59
60
|
FILTER_GEOMETRY_URL?: string
|
|
60
61
|
FILTER_GEOMETRY_DATA?: string
|
|
62
|
+
DO_NOT_USE_DEFAULT_SEARCH_PRESET?: boolean
|
|
61
63
|
SEARCH_PRESET?: SearchPreset[]
|
|
62
64
|
ADVANCED_FILTERS?: []
|
|
63
65
|
LIMIT?: number
|
|
@@ -2,7 +2,8 @@ import packageJson from '../../../../../package.json'
|
|
|
2
2
|
|
|
3
3
|
export const GEONETWORK_UI_VERSION = packageJson.version
|
|
4
4
|
|
|
5
|
-
export const GEONETWORK_UI_TAG_NAME =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export const GEONETWORK_UI_TAG_NAME = GEONETWORK_UI_VERSION.split(
|
|
6
|
+
'-'
|
|
7
|
+
)[1]?.startsWith('dev')
|
|
8
|
+
? 'main'
|
|
9
|
+
: `v${packageJson.version}`
|
|
@@ -331,11 +331,15 @@ export async function getLayers(url: string, serviceProtocol: ServiceProtocol) {
|
|
|
331
331
|
case 'wfs': {
|
|
332
332
|
const endpointWfs = await new WfsEndpoint(url).isReady()
|
|
333
333
|
const featureTypes = await endpointWfs.getFeatureTypes()
|
|
334
|
-
const layers =
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
334
|
+
const layers = (
|
|
335
|
+
await Promise.allSettled(
|
|
336
|
+
featureTypes.map((collection) => {
|
|
337
|
+
return endpointWfs.getFeatureTypeFull(collection.name)
|
|
338
|
+
})
|
|
339
|
+
)
|
|
338
340
|
)
|
|
341
|
+
.filter((settled) => settled.status === 'fulfilled')
|
|
342
|
+
.map((fulfilled) => fulfilled.value)
|
|
339
343
|
return layers
|
|
340
344
|
}
|
|
341
345
|
case 'wms': {
|
|
@@ -10,26 +10,6 @@ export class ThemeService {
|
|
|
10
10
|
return document.documentElement.style.getPropertyValue(`--color-${name}`)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
static generateBgOpacityClasses(
|
|
14
|
-
colorName,
|
|
15
|
-
colorValue,
|
|
16
|
-
opacities = [0, 10, 25, 50, 75]
|
|
17
|
-
) {
|
|
18
|
-
const color = chroma(colorValue)
|
|
19
|
-
const styleElement = document.createElement('style')
|
|
20
|
-
styleElement.innerHTML = opacities.reduce((cssRules, opacity) => {
|
|
21
|
-
cssRules += `.bg-${colorName}-opacity-${opacity}{background-color:${color
|
|
22
|
-
.alpha(opacity / 100)
|
|
23
|
-
.css()};}`
|
|
24
|
-
|
|
25
|
-
cssRules += `.hover-bg-${colorName}-opacity-${opacity}:hover {background-color:${color
|
|
26
|
-
.alpha(opacity / 100)
|
|
27
|
-
.css()};}`
|
|
28
|
-
return cssRules
|
|
29
|
-
}, '')
|
|
30
|
-
document.getElementsByTagName('head')[0].appendChild(styleElement)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
13
|
static applyCssVariables(
|
|
34
14
|
primaryColor: string,
|
|
35
15
|
secondaryColor: string,
|
|
@@ -39,13 +19,19 @@ export class ThemeService {
|
|
|
39
19
|
titleFont?: string,
|
|
40
20
|
fontsStylesheetUrl?: string
|
|
41
21
|
) {
|
|
42
|
-
const applyColor = (name: string, color) => {
|
|
22
|
+
const applyColor = (name: string, color, includeRawValues?: boolean) => {
|
|
43
23
|
document.documentElement.style.setProperty(`--color-${name}`, color.css())
|
|
24
|
+
if (includeRawValues) {
|
|
25
|
+
document.documentElement.style.setProperty(
|
|
26
|
+
`--color-raw-${name}`,
|
|
27
|
+
color.css().replace(/^rgba?\((.*)\)/, '$1')
|
|
28
|
+
)
|
|
29
|
+
}
|
|
44
30
|
}
|
|
45
31
|
|
|
46
32
|
const black = chroma('black')
|
|
47
33
|
const white = chroma('white')
|
|
48
|
-
applyColor('primary', chroma(primaryColor))
|
|
34
|
+
applyColor('primary', chroma(primaryColor), true)
|
|
49
35
|
applyColor(
|
|
50
36
|
'primary-lighter',
|
|
51
37
|
chroma.scale([primaryColor, white]).mode('lab')(0.3)
|
|
@@ -70,7 +56,7 @@ export class ThemeService {
|
|
|
70
56
|
'primary-black',
|
|
71
57
|
chroma.scale([primaryColor, black]).mode('lab')(0.85)
|
|
72
58
|
)
|
|
73
|
-
applyColor('secondary', chroma(secondaryColor))
|
|
59
|
+
applyColor('secondary', chroma(secondaryColor), true)
|
|
74
60
|
applyColor(
|
|
75
61
|
'secondary-lighter',
|
|
76
62
|
chroma.scale([secondaryColor, white]).mode('lab')(0.3)
|
package/tailwind.base.config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
1
2
|
module.exports = {
|
|
2
3
|
theme: {
|
|
3
4
|
extend: {
|
|
@@ -8,14 +9,14 @@ module.exports = {
|
|
|
8
9
|
'primary-white': 'var(--color-primary-white)',
|
|
9
10
|
'primary-lightest': 'var(--color-primary-lightest)',
|
|
10
11
|
'primary-lighter': 'var(--color-primary-lighter)',
|
|
11
|
-
primary: 'var(--color-primary)',
|
|
12
|
+
primary: 'rgb(var(--color-raw-primary) / <alpha-value>)', // supports opacity
|
|
12
13
|
'primary-darker': 'var(--color-primary-darker)',
|
|
13
14
|
'primary-darkest': 'var(--color-primary-darkest)',
|
|
14
15
|
'primary-black': 'var(--color-primary-black)',
|
|
15
16
|
'secondary-white': 'var(--color-secondary-white)',
|
|
16
17
|
'secondary-lightest': 'var(--color-secondary-lightest)',
|
|
17
18
|
'secondary-lighter': 'var(--color-secondary-lighter)',
|
|
18
|
-
secondary: 'var(--color-secondary)',
|
|
19
|
+
secondary: 'rgb(var(--color-raw-secondary) / <alpha-value>)', // supports opacity
|
|
19
20
|
'secondary-darker': 'var(--color-secondary-darker)',
|
|
20
21
|
'secondary-darkest': 'var(--color-secondary-darkest)',
|
|
21
22
|
'secondary-black': 'var(--color-secondary-black)',
|
package/translations/de.json
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"dashboard.records.username": "Benutzername",
|
|
39
39
|
"dashboard.records.users": "{count, plural, =1{Benutzer} other{Benutzer}}",
|
|
40
40
|
"datahub.header.datasets": "Katalog",
|
|
41
|
+
"datahub.header.edit.url.open": "",
|
|
41
42
|
"datahub.header.lastRecords": "Die neuesten",
|
|
42
43
|
"datahub.header.myfavorites": "Meine Favoriten",
|
|
43
44
|
"datahub.header.news": "Startseite",
|
|
@@ -382,11 +383,13 @@
|
|
|
382
383
|
"map.ogc.urlInput.hint": "Die URL des OGC API-Dienstes eingeben",
|
|
383
384
|
"map.select.layer": "Datenquelle",
|
|
384
385
|
"map.select.style": "Style",
|
|
386
|
+
"map.style.default": "Standard",
|
|
385
387
|
"map.wfs.urlInput.hint": "Die WFS URL eingeben",
|
|
386
388
|
"map.wms.urlInput.hint": "Die WMS URL eingeben",
|
|
387
389
|
"multiselect.filter.placeholder": "Suche",
|
|
388
390
|
"nav.back": "Zurück",
|
|
389
391
|
"navbar.mobile.menuTitle": "Schnellzugriff",
|
|
392
|
+
"ogc.geojson.notsupported": "Dieser OGC API-Dienst unterstützt das GeoJSON-Format nicht.",
|
|
390
393
|
"ogc.unreachable.unknown": "Der Dienst konnte nicht erreicht werden",
|
|
391
394
|
"organisation.filter.placeholder": "Ergebnisse filtern",
|
|
392
395
|
"organisation.sort.sortBy": "Sortieren nach:",
|
|
@@ -472,7 +475,7 @@
|
|
|
472
475
|
"record.metadata.download": "Herunterladen",
|
|
473
476
|
"record.metadata.feature.catalog": "Attributkatalog",
|
|
474
477
|
"record.metadata.formats": "Formate",
|
|
475
|
-
"record.metadata.isGeographical": "
|
|
478
|
+
"record.metadata.isGeographical": "geographischer Datensatz",
|
|
476
479
|
"record.metadata.keywords": "Stichworte",
|
|
477
480
|
"record.metadata.languages": "Sprachen",
|
|
478
481
|
"record.metadata.link.postgis.table": "Tabelle:",
|
|
@@ -603,6 +606,7 @@
|
|
|
603
606
|
"search.filters.producerOrg": "Herausgeber",
|
|
604
607
|
"search.filters.publicationYear": "Veröffentlichungsjahr",
|
|
605
608
|
"search.filters.publisherOrg": "Vertreiber",
|
|
609
|
+
"search.filters.recordKind": "",
|
|
606
610
|
"search.filters.recordKind.all": "Alle",
|
|
607
611
|
"search.filters.recordKind.dataset": "Datensätze",
|
|
608
612
|
"search.filters.recordKind.reuse": "Wiederverwendungen",
|
|
@@ -641,7 +645,6 @@
|
|
|
641
645
|
"service.metadata.spatialExtent": "Räumliche Ausdehnung",
|
|
642
646
|
"share.tab.permalink": "Teilen",
|
|
643
647
|
"share.tab.webComponent": "Integrieren",
|
|
644
|
-
"stac.filter.reset": "Filter zurücksetzen",
|
|
645
648
|
"stac.filter.enable": "",
|
|
646
649
|
"stac.filter.reset": "",
|
|
647
650
|
"stac.results.noResults": "Ihre Suchfilter lieferten keine Ergebnisse",
|
|
@@ -662,7 +665,7 @@
|
|
|
662
665
|
"wfs.feature.limit": "Zu viele Features, um den WFS-Layer anzuzeigen!",
|
|
663
666
|
"wfs.featuretype.notfound": "Kein passender Feature-Typ wurde im Dienst gefunden",
|
|
664
667
|
"wfs.geojsongml.notsupported": "Dieser Dienst unterstützt das GeoJSON- oder GML-Format nicht",
|
|
665
|
-
"wfs.unreachable.cors": "Der Dienst
|
|
668
|
+
"wfs.unreachable.cors": "Der Remote-Dienst ist nicht für den Datenempfang (CORS) konfiguriert",
|
|
666
669
|
"wfs.unreachable.http": "Der Dienst hat einen HTTP-Fehler zurückgegeben",
|
|
667
670
|
"wfs.unreachable.unknown": "Der Dienst konnte nicht erreicht werden"
|
|
668
671
|
}
|