geonetwork-ui 2.4.0-dev.613f7319 → 2.4.0-dev.618ec561
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/metadata-converter/src/lib/iso19139/iso19139.converter.mjs +5 -5
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +30 -2
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.mjs +31 -0
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +23 -1
- package/esm2022/libs/api/metadata-converter/src/lib/xml-utils.mjs +6 -1
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/data-access/gn4/src/openapi/api/records.api.service.mjs +2 -6
- package/esm2022/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.mjs +138 -0
- package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.mjs +21 -0
- package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +19 -9
- package/esm2022/libs/feature/editor/src/lib/components/record-form/record-form.component.mjs +2 -1
- package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +12 -2
- package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +10 -5
- package/esm2022/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.mjs +4 -3
- package/esm2022/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.mjs +2 -2
- package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +5 -11
- package/esm2022/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +5 -2
- package/esm2022/libs/ui/inputs/src/lib/image-input/image-input.component.mjs +11 -5
- package/esm2022/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.mjs +3 -3
- package/esm2022/libs/ui/widgets/src/index.mjs +2 -1
- package/esm2022/libs/ui/widgets/src/lib/popover/popover.component.mjs +68 -0
- package/esm2022/translations/de.json +9 -17
- package/esm2022/translations/en.json +2 -10
- package/esm2022/translations/es.json +1 -9
- package/esm2022/translations/fr.json +2 -10
- package/esm2022/translations/it.json +2 -10
- package/esm2022/translations/nl.json +1 -9
- package/esm2022/translations/pt.json +1 -9
- package/fesm2022/geonetwork-ui.mjs +395 -140
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +8 -1
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.d.ts +5 -0
- package/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.d.ts.map +1 -0
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +3 -1
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/xml-utils.d.ts +1 -0
- package/libs/api/metadata-converter/src/lib/xml-utils.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +2 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts +27 -0
- package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts +11 -0
- package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +5 -1
- package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/components/record-form/record-form.component.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/fields.config.d.ts +1 -0
- package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
- package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -1
- package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts +0 -3
- package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts +1 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts +7 -6
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts +4 -2
- package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts.map +1 -1
- package/libs/ui/widgets/src/index.d.ts +1 -0
- package/libs/ui/widgets/src/index.d.ts.map +1 -1
- package/libs/ui/widgets/src/lib/popover/popover.component.d.ts +19 -0
- package/libs/ui/widgets/src/lib/popover/popover.component.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +5 -1
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +37 -12
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +5 -1
- package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +4 -2
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +72 -2
- package/src/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.ts +39 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +70 -1
- package/src/libs/api/metadata-converter/src/lib/xml-utils.ts +8 -0
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +2 -1
- package/src/libs/data-access/gn4/src/openapi/api/records.api.service.ts +1 -5
- package/src/libs/data-access/gn4/src/spec.yaml +0 -8
- package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.html +3 -1
- package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.ts +117 -21
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.css +0 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html +5 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +22 -0
- 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 +13 -1
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +1 -0
- package/src/libs/feature/editor/src/lib/fields.config.ts +12 -1
- package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +8 -4
- package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.html +4 -1
- package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.css +2 -1
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +12 -8
- package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.html +14 -20
- package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +0 -10
- package/src/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.html +1 -1
- package/src/libs/ui/elements/src/lib/ui-elements.module.ts +2 -1
- package/src/libs/ui/inputs/src/lib/image-input/image-input.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/image-input/image-input.component.ts +7 -2
- package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html +1 -1
- package/src/libs/ui/widgets/src/index.ts +1 -0
- package/src/libs/ui/widgets/src/lib/popover/popover.component.css +0 -0
- package/src/libs/ui/widgets/src/lib/popover/popover.component.html +3 -0
- package/src/libs/ui/widgets/src/lib/popover/popover.component.ts +85 -0
- package/tailwind.base.css +2 -1
- package/translations/de.json +9 -17
- package/translations/en.json +2 -10
- package/translations/es.json +1 -9
- package/translations/fr.json +2 -10
- package/translations/it.json +2 -10
- package/translations/nl.json +1 -9
- package/translations/pt.json +1 -9
- package/translations/sk.json +2 -10
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
UpdateFrequencyCode,
|
|
15
15
|
UpdateFrequencyCustom,
|
|
16
16
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
17
|
+
import { ThesaurusModel } from '../../../../../../libs/common/domain/src/lib/model/thesaurus'
|
|
17
18
|
import format from 'date-fns/format'
|
|
19
|
+
import { Geometry } from 'geojson'
|
|
18
20
|
import {
|
|
19
21
|
ChainableFunction,
|
|
20
22
|
fallback,
|
|
@@ -44,8 +46,8 @@ import {
|
|
|
44
46
|
setTextContent,
|
|
45
47
|
} from '../xml-utils'
|
|
46
48
|
import { readKind } from './read-parts'
|
|
49
|
+
import { writeGeometry } from './utils/geometry'
|
|
47
50
|
import { namePartsToFull } from './utils/individual-name'
|
|
48
|
-
import { ThesaurusModel } from '../../../../../../libs/common/domain/src/lib/model/thesaurus'
|
|
49
51
|
|
|
50
52
|
export function writeCharacterString(
|
|
51
53
|
text: string
|
|
@@ -101,6 +103,14 @@ export function writeDate(
|
|
|
101
103
|
)
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
export function writeDecimal(
|
|
107
|
+
decimal: number
|
|
108
|
+
): ChainableFunction<XmlElement, XmlElement> {
|
|
109
|
+
return tap(
|
|
110
|
+
pipe(findChildOrCreate('gco:Decimal'), setTextContent(decimal.toString()))
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
104
114
|
export function getProgressCode(status: RecordStatus): string {
|
|
105
115
|
switch (status) {
|
|
106
116
|
case 'completed':
|
|
@@ -1184,3 +1194,62 @@ export function writeTemporalExtents(
|
|
|
1184
1194
|
)
|
|
1185
1195
|
)(rootEl)
|
|
1186
1196
|
}
|
|
1197
|
+
|
|
1198
|
+
export function writeSpatialExtents(record: DatasetRecord, rootEl: XmlElement) {
|
|
1199
|
+
const appendBoundingPolygon = (geometry?: Geometry) => {
|
|
1200
|
+
if (!geometry) return null
|
|
1201
|
+
return pipe(
|
|
1202
|
+
createElement('gmd:EX_BoundingPolygon'),
|
|
1203
|
+
appendChildren(
|
|
1204
|
+
pipe(
|
|
1205
|
+
createElement('gmd:polygon'),
|
|
1206
|
+
appendChildren(() => writeGeometry(geometry))
|
|
1207
|
+
)
|
|
1208
|
+
)
|
|
1209
|
+
)
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
const appendGeographicBoundingBox = (
|
|
1213
|
+
bbox?: [number, number, number, number]
|
|
1214
|
+
) => {
|
|
1215
|
+
if (!bbox) return null
|
|
1216
|
+
return pipe(
|
|
1217
|
+
createElement('gmd:EX_GeographicBoundingBox'),
|
|
1218
|
+
appendChildren(
|
|
1219
|
+
pipe(createElement('gmd:westBoundLongitude'), writeDecimal(bbox[0])),
|
|
1220
|
+
pipe(createElement('gmd:eastBoundLongitude'), writeDecimal(bbox[2])),
|
|
1221
|
+
pipe(createElement('gmd:southBoundLatitude'), writeDecimal(bbox[1])),
|
|
1222
|
+
pipe(createElement('gmd:northBoundLatitude'), writeDecimal(bbox[3]))
|
|
1223
|
+
)
|
|
1224
|
+
)
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
const appendGeographicDescription = (description?: string) => {
|
|
1228
|
+
if (!description) return null
|
|
1229
|
+
return pipe(
|
|
1230
|
+
createElement('gmd:EX_GeographicDescription'),
|
|
1231
|
+
createChild('gmd:geographicIdentifier'),
|
|
1232
|
+
createChild('gmd:MD_Identifier'),
|
|
1233
|
+
createChild('gmd:code'),
|
|
1234
|
+
writeCharacterString(description)
|
|
1235
|
+
)
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
pipe(
|
|
1239
|
+
findOrCreateIdentification(),
|
|
1240
|
+
findNestedChildOrCreate('gmd:extent', 'gmd:EX_Extent'),
|
|
1241
|
+
removeChildrenByName('gmd:geographicElement'),
|
|
1242
|
+
appendChildren(
|
|
1243
|
+
...record.spatialExtents.map((extent) =>
|
|
1244
|
+
pipe(
|
|
1245
|
+
createElement('gmd:geographicElement'),
|
|
1246
|
+
appendChildren(
|
|
1247
|
+
appendBoundingPolygon(extent.geometry),
|
|
1248
|
+
appendGeographicBoundingBox(extent.bbox),
|
|
1249
|
+
appendGeographicDescription(extent.description)
|
|
1250
|
+
)
|
|
1251
|
+
)
|
|
1252
|
+
)
|
|
1253
|
+
)
|
|
1254
|
+
)(rootEl)
|
|
1255
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
XmlText,
|
|
7
7
|
} from '@rgrove/parse-xml'
|
|
8
8
|
import { ChainableFunction, fallback } from './function-utils'
|
|
9
|
+
|
|
9
10
|
export { XmlDocument, XmlElement } from '@rgrove/parse-xml'
|
|
10
11
|
|
|
11
12
|
export class XmlParseError extends Error {
|
|
@@ -115,6 +116,10 @@ export function allChildrenElement(element: XmlElement): Array<XmlElement> {
|
|
|
115
116
|
] as Array<XmlElement>
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
export function firstChildElement(element: XmlElement): XmlElement {
|
|
120
|
+
return allChildrenElement(element)[0] ?? null
|
|
121
|
+
}
|
|
122
|
+
|
|
118
123
|
/**
|
|
119
124
|
* Will return all matching elements nested according to the given
|
|
120
125
|
* names (similar to a path), starting form the input element;
|
|
@@ -228,6 +233,7 @@ export function xmlToString(
|
|
|
228
233
|
${padding}<${el.name}${attrs}/>
|
|
229
234
|
${parentPadding}`
|
|
230
235
|
}
|
|
236
|
+
|
|
231
237
|
return `
|
|
232
238
|
${padding}<${el.name}${attrs}>${children}</${el.name}>
|
|
233
239
|
${parentPadding}`
|
|
@@ -307,11 +313,13 @@ function getTreeRoot(element: XmlElement): XmlElement {
|
|
|
307
313
|
|
|
308
314
|
// stays on the parent element
|
|
309
315
|
// if the given elements are part of a subtree, will add the root of subtree
|
|
316
|
+
// will filter out falsy elements
|
|
310
317
|
export function appendChildren(
|
|
311
318
|
...childrenFns: Array<ChainableFunction<void, XmlElement>>
|
|
312
319
|
): ChainableFunction<XmlElement, XmlElement> {
|
|
313
320
|
return (element) => {
|
|
314
321
|
if (!element) return null
|
|
322
|
+
childrenFns = childrenFns.filter((fn) => fn)
|
|
315
323
|
element.children.push(...childrenFns.map((fn) => fn()).map(getTreeRoot))
|
|
316
324
|
element.children.forEach((el) => (el.parent = element))
|
|
317
325
|
return element
|
|
@@ -7201,11 +7201,7 @@ export class RecordsApiService {
|
|
|
7201
7201
|
}
|
|
7202
7202
|
|
|
7203
7203
|
// to determine the Content-Type header
|
|
7204
|
-
const consumes: string[] = [
|
|
7205
|
-
'application/xml',
|
|
7206
|
-
'application/json',
|
|
7207
|
-
'application/x-www-form-urlencoded',
|
|
7208
|
-
]
|
|
7204
|
+
const consumes: string[] = ['application/xml']
|
|
7209
7205
|
const httpContentTypeSelected: string | undefined =
|
|
7210
7206
|
this.configuration.selectHeaderContentType(consumes)
|
|
7211
7207
|
if (httpContentTypeSelected !== undefined) {
|
|
@@ -1832,14 +1832,6 @@ paths:
|
|
|
1832
1832
|
schema:
|
|
1833
1833
|
type: string
|
|
1834
1834
|
description: XML fragment.
|
|
1835
|
-
application/json:
|
|
1836
|
-
schema:
|
|
1837
|
-
type: string
|
|
1838
|
-
description: XML fragment.
|
|
1839
|
-
application/x-www-form-urlencoded:
|
|
1840
|
-
schema:
|
|
1841
|
-
type: string
|
|
1842
|
-
description: XML fragment.
|
|
1843
1835
|
responses:
|
|
1844
1836
|
default:
|
|
1845
1837
|
description: default response
|
package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.html
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<gn-ui-image-input
|
|
2
2
|
[maxSizeMB]="5"
|
|
3
3
|
[previewUrl]="resourceUrl"
|
|
4
|
-
[altText]="
|
|
4
|
+
[altText]="resourceAltText"
|
|
5
|
+
[formControl]="formControl"
|
|
5
6
|
(fileChange)="handleFileChange($event)"
|
|
6
7
|
(urlChange)="handleUrlChange($event)"
|
|
8
|
+
(altTextChange)="handleAltTextChange($event)"
|
|
7
9
|
(delete)="handleDelete()"
|
|
8
10
|
></gn-ui-image-input>
|
package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.ts
CHANGED
|
@@ -2,12 +2,24 @@ import {
|
|
|
2
2
|
ChangeDetectionStrategy,
|
|
3
3
|
ChangeDetectorRef,
|
|
4
4
|
Component,
|
|
5
|
+
EventEmitter,
|
|
5
6
|
Input,
|
|
7
|
+
OnChanges,
|
|
6
8
|
OnInit,
|
|
9
|
+
Output,
|
|
10
|
+
SimpleChanges,
|
|
7
11
|
} from '@angular/core'
|
|
8
12
|
import { CommonModule } from '@angular/common'
|
|
9
13
|
import { RecordsApiService } from '../../../../../../../libs/data-access/gn4/src'
|
|
10
14
|
import { UiInputsModule } from '../../../../../../../libs/ui/inputs/src'
|
|
15
|
+
import { FormControl } from '@angular/forms'
|
|
16
|
+
import { GraphicOverview } from '../../../../../../../libs/common/domain/src/lib/model/record'
|
|
17
|
+
|
|
18
|
+
const extractFileNameFromUrl = (url: string): string => {
|
|
19
|
+
const pattern = new RegExp(`attachments/([^/?#]+)(?:[/?#]|$)`, 'i')
|
|
20
|
+
const match = url.match(pattern)
|
|
21
|
+
return match ? match[1] : ''
|
|
22
|
+
}
|
|
11
23
|
|
|
12
24
|
@Component({
|
|
13
25
|
selector: 'gn-ui-overview-upload',
|
|
@@ -17,11 +29,15 @@ import { UiInputsModule } from '../../../../../../../libs/ui/inputs/src'
|
|
|
17
29
|
styleUrls: ['./overview-upload.component.css'],
|
|
18
30
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
19
31
|
})
|
|
20
|
-
export class OverviewUploadComponent implements OnInit {
|
|
32
|
+
export class OverviewUploadComponent implements OnInit, OnChanges {
|
|
21
33
|
@Input() metadataUuid: string
|
|
34
|
+
@Input() formControl!: FormControl
|
|
35
|
+
@Output() overviewChange = new EventEmitter<GraphicOverview | null>()
|
|
36
|
+
@Output() altTextChange: EventEmitter<string> = new EventEmitter()
|
|
22
37
|
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
resourceAltText = '' // = ressourceFileName by default
|
|
39
|
+
resourceFileName = ''
|
|
40
|
+
resourceUrl: URL
|
|
25
41
|
|
|
26
42
|
constructor(
|
|
27
43
|
private recordsApiService: RecordsApiService,
|
|
@@ -29,42 +45,122 @@ export class OverviewUploadComponent implements OnInit {
|
|
|
29
45
|
) {}
|
|
30
46
|
|
|
31
47
|
ngOnInit(): void {
|
|
32
|
-
this.recordsApiService
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
this.recordsApiService.getAllResources(this.metadataUuid).subscribe({
|
|
49
|
+
next: (resources) => {
|
|
50
|
+
if (resources && resources.length > 0) {
|
|
51
|
+
this.resourceUrl = new URL(resources[0]?.url)
|
|
52
|
+
this.resourceAltText =
|
|
53
|
+
this.resourceAltText === ''
|
|
54
|
+
? resources[0].filename
|
|
55
|
+
: this.resourceAltText
|
|
56
|
+
this.resourceFileName = extractFileNameFromUrl(resources[0]?.url)
|
|
57
|
+
} else {
|
|
58
|
+
this.resourceUrl = null
|
|
59
|
+
this.resourceAltText = ''
|
|
60
|
+
this.resourceFileName = ''
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
this.cd.markForCheck()
|
|
38
|
-
}
|
|
64
|
+
},
|
|
65
|
+
error: this.errorHandle,
|
|
66
|
+
})
|
|
39
67
|
}
|
|
40
68
|
|
|
41
69
|
handleFileChange(file: File) {
|
|
42
70
|
this.recordsApiService
|
|
43
71
|
.putResource(this.metadataUuid, file, 'public')
|
|
44
|
-
.subscribe(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
.subscribe({
|
|
73
|
+
next: (resource) => {
|
|
74
|
+
this.resourceUrl = new URL(resource.url)
|
|
75
|
+
this.resourceAltText = resource.filename
|
|
76
|
+
|
|
77
|
+
this.overviewChange.emit({
|
|
78
|
+
url: new URL(resource.url),
|
|
79
|
+
description: resource.filename,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
this.cd.markForCheck()
|
|
83
|
+
},
|
|
84
|
+
error: this.errorHandle,
|
|
48
85
|
})
|
|
49
86
|
}
|
|
50
87
|
|
|
51
88
|
handleUrlChange(url: string) {
|
|
52
89
|
this.recordsApiService
|
|
53
90
|
.putResourceFromURL(this.metadataUuid, url, 'public')
|
|
54
|
-
.subscribe(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
91
|
+
.subscribe({
|
|
92
|
+
next: (resource) => {
|
|
93
|
+
this.resourceUrl = new URL(resource.url)
|
|
94
|
+
this.resourceAltText = resource.filename
|
|
95
|
+
|
|
96
|
+
this.overviewChange.emit({
|
|
97
|
+
url: new URL(resource.url),
|
|
98
|
+
description: resource.filename,
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
this.cd.markForCheck()
|
|
102
|
+
},
|
|
103
|
+
error: this.errorHandle,
|
|
58
104
|
})
|
|
59
105
|
}
|
|
60
106
|
|
|
107
|
+
handleAltTextChange(newAltText: string) {
|
|
108
|
+
this.resourceAltText = newAltText
|
|
109
|
+
|
|
110
|
+
this.overviewChange.emit({
|
|
111
|
+
url: this.resourceUrl,
|
|
112
|
+
description: this.resourceAltText,
|
|
113
|
+
})
|
|
114
|
+
this.cd.markForCheck()
|
|
115
|
+
}
|
|
116
|
+
|
|
61
117
|
handleDelete() {
|
|
62
118
|
this.recordsApiService
|
|
63
119
|
.delResource(this.metadataUuid, this.resourceFileName)
|
|
64
|
-
.subscribe(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
120
|
+
.subscribe({
|
|
121
|
+
next: () => {
|
|
122
|
+
this.resourceAltText = null
|
|
123
|
+
this.resourceUrl = null
|
|
124
|
+
|
|
125
|
+
this.overviewChange.emit(null)
|
|
126
|
+
|
|
127
|
+
this.cd.markForCheck()
|
|
128
|
+
},
|
|
129
|
+
error: this.errorHandle,
|
|
68
130
|
})
|
|
69
131
|
}
|
|
132
|
+
|
|
133
|
+
private errorHandle = (error: never) => {
|
|
134
|
+
console.error(error)
|
|
135
|
+
|
|
136
|
+
this.resourceUrl = null
|
|
137
|
+
this.resourceAltText = ''
|
|
138
|
+
this.resourceFileName = ''
|
|
139
|
+
|
|
140
|
+
this.overviewChange.emit(null)
|
|
141
|
+
|
|
142
|
+
this.cd.markForCheck()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
ngOnChanges(changes: SimpleChanges): void {
|
|
146
|
+
const overviewChanges = changes['formControl']
|
|
147
|
+
if (
|
|
148
|
+
overviewChanges &&
|
|
149
|
+
overviewChanges.currentValue !== overviewChanges.previousValue
|
|
150
|
+
) {
|
|
151
|
+
let overview: GraphicOverview
|
|
152
|
+
if (
|
|
153
|
+
overviewChanges.currentValue.value &&
|
|
154
|
+
overviewChanges.currentValue.value.length > 0
|
|
155
|
+
) {
|
|
156
|
+
overview = overviewChanges.currentValue.value[0] as GraphicOverview
|
|
157
|
+
} else {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
if (overview.description && overview.description !== '') {
|
|
161
|
+
this.resourceAltText = overview.description
|
|
162
|
+
this.cd.markForCheck()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
70
166
|
}
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common'
|
|
2
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
|
3
|
+
import { OverviewUploadComponent } from '../../../overview-upload/overview-upload.component'
|
|
4
|
+
import { FormControl } from '@angular/forms'
|
|
5
|
+
import { GraphicOverview } from '../../../../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'gn-ui-form-field-overviews',
|
|
9
|
+
templateUrl: './form-field-overviews.component.html',
|
|
10
|
+
styleUrls: ['./form-field-overviews.component.css'],
|
|
11
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
12
|
+
standalone: true,
|
|
13
|
+
imports: [CommonModule, OverviewUploadComponent],
|
|
14
|
+
})
|
|
15
|
+
export class FormFieldOverviewsComponent {
|
|
16
|
+
@Input() metadataUuid: string
|
|
17
|
+
@Input() control!: FormControl
|
|
18
|
+
|
|
19
|
+
handleOverviewChange(overView: GraphicOverview | null) {
|
|
20
|
+
this.control.setValue(overView ? [overView] : [])
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
CHANGED
|
@@ -76,6 +76,12 @@
|
|
|
76
76
|
<ng-container *ngIf="isSpatialExtentField">
|
|
77
77
|
<gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>
|
|
78
78
|
</ng-container>
|
|
79
|
+
<ng-container *ngIf="isGraphicOverview">
|
|
80
|
+
<gn-ui-form-field-overviews
|
|
81
|
+
[control]="formControl"
|
|
82
|
+
[metadataUuid]="metadataUuid$ | async"
|
|
83
|
+
></gn-ui-form-field-overviews>
|
|
84
|
+
</ng-container>
|
|
79
85
|
<ng-container *ngIf="isKeywords">
|
|
80
86
|
<gn-ui-form-field-keywords
|
|
81
87
|
[control]="formControl"
|
package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
CHANGED
|
@@ -28,6 +28,9 @@ import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/for
|
|
|
28
28
|
import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
|
|
29
29
|
import { CatalogRecordKeys } from '../../../../../../../../libs/common/domain/src/lib/model/record'
|
|
30
30
|
import { FormFieldKeywordsComponent } from './form-field-keywords/form-field-keywords.component'
|
|
31
|
+
import { FormFieldOverviewsComponent } from './form-field-overviews/form-field-overviews.component'
|
|
32
|
+
import { map, take } from 'rxjs/operators'
|
|
33
|
+
import { EditorFacade } from '../../../+state/editor.facade'
|
|
31
34
|
import { FormFieldConfig } from '../../../models'
|
|
32
35
|
|
|
33
36
|
@Component({
|
|
@@ -55,6 +58,7 @@ import { FormFieldConfig } from '../../../models'
|
|
|
55
58
|
FormFieldArrayComponent,
|
|
56
59
|
FormFieldKeywordsComponent,
|
|
57
60
|
TranslateModule,
|
|
61
|
+
FormFieldOverviewsComponent,
|
|
58
62
|
],
|
|
59
63
|
})
|
|
60
64
|
export class FormFieldComponent {
|
|
@@ -70,9 +74,14 @@ export class FormFieldComponent {
|
|
|
70
74
|
|
|
71
75
|
@ViewChild('titleInput') titleInput: ElementRef
|
|
72
76
|
|
|
77
|
+
metadataUuid$ = this.facade.record$.pipe(
|
|
78
|
+
take(1),
|
|
79
|
+
map((record) => record.uniqueIdentifier)
|
|
80
|
+
)
|
|
81
|
+
|
|
73
82
|
formControl = new FormControl()
|
|
74
83
|
|
|
75
|
-
constructor() {
|
|
84
|
+
constructor(private facade: EditorFacade) {
|
|
76
85
|
this.valueChange = this.formControl.valueChanges
|
|
77
86
|
}
|
|
78
87
|
|
|
@@ -101,6 +110,9 @@ export class FormFieldComponent {
|
|
|
101
110
|
get isSpatialExtentField() {
|
|
102
111
|
return this.model === 'spatialExtents'
|
|
103
112
|
}
|
|
113
|
+
get isGraphicOverview() {
|
|
114
|
+
return this.model === 'overviews'
|
|
115
|
+
}
|
|
104
116
|
get isSimpleField() {
|
|
105
117
|
return this.model === 'uniqueIdentifier' || this.model === 'recordUpdated'
|
|
106
118
|
}
|
|
@@ -83,6 +83,13 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
|
|
|
83
83
|
},
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export const RECORD_GRAPHICAL_OVERVIEW_FIELD: EditorField = {
|
|
87
|
+
model: 'overviews',
|
|
88
|
+
formFieldConfig: {
|
|
89
|
+
labelKey: marker('editor.record.form.field.overviews'),
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
86
93
|
/************************************************************
|
|
87
94
|
*************** SECTIONS *****************
|
|
88
95
|
************************************************************
|
|
@@ -90,7 +97,11 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
|
|
|
90
97
|
|
|
91
98
|
export const TITLE_SECTION: EditorSection = {
|
|
92
99
|
hidden: false,
|
|
93
|
-
fields: [
|
|
100
|
+
fields: [
|
|
101
|
+
RECORD_TITLE_FIELD,
|
|
102
|
+
RECORD_ABSTRACT_FIELD,
|
|
103
|
+
RECORD_GRAPHICAL_OVERVIEW_FIELD,
|
|
104
|
+
],
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
export const ABOUT_SECTION: EditorSection = {
|
|
@@ -32,7 +32,7 @@ import { ProxyService } from '../../../../../../libs/util/shared/src'
|
|
|
32
32
|
import { WmsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
|
|
33
33
|
import { LONLAT_CRS_CODES } from '../constant/projections'
|
|
34
34
|
import { fromEPSGCode, register } from 'ol/proj/proj4'
|
|
35
|
-
import proj4 from 'proj4
|
|
35
|
+
import proj4 from 'proj4'
|
|
36
36
|
import { defaults as defaultControls } from 'ol/control/defaults'
|
|
37
37
|
|
|
38
38
|
const FEATURE_PROJECTION = 'EPSG:3857'
|
|
@@ -220,11 +220,15 @@ export class MapUtilsService {
|
|
|
220
220
|
if (!('spatialExtents' in record) || record.spatialExtents.length === 0) {
|
|
221
221
|
return null
|
|
222
222
|
}
|
|
223
|
-
//
|
|
223
|
+
// extend all the spatial extents into an including bbox
|
|
224
224
|
const totalExtent = record.spatialExtents.reduce(
|
|
225
225
|
(prev, curr) => {
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
if ('bbox' in curr) return extend(prev, curr.bbox)
|
|
227
|
+
else if ('geometry' in curr) {
|
|
228
|
+
const geom = GEOJSON.readGeometry(curr.geometry)
|
|
229
|
+
return extend(prev, geom.getExtent())
|
|
230
|
+
}
|
|
231
|
+
return prev
|
|
228
232
|
},
|
|
229
233
|
[Infinity, Infinity, -Infinity, -Infinity]
|
|
230
234
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div class="mb-6 md-description sm:mb-4 sm:pr-16">
|
|
2
2
|
<gn-ui-content-ghost ghostClass="h-32" [showContent]="fieldReady('abstract')">
|
|
3
3
|
<gn-ui-max-lines [maxLines]="6" *ngIf="metadata.abstract">
|
|
4
|
-
<div>
|
|
4
|
+
<div class="mb-6">
|
|
5
5
|
<gn-ui-markdown-parser
|
|
6
6
|
[textContent]="metadata.abstract"
|
|
7
7
|
></gn-ui-markdown-parser>
|
|
@@ -47,19 +47,23 @@
|
|
|
47
47
|
</ng-template>
|
|
48
48
|
</ng-container>
|
|
49
49
|
<ng-container *ngIf="legalConstraints.length">
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
<div class="mb-6">
|
|
51
|
+
<gn-ui-markdown-parser
|
|
52
|
+
*ngFor="let constraint of legalConstraints"
|
|
53
|
+
[textContent]="constraint"
|
|
54
|
+
>
|
|
55
|
+
</gn-ui-markdown-parser>
|
|
56
|
+
</div>
|
|
55
57
|
</ng-container>
|
|
56
58
|
<ng-container *ngIf="otherConstraints.length">
|
|
57
59
|
<div gnUiLinkify *ngFor="let constraint of otherConstraints">
|
|
58
60
|
<h5 translate class="font-medium text-black text-sm mb-[2px] mt-[16px]">
|
|
59
61
|
record.metadata.otherConstraints
|
|
60
62
|
</h5>
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
+
<div class="mb-6">
|
|
64
|
+
<gn-ui-markdown-parser [textContent]="constraint">
|
|
65
|
+
</gn-ui-markdown-parser>
|
|
66
|
+
</div>
|
|
63
67
|
</div>
|
|
64
68
|
</ng-container>
|
|
65
69
|
|
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
<div
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
></gn-ui-progress-bar>
|
|
15
|
-
</div>
|
|
16
|
-
<div
|
|
17
|
-
class="absolute z-10 bg-white border border-black border-opacity-35 rounded-lg shadow-lg p-5 whitespace-nowrap"
|
|
18
|
-
[class]="isMenuShown ? 'block' : 'hidden'"
|
|
19
|
-
>
|
|
1
|
+
<div *ngIf="metadataQualityDisplay" class="mb-6 metadata-quality">
|
|
2
|
+
<gn-ui-popover [content]="popoverItems" theme="light-border">
|
|
3
|
+
<div class="min-w-[200px]" [class]="smaller ? 'leading-[8px]' : ''">
|
|
4
|
+
<gn-ui-progress-bar
|
|
5
|
+
tabindex="0"
|
|
6
|
+
[value]="qualityScore"
|
|
7
|
+
type="primary"
|
|
8
|
+
></gn-ui-progress-bar>
|
|
9
|
+
</div>
|
|
10
|
+
</gn-ui-popover>
|
|
11
|
+
</div>
|
|
12
|
+
<ng-template #popoverItems>
|
|
13
|
+
<div class="p-2 py-4">
|
|
20
14
|
<div class="mb-4 font-bold" translate>record.metadata.quality.details</div>
|
|
21
15
|
<gn-ui-metadata-quality-item
|
|
22
16
|
*ngFor="let e of items"
|
|
@@ -24,4 +18,4 @@
|
|
|
24
18
|
[value]="e.value"
|
|
25
19
|
></gn-ui-metadata-quality-item>
|
|
26
20
|
</div>
|
|
27
|
-
</
|
|
21
|
+
</ng-template>
|
|
@@ -21,8 +21,6 @@ export class MetadataQualityComponent implements OnChanges {
|
|
|
21
21
|
|
|
22
22
|
items: MetadataQualityItem[] = []
|
|
23
23
|
|
|
24
|
-
isMenuShown = false
|
|
25
|
-
|
|
26
24
|
get qualityScore() {
|
|
27
25
|
const qualityScore = this.metadata?.extras?.qualityScore
|
|
28
26
|
return typeof qualityScore === 'number'
|
|
@@ -36,14 +34,6 @@ export class MetadataQualityComponent implements OnChanges {
|
|
|
36
34
|
)
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
showMenu() {
|
|
40
|
-
this.isMenuShown = true
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
hideMenu() {
|
|
44
|
-
this.isMenuShown = false
|
|
45
|
-
}
|
|
46
|
-
|
|
47
37
|
private add(name: string, value: boolean) {
|
|
48
38
|
if (this.metadataQualityDisplay?.[name] !== false) {
|
|
49
39
|
this.items.push({ name, value })
|