geonetwork-ui 2.6.0-dev.01d2b5fc0 → 2.6.0-dev.4fa0a0afc
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/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +18 -11
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +3 -3
- package/esm2022/libs/feature/dataviz/src/lib/geo-table-view/geo-table-view.component.mjs +2 -2
- package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +2 -1
- package/esm2022/libs/feature/dataviz/src/lib/table-view/table-view.component.mjs +3 -3
- package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-map-container/form-field-map-container.component.mjs +1 -1
- package/esm2022/libs/feature/map/src/lib/map-state-container/map-state-container.component.mjs +2 -2
- package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +2 -4
- package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +40 -14
- package/esm2022/libs/ui/elements/src/lib/api-card/api-card.component.mjs +27 -6
- package/esm2022/libs/ui/elements/src/lib/download-item/download-item.component.mjs +22 -6
- package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/link-card/link-card.component.mjs +29 -7
- package/esm2022/libs/ui/elements/src/lib/record-api-form/record-api-form.component.mjs +3 -2
- package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +3 -3
- package/esm2022/libs/ui/map/src/lib/components/map-container/map-container.component.mjs +14 -3
- package/esm2022/libs/ui/map/src/lib/components/map-legend/map-legend.component.mjs +5 -1
- package/esm2022/libs/util/data-fetcher/src/lib/data-fetcher.mjs +6 -2
- package/esm2022/libs/util/data-fetcher/src/lib/model.mjs +4 -1
- package/esm2022/libs/util/data-fetcher/src/lib/readers/wfs.mjs +30 -2
- package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +21 -19
- package/esm2022/translations/de.json +1 -0
- package/esm2022/translations/en.json +2 -1
- package/esm2022/translations/es.json +1 -0
- package/esm2022/translations/fr.json +1 -0
- package/esm2022/translations/it.json +1 -0
- package/esm2022/translations/nl.json +1 -0
- package/esm2022/translations/pt.json +1 -0
- package/fesm2022/geonetwork-ui.mjs +221 -75
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +1 -0
- package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +18 -2
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
- package/libs/feature/dataviz/src/lib/table-view/table-view.component.d.ts +1 -1
- package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
- package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +7 -2
- package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/api-card/api-card.component.d.ts +9 -1
- package/libs/ui/elements/src/lib/api-card/api-card.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/download-item/download-item.component.d.ts +8 -1
- package/libs/ui/elements/src/lib/download-item/download-item.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/link-card/link-card.component.d.ts +10 -2
- package/libs/ui/elements/src/lib/link-card/link-card.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts.map +1 -1
- package/libs/ui/map/src/lib/components/map-container/map-container.component.d.ts +4 -2
- package/libs/ui/map/src/lib/components/map-container/map-container.component.d.ts.map +1 -1
- package/libs/ui/map/src/lib/components/map-legend/map-legend.component.d.ts.map +1 -1
- package/libs/util/data-fetcher/src/lib/data-fetcher.d.ts.map +1 -1
- package/libs/util/data-fetcher/src/lib/model.d.ts +3 -2
- package/libs/util/data-fetcher/src/lib/model.d.ts.map +1 -1
- package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts +1 -0
- package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts.map +1 -1
- package/libs/util/shared/src/lib/links/link-utils.d.ts +16 -16
- package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +20 -12
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +17 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +18 -2
- package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.html +1 -0
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +1 -0
- package/src/libs/feature/dataviz/src/lib/table-view/table-view.component.html +10 -8
- package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +1 -3
- package/src/libs/feature/record/src/lib/map-view/map-view.component.html +1 -0
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +36 -7
- package/src/libs/ui/elements/src/lib/api-card/api-card.component.html +64 -38
- package/src/libs/ui/elements/src/lib/api-card/api-card.component.ts +26 -2
- package/src/libs/ui/elements/src/lib/download-item/download-item.component.html +17 -17
- package/src/libs/ui/elements/src/lib/download-item/download-item.component.ts +20 -2
- package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +1 -0
- package/src/libs/ui/elements/src/lib/link-card/link-card.component.html +27 -29
- package/src/libs/ui/elements/src/lib/link-card/link-card.component.ts +33 -3
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +2 -1
- package/src/libs/ui/layout/src/lib/carousel/carousel.component.css +0 -4
- package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +14 -0
- package/src/libs/ui/map/src/lib/components/map-legend/map-legend.component.ts +3 -0
- package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +3 -1
- package/src/libs/util/data-fetcher/src/lib/model.ts +11 -1
- package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +29 -3
- package/src/libs/util/shared/src/lib/links/link-utils.ts +20 -18
- package/tailwind.base.css +29 -1
- package/translations/de.json +1 -0
- package/translations/en.json +2 -1
- package/translations/es.json +1 -0
- package/translations/fr.json +1 -0
- package/translations/it.json +1 -0
- package/translations/nl.json +1 -0
- package/translations/pt.json +1 -0
- package/translations/sk.json +1 -0
|
@@ -187,8 +187,24 @@ As such, **it is not very interesting at all.**`,
|
|
|
187
187
|
],
|
|
188
188
|
code: '',
|
|
189
189
|
aliases: '',
|
|
190
|
-
typeName: "Catalogue d'attributs",
|
|
191
|
-
definition: '',
|
|
190
|
+
typeName: "Catalogue d'attributs N°1",
|
|
191
|
+
definition: 'Définition du catalogue d attributs N°1',
|
|
192
|
+
isAbstract: 'false',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
attributeTable: [
|
|
196
|
+
{
|
|
197
|
+
code: 'UniqueObject',
|
|
198
|
+
name: 'unique object ',
|
|
199
|
+
link: '',
|
|
200
|
+
definition: 'this is the only object of this catalog',
|
|
201
|
+
type: 'String (50)',
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
code: '',
|
|
205
|
+
aliases: '',
|
|
206
|
+
typeName: "Catalogue d'attributs N°2",
|
|
207
|
+
definition: 'Définition du catalogue d attributs N°2',
|
|
192
208
|
isAbstract: 'false',
|
|
193
209
|
},
|
|
194
210
|
],
|
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
class="absolute inset-0"
|
|
12
12
|
[message]="'table.loading.data' | translate"
|
|
13
13
|
></gn-ui-loading-mask>
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
<ng-content *ngIf="error">
|
|
15
|
+
<div class="border border-gray-300 rounded-lg bg-white h-full"></div>
|
|
16
|
+
<gn-ui-popup-alert
|
|
17
|
+
type="warning"
|
|
18
|
+
icon="matErrorOutlineOutline"
|
|
19
|
+
class="absolute m-2 inset-0"
|
|
20
|
+
>
|
|
21
|
+
<span translate>{{ error }}</span>
|
|
22
|
+
</gn-ui-popup-alert>
|
|
23
|
+
</ng-content>
|
|
22
24
|
</div>
|
|
23
25
|
</div>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core'
|
|
2
2
|
import { extend, Extent } from 'ol/extent'
|
|
3
3
|
import GeoJSON from 'ol/format/GeoJSON'
|
|
4
|
-
import { transformExtent } from 'ol/proj'
|
|
5
4
|
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
5
|
|
|
7
6
|
const GEOJSON = new GeoJSON()
|
|
@@ -15,7 +14,7 @@ export class MapUtilsService {
|
|
|
15
14
|
return null
|
|
16
15
|
}
|
|
17
16
|
// extend all the spatial extents into an including bbox
|
|
18
|
-
|
|
17
|
+
return record.spatialExtents.reduce(
|
|
19
18
|
(prev, curr) => {
|
|
20
19
|
if ('bbox' in curr) return extend(prev, curr.bbox)
|
|
21
20
|
else if ('geometry' in curr) {
|
|
@@ -26,6 +25,5 @@ export class MapUtilsService {
|
|
|
26
25
|
},
|
|
27
26
|
[Infinity, Infinity, -Infinity, -Infinity]
|
|
28
27
|
)
|
|
29
|
-
return transformExtent(totalExtent, 'EPSG:4326', 'EPSG:3857')
|
|
30
28
|
}
|
|
31
29
|
}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
#mapContainer
|
|
32
32
|
[context]="mapContext$ | async"
|
|
33
33
|
(featuresClick)="onMapFeatureSelect($event)"
|
|
34
|
+
(sourceLoadError)="onSourceLoadError($event)"
|
|
34
35
|
></gn-ui-map-container>
|
|
35
36
|
<div
|
|
36
37
|
class="top-[1em] right-[1em] p-3 bg-white absolute overflow-y-auto overflow-x-hidden max-h-72 w-56"
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
createViewFromLayer,
|
|
35
35
|
MapContext,
|
|
36
36
|
MapContextLayer,
|
|
37
|
+
SourceLoadErrorEvent,
|
|
37
38
|
} from '@geospatial-sdk/core'
|
|
38
39
|
import {
|
|
39
40
|
FeatureDetailComponent,
|
|
@@ -49,13 +50,14 @@ import {
|
|
|
49
50
|
ButtonComponent,
|
|
50
51
|
DropdownSelectorComponent,
|
|
51
52
|
} from '../../../../../../libs/ui/inputs/src'
|
|
52
|
-
import { TranslateModule } from '@ngx-translate/core'
|
|
53
|
+
import { TranslateModule, TranslateService } from '@ngx-translate/core'
|
|
53
54
|
import { ExternalViewerButtonComponent } from '../external-viewer-button/external-viewer-button.component'
|
|
54
55
|
import {
|
|
55
56
|
LoadingMaskComponent,
|
|
56
57
|
PopupAlertComponent,
|
|
57
58
|
} from '../../../../../../libs/ui/widgets/src'
|
|
58
59
|
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
|
|
60
|
+
import { FetchError } from '../../../../../../libs/util/data-fetcher/src'
|
|
59
61
|
|
|
60
62
|
marker('map.dropdown.placeholder')
|
|
61
63
|
marker('wfs.feature.limit')
|
|
@@ -100,9 +102,6 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
100
102
|
|
|
101
103
|
onLegendStatusChange(status: boolean) {
|
|
102
104
|
this.legendExists = status
|
|
103
|
-
if (!status) {
|
|
104
|
-
this.showLegend = false
|
|
105
|
-
}
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
compatibleMapLinks$ = combineLatest([
|
|
@@ -149,8 +148,7 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
149
148
|
return this.getLayerFromLink(link).pipe(
|
|
150
149
|
map((layer) => [layer]),
|
|
151
150
|
catchError((e) => {
|
|
152
|
-
this.
|
|
153
|
-
console.warn(e.stack || e.message)
|
|
151
|
+
this.handleError(e)
|
|
154
152
|
return of([])
|
|
155
153
|
}),
|
|
156
154
|
finalize(() => (this.loading = false))
|
|
@@ -192,7 +190,8 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
192
190
|
private mdViewFacade: MdViewFacade,
|
|
193
191
|
private mapUtils: MapUtilsService,
|
|
194
192
|
private dataService: DataService,
|
|
195
|
-
private changeRef: ChangeDetectorRef
|
|
193
|
+
private changeRef: ChangeDetectorRef,
|
|
194
|
+
private translateService: TranslateService
|
|
196
195
|
) {}
|
|
197
196
|
|
|
198
197
|
async ngAfterViewInit() {
|
|
@@ -210,6 +209,16 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
210
209
|
this.changeRef.detectChanges()
|
|
211
210
|
}
|
|
212
211
|
|
|
212
|
+
onSourceLoadError(error: SourceLoadErrorEvent) {
|
|
213
|
+
if (error.httpStatus === 403 || error.httpStatus === 401) {
|
|
214
|
+
this.error = this.translateService.instant(`dataset.error.forbidden`)
|
|
215
|
+
} else {
|
|
216
|
+
this.error = this.translateService.instant(`dataset.error.http`, {
|
|
217
|
+
info: error.httpStatus,
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
213
222
|
resetSelection(): void {
|
|
214
223
|
if (this.selection) {
|
|
215
224
|
// FIXME: restore styling of selected feature
|
|
@@ -255,4 +264,24 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
255
264
|
selectLinkToDisplay(link: number) {
|
|
256
265
|
this.selectedLinkIndex$.next(link)
|
|
257
266
|
}
|
|
267
|
+
|
|
268
|
+
handleError(error: FetchError | Error | string) {
|
|
269
|
+
if (error instanceof FetchError) {
|
|
270
|
+
this.error = this.translateService.instant(
|
|
271
|
+
`dataset.error.${error.type}`,
|
|
272
|
+
{
|
|
273
|
+
info: error.info,
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
console.warn(error.message)
|
|
277
|
+
} else if (error instanceof Error) {
|
|
278
|
+
this.error = this.translateService.instant(error.message)
|
|
279
|
+
console.warn(error.stack || error)
|
|
280
|
+
} else {
|
|
281
|
+
this.error = this.translateService.instant(error)
|
|
282
|
+
console.warn(error)
|
|
283
|
+
}
|
|
284
|
+
this.loading = false
|
|
285
|
+
this.changeRef.detectChanges()
|
|
286
|
+
}
|
|
258
287
|
}
|
|
@@ -1,13 +1,66 @@
|
|
|
1
1
|
<div
|
|
2
|
-
class="group flex
|
|
2
|
+
class="group flex justify-between rounded filter overflow-hidden"
|
|
3
|
+
[ngClass]="cardClass"
|
|
3
4
|
>
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
<ng-container *ngIf="size !== 'S'">
|
|
6
|
+
<div>
|
|
7
|
+
<ng-container *ngTemplateOutlet="content"></ng-container>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="flex items-center">
|
|
10
|
+
<ng-container *ngTemplateOutlet="buttons"></ng-container>
|
|
11
|
+
</div>
|
|
12
|
+
</ng-container>
|
|
13
|
+
<ng-container *ngIf="size === 'S'">
|
|
14
|
+
<ng-container *ngTemplateOutlet="content"></ng-container>
|
|
15
|
+
</ng-container>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<ng-template #buttons>
|
|
19
|
+
<div class="flex flex-row gap-2">
|
|
20
|
+
<gn-ui-copy-text-button
|
|
21
|
+
[text]="link.url"
|
|
22
|
+
[tooltipText]="'tooltip.url.copy' | translate"
|
|
23
|
+
[displayText]="false"
|
|
24
|
+
class="border border-gray-300 rounded-lg pt-1 px-2 h-[34px]"
|
|
25
|
+
></gn-ui-copy-text-button>
|
|
26
|
+
<button
|
|
27
|
+
*ngIf="displayApiFormButton"
|
|
28
|
+
type="button"
|
|
29
|
+
class="gn-ui-card-icon"
|
|
30
|
+
[ngClass]="{
|
|
31
|
+
'py-2 px-4 rounded-r-md bg-gray-400 hover:bg-gray-600 focus:bg-gray-800 text-white':
|
|
32
|
+
displayText,
|
|
33
|
+
}"
|
|
34
|
+
[matTooltip]="
|
|
35
|
+
!currentlyActive
|
|
36
|
+
? ('record.metadata.api.form.openForm' | translate)
|
|
37
|
+
: ('record.metadata.api.form.closeForm' | translate)
|
|
38
|
+
"
|
|
39
|
+
matTooltipPosition="above"
|
|
40
|
+
(click)="openRecordApiFormPanel()"
|
|
41
|
+
>
|
|
42
|
+
<ng-icon
|
|
43
|
+
class="pointer-events-none align-middle card-icon"
|
|
44
|
+
name="iconoirSettings"
|
|
45
|
+
[ngClass]="{
|
|
46
|
+
'text-secondary opacity-100': currentlyActive,
|
|
47
|
+
}"
|
|
48
|
+
></ng-icon>
|
|
49
|
+
</button>
|
|
8
50
|
</div>
|
|
9
|
-
|
|
10
|
-
|
|
51
|
+
</ng-template>
|
|
52
|
+
|
|
53
|
+
<ng-template #content>
|
|
54
|
+
<div>
|
|
55
|
+
<div class="gn-ui-card-title">
|
|
56
|
+
{{ link.description || link.name }}
|
|
57
|
+
</div>
|
|
58
|
+
<div class="gn-ui-card-detail">
|
|
59
|
+
{{ link.name }}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="flex flex-row justify-between">
|
|
63
|
+
<div class="flex flex-row gap-2.5 items-center pt-1">
|
|
11
64
|
<span
|
|
12
65
|
*ngIf="link.accessServiceProtocol !== 'GPFDL'"
|
|
13
66
|
class="bg-primary-opacity-50 uppercase inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded text-primary-lightest group-hover:bg-primary transition-colors"
|
|
@@ -26,36 +79,9 @@
|
|
|
26
79
|
>
|
|
27
80
|
record.metadata.api.gpfdl</span
|
|
28
81
|
>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[tooltipText]="'tooltip.url.copy' | translate"
|
|
33
|
-
[displayText]="false"
|
|
34
|
-
></gn-ui-copy-text-button>
|
|
35
|
-
<button
|
|
36
|
-
*ngIf="displayApiFormButton"
|
|
37
|
-
type="button"
|
|
38
|
-
[ngClass]="{
|
|
39
|
-
'py-2 px-4 rounded-r-md bg-gray-400 hover:bg-gray-600 focus:bg-gray-800 text-white':
|
|
40
|
-
displayText,
|
|
41
|
-
}"
|
|
42
|
-
[matTooltip]="
|
|
43
|
-
!currentlyActive
|
|
44
|
-
? ('record.metadata.api.form.openForm' | translate)
|
|
45
|
-
: ('record.metadata.api.form.closeForm' | translate)
|
|
46
|
-
"
|
|
47
|
-
matTooltipPosition="above"
|
|
48
|
-
(click)="openRecordApiFormPanel()"
|
|
49
|
-
>
|
|
50
|
-
<ng-icon
|
|
51
|
-
class="pointer-events-none align-middle card-icon"
|
|
52
|
-
name="matMoreHoriz"
|
|
53
|
-
[ngClass]="{
|
|
54
|
-
'text-secondary opacity-100': currentlyActive,
|
|
55
|
-
}"
|
|
56
|
-
></ng-icon>
|
|
57
|
-
</button>
|
|
58
|
-
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<div *ngIf="size === 'S'">
|
|
84
|
+
<ng-container *ngTemplateOutlet="buttons"></ng-container>
|
|
59
85
|
</div>
|
|
60
86
|
</div>
|
|
61
|
-
</
|
|
87
|
+
</ng-template>
|
|
@@ -14,7 +14,9 @@ import { CopyTextButtonComponent } from '../../../../../../libs/ui/inputs/src'
|
|
|
14
14
|
import { TranslateModule } from '@ngx-translate/core'
|
|
15
15
|
import { MatTooltipModule } from '@angular/material/tooltip'
|
|
16
16
|
import { NgIcon, provideIcons } from '@ng-icons/core'
|
|
17
|
-
import {
|
|
17
|
+
import { iconoirSettings } from '@ng-icons/iconoir'
|
|
18
|
+
|
|
19
|
+
type CardSize = 'L' | 'M' | 'S' | 'XS'
|
|
18
20
|
|
|
19
21
|
@Component({
|
|
20
22
|
selector: 'gn-ui-api-card',
|
|
@@ -31,18 +33,40 @@ import { matMoreHoriz } from '@ng-icons/material-icons/baseline'
|
|
|
31
33
|
],
|
|
32
34
|
viewProviders: [
|
|
33
35
|
provideIcons({
|
|
34
|
-
|
|
36
|
+
iconoirSettings,
|
|
35
37
|
}),
|
|
36
38
|
],
|
|
37
39
|
})
|
|
38
40
|
export class ApiCardComponent implements OnInit, OnChanges {
|
|
41
|
+
private _size: 'L' | 'M' | 'S' | 'XS'
|
|
39
42
|
@Input() link: DatasetServiceDistribution
|
|
40
43
|
@Input() currentLink: DatasetServiceDistribution
|
|
44
|
+
private readonly sizeClassMap: Record<CardSize, string> = {
|
|
45
|
+
L: 'gn-ui-card-l py-2 px-5 flex-row',
|
|
46
|
+
M: 'gn-ui-card-m py-2 px-5 flex-row',
|
|
47
|
+
S: 'gn-ui-card-s p-4 flex-col',
|
|
48
|
+
XS: 'gn-ui-card-xs py-2 px-5 flex-row',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Input() set size(value: CardSize) {
|
|
52
|
+
this._size = value
|
|
53
|
+
this.cardClass = this.sizeClassMap[value]
|
|
54
|
+
}
|
|
55
|
+
get size(): 'L' | 'M' | 'S' | 'XS' {
|
|
56
|
+
return this._size
|
|
57
|
+
}
|
|
58
|
+
cardClass = ''
|
|
41
59
|
displayApiFormButton: boolean
|
|
42
60
|
currentlyActive = false
|
|
43
61
|
@Output() openRecordApiForm: EventEmitter<DatasetServiceDistribution> =
|
|
44
62
|
new EventEmitter<DatasetServiceDistribution>()
|
|
45
63
|
|
|
64
|
+
get generatedText() {
|
|
65
|
+
return this.link.accessServiceProtocol === 'wfs'
|
|
66
|
+
? 'datahub.search.filter.generatedByWfs'
|
|
67
|
+
: 'datahub.search.filter.generatedByAPI'
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
ngOnInit() {
|
|
47
71
|
this.displayApiFormButton =
|
|
48
72
|
this.link.accessServiceProtocol === 'ogcFeatures' ||
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
<a
|
|
2
2
|
href="{{ link.url }}"
|
|
3
3
|
target="_blank"
|
|
4
|
-
class="group flex justify-between card-shadow
|
|
4
|
+
class="group flex flex-row justify-between card-shadow cursor-pointer rounded overflow-hidden"
|
|
5
5
|
rel="noopener"
|
|
6
|
+
[ngClass]="cardClass"
|
|
6
7
|
>
|
|
7
|
-
<div class="
|
|
8
|
-
<div
|
|
9
|
-
class="text-21 text-black truncate font-title w-11/12"
|
|
10
|
-
[title]="link.description || link.name"
|
|
11
|
-
>
|
|
8
|
+
<div class="flex flex-col justify-between">
|
|
9
|
+
<div class="gn-ui-card-title" [title]="link.description || link.name">
|
|
12
10
|
{{ link.description || link.name }}
|
|
13
11
|
</div>
|
|
14
|
-
<div class="
|
|
12
|
+
<div class="gn-ui-card-detail">
|
|
13
|
+
{{ link.name }}
|
|
14
|
+
</div>
|
|
15
|
+
<div class="flex flex-row gap-2 items-center pt-1">
|
|
15
16
|
<span
|
|
16
17
|
class="inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded transition-opacity opacity-70 group-hover:opacity-100"
|
|
17
18
|
[style.background-color]="color"
|
|
18
19
|
data-cy="download-format"
|
|
19
20
|
>{{ format || ('downloads.format.unknown' | translate) }}</span
|
|
20
21
|
>
|
|
21
|
-
<span
|
|
22
|
-
class="pl-2 inline-flex items-center text-gray-800 text-sm"
|
|
23
|
-
*ngIf="isFromApi"
|
|
24
|
-
translate=""
|
|
22
|
+
<span class="text-gray-800 text-xs" *ngIf="isFromApi" translate=""
|
|
25
23
|
>datahub.search.filter.generatedByAPI</span
|
|
26
24
|
>
|
|
27
25
|
</div>
|
|
28
26
|
</div>
|
|
29
|
-
<div class="
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
<div class="flex" [ngClass]="size === 'S' ? 'items-end' : 'items-center'">
|
|
28
|
+
<div class="gn-ui-card-icon">
|
|
29
|
+
<ng-icon
|
|
30
|
+
class="inline-block card-icon align-middle"
|
|
31
|
+
name="iconoirDownload"
|
|
32
|
+
>
|
|
33
|
+
</ng-icon>
|
|
34
|
+
</div>
|
|
35
35
|
</div>
|
|
36
36
|
</a>
|
|
@@ -9,7 +9,9 @@ import { DatasetOnlineResource } from '../../../../../../libs/common/domain/src/
|
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core'
|
|
10
10
|
import { CommonModule } from '@angular/common'
|
|
11
11
|
import { NgIcon, provideIcons } from '@ng-icons/core'
|
|
12
|
-
import {
|
|
12
|
+
import { iconoirDownload } from '@ng-icons/iconoir'
|
|
13
|
+
|
|
14
|
+
type CardSize = 'L' | 'M' | 'S' | 'XS'
|
|
13
15
|
|
|
14
16
|
@Component({
|
|
15
17
|
selector: 'gn-ui-download-item',
|
|
@@ -20,15 +22,31 @@ import { matCloudDownloadOutline } from '@ng-icons/material-icons/outline'
|
|
|
20
22
|
standalone: true,
|
|
21
23
|
viewProviders: [
|
|
22
24
|
provideIcons({
|
|
23
|
-
|
|
25
|
+
iconoirDownload,
|
|
24
26
|
}),
|
|
25
27
|
],
|
|
26
28
|
})
|
|
27
29
|
export class DownloadItemComponent {
|
|
30
|
+
private _size: 'L' | 'M' | 'S' | 'XS'
|
|
28
31
|
@Input() link: DatasetOnlineResource
|
|
29
32
|
@Input() color: string
|
|
30
33
|
@Input() format: string
|
|
31
34
|
@Input() isFromApi: boolean
|
|
35
|
+
private readonly sizeClassMap: Record<CardSize, string> = {
|
|
36
|
+
L: 'gn-ui-card-l py-2 px-5',
|
|
37
|
+
M: 'gn-ui-card-m py-2 px-5',
|
|
38
|
+
S: 'gn-ui-card-s p-4',
|
|
39
|
+
XS: 'gn-ui-card-xs py-2 px-5',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Input() set size(value: CardSize) {
|
|
43
|
+
this._size = value
|
|
44
|
+
this.cardClass = this.sizeClassMap[value]
|
|
45
|
+
}
|
|
46
|
+
get size(): 'L' | 'M' | 'S' | 'XS' {
|
|
47
|
+
return this._size
|
|
48
|
+
}
|
|
49
|
+
cardClass = ''
|
|
32
50
|
@Output() exportUrl = new EventEmitter<string>()
|
|
33
51
|
|
|
34
52
|
openUrl() {
|
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
<a
|
|
2
2
|
[href]="link.url"
|
|
3
3
|
target="_blank"
|
|
4
|
-
class="flex flex-
|
|
5
|
-
[ngClass]="
|
|
4
|
+
class="group flex flex-row justify-between card-shadow cursor-pointer rounded overflow-hidden"
|
|
5
|
+
[ngClass]="cardClass"
|
|
6
6
|
[title]="title"
|
|
7
7
|
>
|
|
8
|
-
<
|
|
9
|
-
<div class="
|
|
10
|
-
|
|
11
|
-
class="font-title font-medium text-21 text-black break-words mb-1 line-clamp-2"
|
|
12
|
-
>
|
|
13
|
-
{{ link.name }}
|
|
14
|
-
</p>
|
|
15
|
-
<p class="font-medium text-sm break-words">
|
|
16
|
-
{{ link.description }}
|
|
17
|
-
</p>
|
|
18
|
-
<p
|
|
19
|
-
*ngIf="!link.name && !link.description"
|
|
20
|
-
class="font-medium text-sm break-words truncate"
|
|
21
|
-
>
|
|
22
|
-
{{ link.url }}
|
|
23
|
-
</p>
|
|
8
|
+
<div class="flex flex-col justify-between">
|
|
9
|
+
<div class="gn-ui-card-title">
|
|
10
|
+
{{ link.description || link.name }}
|
|
24
11
|
</div>
|
|
25
|
-
<div>
|
|
26
|
-
|
|
12
|
+
<div class="gn-ui-card-detail">
|
|
13
|
+
{{ link.name }}
|
|
27
14
|
</div>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
<p *ngIf="!link.name && !link.description" class="gn-ui-card-title">
|
|
16
|
+
{{ link.url }}
|
|
17
|
+
</p>
|
|
18
|
+
<div class="pt-1">
|
|
19
|
+
<span
|
|
20
|
+
class="inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded transition-opacity opacity-70 group-hover:opacity-100"
|
|
21
|
+
[style.background-color]="getLinkColor(link)"
|
|
22
|
+
data-cy="download-format"
|
|
23
|
+
>{{
|
|
24
|
+
getLinkFormat(link) || ('downloads.format.unknown' | translate)
|
|
25
|
+
}}</span
|
|
33
26
|
>
|
|
34
|
-
{{ link.name || link.description }}
|
|
35
|
-
</p>
|
|
36
|
-
<ng-icon class="card-icon flex-shrink-0" name="matOpenInNew"></ng-icon>
|
|
37
27
|
</div>
|
|
38
|
-
</
|
|
28
|
+
</div>
|
|
29
|
+
<div class="flex" [ngClass]="size === 'S' ? 'items-end' : 'items-center'">
|
|
30
|
+
<div class="gn-ui-card-icon">
|
|
31
|
+
<ng-icon
|
|
32
|
+
class="inline-block card-icon align-middle"
|
|
33
|
+
name="matOpenInNew"
|
|
34
|
+
></ng-icon>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
39
37
|
</a>
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DatasetDownloadDistribution,
|
|
4
|
+
DatasetOnlineResource,
|
|
5
|
+
DatasetServiceDistribution,
|
|
6
|
+
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
3
7
|
import { CommonModule } from '@angular/common'
|
|
4
8
|
import {
|
|
5
9
|
NgIconComponent,
|
|
@@ -7,14 +11,17 @@ import {
|
|
|
7
11
|
provideNgIconsConfig,
|
|
8
12
|
} from '@ng-icons/core'
|
|
9
13
|
import { matOpenInNew } from '@ng-icons/material-icons/baseline'
|
|
14
|
+
import { getBadgeColor, getFileFormat } from '../../../../../../libs/util/shared/src'
|
|
15
|
+
import { TranslateModule } from '@ngx-translate/core'
|
|
10
16
|
|
|
17
|
+
type CardSize = 'L' | 'M' | 'S' | 'XS'
|
|
11
18
|
@Component({
|
|
12
19
|
selector: 'gn-ui-link-card',
|
|
13
20
|
templateUrl: './link-card.component.html',
|
|
14
21
|
styleUrls: ['./link-card.component.css'],
|
|
15
22
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16
23
|
standalone: true,
|
|
17
|
-
imports: [CommonModule, NgIconComponent],
|
|
24
|
+
imports: [CommonModule, NgIconComponent, TranslateModule],
|
|
18
25
|
providers: [
|
|
19
26
|
provideIcons({
|
|
20
27
|
matOpenInNew,
|
|
@@ -23,8 +30,23 @@ import { matOpenInNew } from '@ng-icons/material-icons/baseline'
|
|
|
23
30
|
],
|
|
24
31
|
})
|
|
25
32
|
export class LinkCardComponent {
|
|
33
|
+
private _size: 'L' | 'M' | 'S' | 'XS'
|
|
26
34
|
@Input() link: DatasetOnlineResource
|
|
27
|
-
|
|
35
|
+
private readonly sizeClassMap: Record<CardSize, string> = {
|
|
36
|
+
L: 'gn-ui-card-l py-2 px-5',
|
|
37
|
+
M: 'gn-ui-card-m py-2 px-5',
|
|
38
|
+
S: 'gn-ui-card-s p-4',
|
|
39
|
+
XS: 'gn-ui-card-xs py-2 px-5',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Input() set size(value: CardSize) {
|
|
43
|
+
this._size = value
|
|
44
|
+
this.cardClass = this.sizeClassMap[value]
|
|
45
|
+
}
|
|
46
|
+
get size(): 'L' | 'M' | 'S' | 'XS' {
|
|
47
|
+
return this._size
|
|
48
|
+
}
|
|
49
|
+
cardClass = ''
|
|
28
50
|
|
|
29
51
|
get title() {
|
|
30
52
|
if (this.link.name && this.link.description) {
|
|
@@ -32,4 +54,12 @@ export class LinkCardComponent {
|
|
|
32
54
|
}
|
|
33
55
|
return this.link.name || this.link.description || ''
|
|
34
56
|
}
|
|
57
|
+
|
|
58
|
+
getLinkFormat(link: any) {
|
|
59
|
+
return getFileFormat(link)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getLinkColor(link: any) {
|
|
63
|
+
return getBadgeColor(getFileFormat(link))
|
|
64
|
+
}
|
|
35
65
|
}
|
|
@@ -162,7 +162,7 @@ export class RecordApiFormComponent {
|
|
|
162
162
|
limit: limit !== '-1' ? Number(limit) : -1,
|
|
163
163
|
offset: offset !== '' ? Number(offset) : undefined,
|
|
164
164
|
outputCrs:
|
|
165
|
-
format
|
|
165
|
+
format.toLowerCase().indexOf('json') > -1 ? 'EPSG:4326' : undefined,
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
if (this.endpoint instanceof WfsEndpoint) {
|
|
@@ -170,6 +170,7 @@ export class RecordApiFormComponent {
|
|
|
170
170
|
options.maxFeatures = limit !== '-1' ? Number(limit) : undefined
|
|
171
171
|
return this.endpoint.getFeatureUrl(this.apiFeatureType, options)
|
|
172
172
|
} else {
|
|
173
|
+
delete options.outputCrs
|
|
173
174
|
return await this.endpoint.getCollectionItemsUrl(
|
|
174
175
|
this.apiFeatureType,
|
|
175
176
|
options
|
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
MapContextLayer,
|
|
29
29
|
MapContextLayerXyz,
|
|
30
30
|
MapContextView,
|
|
31
|
+
SourceLoadErrorEvent,
|
|
32
|
+
SourceLoadErrorType,
|
|
31
33
|
} from '@geospatial-sdk/core'
|
|
32
34
|
import {
|
|
33
35
|
applyContextDiffToMap,
|
|
@@ -119,6 +121,18 @@ export class MapContainerComponent implements AfterViewInit, OnChanges {
|
|
|
119
121
|
}
|
|
120
122
|
return this._mapClick
|
|
121
123
|
}
|
|
124
|
+
_sourceLoadError: EventEmitter<SourceLoadErrorEvent>
|
|
125
|
+
@Output() get sourceLoadError() {
|
|
126
|
+
if (!this._sourceLoadError) {
|
|
127
|
+
this.openlayersMap.then((olMap) => {
|
|
128
|
+
listen(olMap, SourceLoadErrorType, (error: SourceLoadErrorEvent) =>
|
|
129
|
+
this._sourceLoadError.emit(error)
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
this._sourceLoadError = new EventEmitter<SourceLoadErrorEvent>()
|
|
133
|
+
}
|
|
134
|
+
return this._sourceLoadError
|
|
135
|
+
}
|
|
122
136
|
|
|
123
137
|
@ViewChild('map') container: ElementRef
|
|
124
138
|
displayMessage$: Observable<boolean>
|