geonetwork-ui 2.2.0-dev.8cce3b0e → 2.2.0-dev.91cd6a97
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/gn4/atomic-operations.mjs +27 -1
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +23 -11
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +4 -2
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.mjs +14 -0
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/converter.mjs +10 -9
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +33 -8
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +31 -14
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.mjs +3 -3
- package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +17 -5
- package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +2 -2
- package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.mjs +3 -3
- package/esm2022/libs/util/i18n/src/lib/i18n.constants.mjs +18 -1
- package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
- package/esm2022/libs/util/shared/src/lib/utils/temporal-extent-union.mjs +32 -0
- package/esm2022/translations/de.json +26 -19
- package/esm2022/translations/en.json +26 -19
- package/esm2022/translations/es.json +23 -16
- package/esm2022/translations/fr.json +27 -20
- package/esm2022/translations/it.json +26 -19
- package/esm2022/translations/nl.json +24 -17
- package/esm2022/translations/pt.json +23 -16
- package/fesm2022/geonetwork-ui.mjs +381 -178
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +2 -0
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +4 -5
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts +3 -0
- package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts.map +1 -0
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +3 -3
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +16 -2
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +9 -3
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
- package/libs/ui/layout/src/lib/interactive-table/interactive-table-column/interactive-table-column.component.d.ts +1 -1
- package/libs/util/i18n/src/lib/i18n.constants.d.ts +17 -0
- package/libs/util/i18n/src/lib/i18n.constants.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
- package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts +5 -0
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +56 -2
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +51 -6
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +205 -20
- package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +29 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +30 -11
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.ts +3 -1
- package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +4 -5
- package/src/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.ts +16 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/converter.ts +9 -9
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +58 -20
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +86 -38
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +20 -3
- package/src/libs/common/fixtures/src/lib/elasticsearch/full-response.ts +1 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +44 -8
- package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html +3 -4
- package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.html +1 -1
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +1 -1
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +114 -23
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +20 -3
- package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +1 -1
- package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.html +2 -2
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html +3 -1
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.css +3 -0
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.html +1 -1
- package/src/libs/util/i18n/src/lib/i18n.constants.ts +18 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/src/libs/util/shared/src/lib/utils/temporal-extent-union.ts +32 -0
- package/tailwind.base.config.js +3 -0
- package/tailwind.base.css +2 -2
- package/translations/de.json +26 -19
- package/translations/en.json +26 -19
- package/translations/es.json +23 -16
- package/translations/fr.json +27 -20
- package/translations/it.json +26 -19
- package/translations/nl.json +24 -17
- package/translations/pt.json +23 -16
- package/translations/sk.json +24 -17
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
DatasetRecord,
|
|
6
6
|
DatasetServiceDistribution,
|
|
7
7
|
Individual,
|
|
8
|
+
Keyword,
|
|
9
|
+
KeywordThesaurus,
|
|
8
10
|
RecordStatus,
|
|
9
11
|
Role,
|
|
10
12
|
ServiceEndpoint,
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
findNestedElement,
|
|
26
28
|
findNestedElements,
|
|
27
29
|
readAttribute,
|
|
30
|
+
readText,
|
|
28
31
|
removeAllChildren,
|
|
29
32
|
removeChildren,
|
|
30
33
|
removeChildrenByName,
|
|
@@ -288,7 +291,10 @@ function appendResponsibleParty(contact: Individual) {
|
|
|
288
291
|
)
|
|
289
292
|
}
|
|
290
293
|
|
|
291
|
-
function updateCitationDate(
|
|
294
|
+
function updateCitationDate(
|
|
295
|
+
date: Date,
|
|
296
|
+
type: 'revision' | 'creation' | 'publication'
|
|
297
|
+
) {
|
|
292
298
|
return pipe(
|
|
293
299
|
findNestedElements('gmd:date', 'gmd:CI_Date'),
|
|
294
300
|
filterArray(
|
|
@@ -305,7 +311,10 @@ function updateCitationDate(date: Date, type: 'revision' | 'creation') {
|
|
|
305
311
|
)
|
|
306
312
|
}
|
|
307
313
|
|
|
308
|
-
function appendCitationDate(
|
|
314
|
+
function appendCitationDate(
|
|
315
|
+
date,
|
|
316
|
+
type: 'revision' | 'creation' | 'publication'
|
|
317
|
+
) {
|
|
309
318
|
return appendChildren(
|
|
310
319
|
pipe(
|
|
311
320
|
createElement('gmd:date'),
|
|
@@ -326,47 +335,78 @@ function appendCitationDate(date, type: 'revision' | 'creation') {
|
|
|
326
335
|
)
|
|
327
336
|
}
|
|
328
337
|
|
|
329
|
-
function removeKeywords(
|
|
330
|
-
return removeChildren(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
338
|
+
function removeKeywords() {
|
|
339
|
+
return removeChildren(pipe(findNestedElements('gmd:descriptiveKeywords')))
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// returns a <gmd:thesaurusName> element
|
|
343
|
+
function createThesaurus(thesaurus: KeywordThesaurus) {
|
|
344
|
+
return pipe(
|
|
345
|
+
createElement('gmd:thesaurusName'),
|
|
346
|
+
createChild('gmd:CI_Citation'),
|
|
347
|
+
appendChildren(
|
|
348
|
+
pipe(
|
|
349
|
+
createElement('gmd:title'),
|
|
350
|
+
writeCharacterString(thesaurus.name || thesaurus.id)
|
|
351
|
+
),
|
|
352
|
+
pipe(
|
|
353
|
+
createElement('gmd:identifier'),
|
|
354
|
+
createChild('gmd:MD_Identifier'),
|
|
355
|
+
appendChildren(
|
|
356
|
+
pipe(
|
|
357
|
+
createElement('gmd:code'),
|
|
358
|
+
thesaurus.url
|
|
359
|
+
? writeAnchor(thesaurus.url, thesaurus.id)
|
|
360
|
+
: writeCharacterString(thesaurus.id)
|
|
361
|
+
)
|
|
343
362
|
)
|
|
344
363
|
)
|
|
345
364
|
)
|
|
346
365
|
)
|
|
347
366
|
}
|
|
348
367
|
|
|
349
|
-
function appendKeywords(keywords:
|
|
368
|
+
function appendKeywords(keywords: Keyword[]) {
|
|
369
|
+
const keywordsByThesaurus: Keyword[][] = keywords.reduce((acc, keyword) => {
|
|
370
|
+
const thesaurusId = keyword.thesaurus?.id
|
|
371
|
+
const type = keyword.type
|
|
372
|
+
let existingGroup = acc.find((group) =>
|
|
373
|
+
group[0].thesaurus
|
|
374
|
+
? group[0].thesaurus.id === thesaurusId
|
|
375
|
+
: group[0].type === type
|
|
376
|
+
)
|
|
377
|
+
if (!existingGroup) {
|
|
378
|
+
existingGroup = []
|
|
379
|
+
acc.push(existingGroup)
|
|
380
|
+
}
|
|
381
|
+
existingGroup.push(keyword)
|
|
382
|
+
return acc
|
|
383
|
+
}, [])
|
|
350
384
|
return appendChildren(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
385
|
+
...keywordsByThesaurus.map((keywords) =>
|
|
386
|
+
pipe(
|
|
387
|
+
createElement('gmd:descriptiveKeywords'),
|
|
388
|
+
createChild('gmd:MD_Keywords'),
|
|
389
|
+
appendChildren(
|
|
390
|
+
pipe(
|
|
391
|
+
createElement('gmd:type'),
|
|
392
|
+
createChild('gmd:MD_KeywordTypeCode'),
|
|
393
|
+
addAttribute(
|
|
394
|
+
'codeList',
|
|
395
|
+
'http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_KeywordTypeCode'
|
|
396
|
+
),
|
|
397
|
+
addAttribute('codeListValue', keywords[0].type)
|
|
398
|
+
)
|
|
399
|
+
),
|
|
400
|
+
keywords[0].thesaurus
|
|
401
|
+
? appendChildren(createThesaurus(keywords[0].thesaurus))
|
|
402
|
+
: noop,
|
|
403
|
+
appendChildren(
|
|
404
|
+
...keywords.map((keyword) =>
|
|
356
405
|
pipe(
|
|
357
|
-
createElement('gmd:
|
|
358
|
-
|
|
359
|
-
addAttribute(
|
|
360
|
-
'codeList',
|
|
361
|
-
'http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_KeywordTypeCode'
|
|
362
|
-
),
|
|
363
|
-
addAttribute('codeListValue', type)
|
|
406
|
+
createElement('gmd:keyword'),
|
|
407
|
+
writeCharacterString(keyword.label)
|
|
364
408
|
)
|
|
365
409
|
)
|
|
366
|
-
: noop,
|
|
367
|
-
appendChildren(
|
|
368
|
-
...keywords.map((keyword) =>
|
|
369
|
-
pipe(createElement('gmd:keyword'), writeCharacterString(keyword))
|
|
370
410
|
)
|
|
371
411
|
)
|
|
372
412
|
)
|
|
@@ -740,16 +780,24 @@ export function writeContacts(record: CatalogRecord, rootEl: XmlElement) {
|
|
|
740
780
|
export function writeKeywords(record: CatalogRecord, rootEl: XmlElement) {
|
|
741
781
|
pipe(
|
|
742
782
|
findOrCreateIdentification(),
|
|
743
|
-
removeKeywords(
|
|
744
|
-
appendKeywords(record.keywords
|
|
783
|
+
removeKeywords(),
|
|
784
|
+
appendKeywords(record.keywords)
|
|
745
785
|
)(rootEl)
|
|
746
786
|
}
|
|
747
787
|
|
|
748
|
-
export function
|
|
788
|
+
export function writeTopics(record: CatalogRecord, rootEl: XmlElement) {
|
|
749
789
|
pipe(
|
|
750
790
|
findOrCreateIdentification(),
|
|
751
|
-
|
|
752
|
-
|
|
791
|
+
removeChildrenByName('gmd:topicCategory'),
|
|
792
|
+
appendChildren(
|
|
793
|
+
...record.topics.map((topic) =>
|
|
794
|
+
pipe(
|
|
795
|
+
createElement('gmd:topicCategory'),
|
|
796
|
+
createChild('gmd:MD_TopicCategoryCode'),
|
|
797
|
+
setTextContent(topic)
|
|
798
|
+
)
|
|
799
|
+
)
|
|
800
|
+
)
|
|
753
801
|
)(rootEl)
|
|
754
802
|
}
|
|
755
803
|
|
|
@@ -60,6 +60,22 @@ export type SpatialRepresentationType =
|
|
|
60
60
|
| 'table'
|
|
61
61
|
| 'point'
|
|
62
62
|
|
|
63
|
+
export type KeywordType = 'place' | 'temporal' | 'theme' | 'other'
|
|
64
|
+
|
|
65
|
+
export type KeywordThesaurus = {
|
|
66
|
+
id: string
|
|
67
|
+
name?: string
|
|
68
|
+
url?: URL
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface Keyword {
|
|
72
|
+
label: string
|
|
73
|
+
type: KeywordType
|
|
74
|
+
thesaurus?: KeywordThesaurus
|
|
75
|
+
}
|
|
76
|
+
// languages should be expressed using two-letters ISO 639-1 codes
|
|
77
|
+
export type LanguageCode = string
|
|
78
|
+
|
|
63
79
|
export interface BaseRecord {
|
|
64
80
|
uniqueIdentifier: Uuid
|
|
65
81
|
ownerOrganization: Organization
|
|
@@ -68,9 +84,11 @@ export interface BaseRecord {
|
|
|
68
84
|
abstract: string
|
|
69
85
|
recordCreated?: Date
|
|
70
86
|
recordUpdated: Date
|
|
87
|
+
recordPublished?: Date
|
|
88
|
+
languages: Array<LanguageCode>
|
|
71
89
|
kind: RecordKind
|
|
72
|
-
|
|
73
|
-
keywords: Array<
|
|
90
|
+
topics: Array<string> // TODO: handle codelists
|
|
91
|
+
keywords: Array<Keyword>
|
|
74
92
|
licenses: Array<Constraint>
|
|
75
93
|
legalConstraints: Array<Constraint>
|
|
76
94
|
securityConstraints: Array<Constraint>
|
|
@@ -80,7 +98,6 @@ export interface BaseRecord {
|
|
|
80
98
|
landingPage?: URL
|
|
81
99
|
updateFrequency?: UpdateFrequency
|
|
82
100
|
|
|
83
|
-
// to add: iso19139.topicCategory
|
|
84
101
|
// to add: canonical url
|
|
85
102
|
// to add: source catalog (??)
|
|
86
103
|
// to add: is open data ?
|
|
@@ -131,7 +131,7 @@ export const ES_FIXTURE_FULL_RESPONSE = deepFreeze({
|
|
|
131
131
|
creationDateForResource: ['2012-01-01T00:00:00.000Z'],
|
|
132
132
|
creationYearForResource: '2012',
|
|
133
133
|
creationMonthForResource: '2012-01',
|
|
134
|
-
publicationDateForResource:
|
|
134
|
+
publicationDateForResource: '2021-04-01T00:00:00.000Z',
|
|
135
135
|
publicationYearForResource: '2021',
|
|
136
136
|
publicationMonthForResource: '2021-04',
|
|
137
137
|
resourceDate: [
|
|
@@ -69,8 +69,24 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
|
|
|
69
69
|
url: new URL('http://my-org.net/two.png'),
|
|
70
70
|
},
|
|
71
71
|
],
|
|
72
|
-
keywords: [
|
|
73
|
-
|
|
72
|
+
keywords: [
|
|
73
|
+
{
|
|
74
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
75
|
+
type: 'other',
|
|
76
|
+
label: 'international',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
80
|
+
type: 'other',
|
|
81
|
+
label: 'test',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
85
|
+
type: 'other',
|
|
86
|
+
label: '_another_keyword_',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
topics: ['testData', 'exampleData'],
|
|
74
90
|
spatialRepresentation: 'grid',
|
|
75
91
|
distributions: [
|
|
76
92
|
{
|
|
@@ -170,13 +186,33 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
170
186
|
},
|
|
171
187
|
],
|
|
172
188
|
keywords: [
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
189
|
+
{
|
|
190
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
191
|
+
type: 'other',
|
|
192
|
+
label: 'planification',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
196
|
+
type: 'other',
|
|
197
|
+
label: 'PLU',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
201
|
+
type: 'other',
|
|
202
|
+
label: "Plan local d'urbanisme",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
206
|
+
type: 'other',
|
|
207
|
+
label: 'données ouvertes',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
211
|
+
type: 'other',
|
|
212
|
+
label: 'Avrigny*60036',
|
|
213
|
+
},
|
|
178
214
|
],
|
|
179
|
-
|
|
215
|
+
topics: ['Usage des sols', "document d'urbanisme"],
|
|
180
216
|
spatialRepresentation: 'vector',
|
|
181
217
|
distributions: [
|
|
182
218
|
{
|
package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<div class="flex flex-row
|
|
1
|
+
<div class="flex flex-row items-center">
|
|
2
2
|
<span
|
|
3
|
-
class="align-text-top mr-1.5
|
|
3
|
+
class="align-text-top mr-1.5 favorite-count"
|
|
4
4
|
*ngIf="hasFavoriteCount && displayCount"
|
|
5
5
|
>{{ favoriteCount }}</span
|
|
6
6
|
>
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
[toggled]="isFavorite$ | async"
|
|
9
9
|
(newValue)="toggleFavorite($event)"
|
|
10
10
|
[disabled]="loading || (isAnonymous$ | async)"
|
|
11
|
-
class="mt-1"
|
|
12
11
|
></gn-ui-star-toggle>
|
|
13
12
|
<span
|
|
14
|
-
class="align-text-top ml-1.5 favorite-count
|
|
13
|
+
class="align-text-top ml-1.5 favorite-count"
|
|
15
14
|
*ngIf="!displayCount"
|
|
16
15
|
translate="datahub.record.addToFavorites"
|
|
17
16
|
></span>
|
|
@@ -55,29 +55,85 @@
|
|
|
55
55
|
</div>
|
|
56
56
|
</gn-ui-expandable-panel>
|
|
57
57
|
<gn-ui-expandable-panel
|
|
58
|
-
class="metadata-origin"
|
|
59
58
|
*ngIf="
|
|
60
59
|
metadata.lineage ||
|
|
61
60
|
metadata.recordUpdated ||
|
|
62
61
|
metadata.updateFrequency ||
|
|
63
62
|
metadata.status
|
|
64
63
|
"
|
|
65
|
-
[title]="'record.metadata.
|
|
64
|
+
[title]="'record.metadata.details' | translate"
|
|
66
65
|
>
|
|
67
|
-
<
|
|
66
|
+
<div
|
|
68
67
|
*ngIf="metadata.lineage"
|
|
69
|
-
class="mb-5 pt-4
|
|
70
|
-
gnUiLinkify
|
|
68
|
+
class="text-gray-900 flex flex-col mb-5 pt-4 gap-2"
|
|
71
69
|
>
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
<p class="whitespace-pre-line break-words text-gray-900" gnUiLinkify>
|
|
71
|
+
{{ metadata.lineage }}
|
|
72
|
+
</p>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="flex flex-row gap-6 mb-8" *ngIf="resourceContact">
|
|
75
|
+
<div
|
|
76
|
+
*ngIf="resourceContact.organization?.logoUrl?.href"
|
|
77
|
+
class="flex items-center justify-center border-solid border border-gray-300 rounded-md bg-white h-32 overflow-hidden"
|
|
78
|
+
>
|
|
79
|
+
<gn-ui-thumbnail
|
|
80
|
+
class="relative h-full w-full"
|
|
81
|
+
[thumbnailUrl]="resourceContact.organization.logoUrl.href"
|
|
82
|
+
fit="contain"
|
|
83
|
+
></gn-ui-thumbnail>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="flex flex-col gap-1">
|
|
86
|
+
<p class="text-sm font-medium" translate>record.metadata.producer</p>
|
|
87
|
+
<div
|
|
88
|
+
class="text-primary font-title text-21 mr-2 cursor-pointer hover:underline"
|
|
89
|
+
data-cy="organization-name"
|
|
90
|
+
>
|
|
91
|
+
{{ resourceContact.organization?.name }}
|
|
92
|
+
</div>
|
|
93
|
+
<div *ngIf="resourceContact.organization?.website">
|
|
94
|
+
<a
|
|
95
|
+
[href]="resourceContact.organization.website"
|
|
96
|
+
target="_blank"
|
|
97
|
+
class="contact-website text-primary text-sm cursor-pointer hover:underline transition-all"
|
|
98
|
+
>{{ resourceContact.organization.website }}
|
|
99
|
+
<mat-icon
|
|
100
|
+
class="material-symbols-outlined !w-[12px] !h-[12px] !text-[12px] opacity-75 shrink-0"
|
|
101
|
+
>open_in_new</mat-icon
|
|
102
|
+
>
|
|
103
|
+
</a>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="mt-4" *ngIf="resourceContact.email">
|
|
106
|
+
<div class="flex">
|
|
107
|
+
<mat-icon
|
|
108
|
+
class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
|
|
109
|
+
>
|
|
110
|
+
mail_outline</mat-icon
|
|
111
|
+
>
|
|
112
|
+
<a
|
|
113
|
+
*ngIf="resourceContact.email"
|
|
114
|
+
[href]="'mailto:' + resourceContact.email"
|
|
115
|
+
class="text-sm hover:underline ml-2"
|
|
116
|
+
target="_blank"
|
|
117
|
+
data-cy="contact-email"
|
|
118
|
+
>{{ resourceContact?.email }}</a
|
|
119
|
+
>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
74
124
|
<div
|
|
75
|
-
class="py-
|
|
125
|
+
class="py-6 px-6 rounded bg-gray-100 grid grid-cols-2 gap-y-6 gap-x-[20px] text-gray-700"
|
|
76
126
|
>
|
|
77
|
-
<div *ngIf="metadata.
|
|
78
|
-
<p class="text-sm" translate>record.metadata.
|
|
127
|
+
<div *ngIf="metadata.recordCreated">
|
|
128
|
+
<p class="text-sm" translate>record.metadata.creation</p>
|
|
79
129
|
<p class="text-primary font-medium mt-1">
|
|
80
|
-
{{ metadata.
|
|
130
|
+
{{ metadata.recordCreated.toLocaleDateString() }}
|
|
131
|
+
</p>
|
|
132
|
+
</div>
|
|
133
|
+
<div *ngIf="metadata.recordPublished">
|
|
134
|
+
<p class="text-sm" translate>record.metadata.publication</p>
|
|
135
|
+
<p class="text-primary font-medium mt-1">
|
|
136
|
+
{{ metadata.recordPublished.toLocaleDateString() }}
|
|
81
137
|
</p>
|
|
82
138
|
</div>
|
|
83
139
|
<div *ngIf="updateFrequency">
|
|
@@ -90,17 +146,52 @@
|
|
|
90
146
|
{{ updateFrequency }}
|
|
91
147
|
</p>
|
|
92
148
|
</div>
|
|
93
|
-
<div *ngIf="metadata.
|
|
94
|
-
<p class="text-sm" translate>record.metadata.
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
149
|
+
<div *ngIf="metadata.languages">
|
|
150
|
+
<p class="text-sm mb-1" translate>record.metadata.languages</p>
|
|
151
|
+
<div class="flex flex-row gap-1 flex-wrap">
|
|
152
|
+
<p
|
|
153
|
+
class="text-primary font-medium"
|
|
154
|
+
translate
|
|
155
|
+
*ngFor="let language of metadata.languages"
|
|
156
|
+
>
|
|
157
|
+
language.{{ language }}
|
|
158
|
+
</p>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
<div *ngIf="temporalExtent">
|
|
162
|
+
<p class="text-sm" translate>record.metadata.temporalExtent</p>
|
|
163
|
+
<div class="flex flex-row gap-1 mb-1 text-primary font-medium">
|
|
164
|
+
<p
|
|
165
|
+
*ngIf="temporalExtent.start && temporalExtent.end"
|
|
166
|
+
translate
|
|
167
|
+
[translateParams]="{
|
|
168
|
+
start: temporalExtent.start,
|
|
169
|
+
end: temporalExtent.end
|
|
170
|
+
}"
|
|
171
|
+
>
|
|
172
|
+
record.metadata.temporalExtent.fromDateToDate
|
|
173
|
+
</p>
|
|
174
|
+
<p
|
|
175
|
+
*ngIf="temporalExtent.start && !temporalExtent.end"
|
|
176
|
+
translate
|
|
177
|
+
[translateParams]="{ start: temporalExtent.start }"
|
|
178
|
+
>
|
|
179
|
+
record.metadata.temporalExtent.sinceDate
|
|
180
|
+
</p>
|
|
181
|
+
<p
|
|
182
|
+
*ngIf="!temporalExtent.start && temporalExtent.end"
|
|
183
|
+
translate
|
|
184
|
+
[translateParams]="{ end: temporalExtent.end }"
|
|
185
|
+
>
|
|
186
|
+
record.metadata.temporalExtent.untilDate
|
|
187
|
+
</p>
|
|
188
|
+
</div>
|
|
98
189
|
</div>
|
|
99
190
|
</div>
|
|
100
191
|
</gn-ui-expandable-panel>
|
|
101
192
|
<gn-ui-expandable-panel
|
|
102
193
|
*ngIf="metadata.landingPage"
|
|
103
|
-
[title]="'record.metadata.
|
|
194
|
+
[title]="'record.metadata.technical' | translate"
|
|
104
195
|
>
|
|
105
196
|
<div class="flex flex-col gap-4 mr-4 py-5 rounded text-gray-700">
|
|
106
197
|
<div *ngIf="metadata.recordUpdated">
|
|
@@ -136,13 +227,13 @@
|
|
|
136
227
|
</p>
|
|
137
228
|
</div>
|
|
138
229
|
</div>
|
|
139
|
-
<div *ngIf="metadata.
|
|
140
|
-
<p class="text-sm mb-1" translate>record.metadata.
|
|
230
|
+
<div *ngIf="metadata.topics?.length">
|
|
231
|
+
<p class="text-sm mb-1" translate>record.metadata.topics</p>
|
|
141
232
|
<div class="sm:pb-4 sm:pr-16">
|
|
142
233
|
<gn-ui-badge
|
|
143
|
-
class="inline-block mr-2 lowercase"
|
|
144
|
-
*ngFor="let
|
|
145
|
-
>{{
|
|
234
|
+
class="inline-block mr-2 mb-2 lowercase"
|
|
235
|
+
*ngFor="let topic of metadata.topics"
|
|
236
|
+
>{{ topic }}</gn-ui-badge
|
|
146
237
|
>
|
|
147
238
|
</div>
|
|
148
239
|
</div>
|
|
@@ -154,7 +245,7 @@
|
|
|
154
245
|
(click)="onKeywordClick(keyword)"
|
|
155
246
|
[clickable]="true"
|
|
156
247
|
*ngFor="let keyword of metadata.keywords"
|
|
157
|
-
>{{ keyword }}</gn-ui-badge
|
|
248
|
+
>{{ keyword.label }}</gn-ui-badge
|
|
158
249
|
>
|
|
159
250
|
</div>
|
|
160
251
|
</div>
|
|
@@ -5,7 +5,11 @@ import {
|
|
|
5
5
|
Input,
|
|
6
6
|
Output,
|
|
7
7
|
} from '@angular/core'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
DatasetRecord,
|
|
10
|
+
Keyword,
|
|
11
|
+
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
12
|
+
import { getTemporalRangeUnion } from '../../../../../../libs/util/shared/src'
|
|
9
13
|
|
|
10
14
|
@Component({
|
|
11
15
|
selector: 'gn-ui-metadata-info',
|
|
@@ -16,7 +20,7 @@ import { DatasetRecord } from '../../../../../../libs/common/domain/src/lib/mode
|
|
|
16
20
|
export class MetadataInfoComponent {
|
|
17
21
|
@Input() metadata: Partial<DatasetRecord>
|
|
18
22
|
@Input() incomplete: boolean
|
|
19
|
-
@Output() keyword = new EventEmitter<
|
|
23
|
+
@Output() keyword = new EventEmitter<Keyword>()
|
|
20
24
|
updatedTimes: number
|
|
21
25
|
|
|
22
26
|
get hasUsage() {
|
|
@@ -73,11 +77,24 @@ export class MetadataInfoComponent {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
get temporalExtent(): { start: string; end: string } {
|
|
81
|
+
const temporalExtents = this.metadata.temporalExtents
|
|
82
|
+
return getTemporalRangeUnion(temporalExtents)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get shownOrganization() {
|
|
86
|
+
return this.metadata.ownerOrganization
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get resourceContact() {
|
|
90
|
+
return this.metadata.contactsForResource?.[0]
|
|
91
|
+
}
|
|
92
|
+
|
|
76
93
|
fieldReady(propName: string) {
|
|
77
94
|
return !this.incomplete || propName in this.metadata
|
|
78
95
|
}
|
|
79
96
|
|
|
80
|
-
onKeywordClick(keyword:
|
|
97
|
+
onKeywordClick(keyword: Keyword) {
|
|
81
98
|
this.keyword.emit(keyword)
|
|
82
99
|
}
|
|
83
100
|
}
|
|
@@ -55,7 +55,7 @@ export class MetadataQualityComponent implements OnChanges {
|
|
|
55
55
|
this.items = []
|
|
56
56
|
this.add('title', !!this.metadata?.title)
|
|
57
57
|
this.add('description', !!this.metadata?.abstract)
|
|
58
|
-
this.add('topic', this.metadata?.
|
|
58
|
+
this.add('topic', this.metadata?.topics?.length > 0)
|
|
59
59
|
this.add('keywords', this.metadata?.keywords?.length > 0)
|
|
60
60
|
this.add('legalConstraints', this.metadata?.legalConstraints?.length > 0)
|
|
61
61
|
this.add('organisation', !!contact?.organization)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<div
|
|
2
2
|
#containerElement
|
|
3
|
-
class="h-full w-full relative shrink-0 overflow-hidden flex items-center"
|
|
3
|
+
class="h-full w-full relative shrink-0 overflow-hidden flex items-center justify-center"
|
|
4
4
|
[ngClass]="isPlaceholder ? 'bg-gray-100' : 'bg-white'"
|
|
5
5
|
[attr.data-cy-is-placeholder]="isPlaceholder.toString()"
|
|
6
6
|
>
|
|
7
7
|
<img
|
|
8
8
|
#imageElement
|
|
9
9
|
class="relative w-full object-center"
|
|
10
|
-
[ngClass]="imgFit === 'contain' ? 'h-4/5' : 'h-full'"
|
|
10
|
+
[ngClass]="imgFit === 'contain' ? 'h-4/5 w-4/5' : 'h-full'"
|
|
11
11
|
[ngStyle]="{ objectFit: imgFit }"
|
|
12
12
|
alt="thumbnail"
|
|
13
13
|
loading="lazy"
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
<gn-ui-button
|
|
10
10
|
type="outline"
|
|
11
11
|
class="grow min-w-0"
|
|
12
|
-
extraClass="!p-[8px] !pl-[16px] flex flex-row w-full {{
|
|
12
|
+
extraClass="bg-background !p-[8px] !pl-[16px] flex flex-row w-full {{
|
|
13
|
+
extraBtnClass
|
|
14
|
+
}}"
|
|
13
15
|
[title]="title"
|
|
14
16
|
[attr.aria-owns]="id"
|
|
15
17
|
(buttonClick)="openOverlay()"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<button
|
|
2
|
-
class="group flex items-center justify-center gap-1 backdrop-blur p-1 bg-primary-opacity-30
|
|
2
|
+
class="group flex items-center justify-center gap-1 backdrop-blur p-1 bg-primary-opacity-30 rounded content-center"
|
|
3
3
|
>
|
|
4
4
|
<mat-icon class="material-symbols-outlined align-middle w-[18px]">{{
|
|
5
5
|
icon
|
|
@@ -40,6 +40,24 @@ export const LANG_3_TO_2_MAPPER = {
|
|
|
40
40
|
slo: 'sk',
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export const LANGUAGE_NAMES = {
|
|
44
|
+
en: 'English',
|
|
45
|
+
nl: 'Nederlands',
|
|
46
|
+
fr: 'Français',
|
|
47
|
+
de: 'Deutsch',
|
|
48
|
+
ko: '한국어',
|
|
49
|
+
es: 'Español',
|
|
50
|
+
cs: 'Čeština',
|
|
51
|
+
ca: 'Català',
|
|
52
|
+
fi: 'Suomi',
|
|
53
|
+
is: 'Íslenska',
|
|
54
|
+
it: 'Italiano',
|
|
55
|
+
pt: 'Português',
|
|
56
|
+
ru: 'Русский',
|
|
57
|
+
zh: '中文',
|
|
58
|
+
sk: 'Slovenčina',
|
|
59
|
+
}
|
|
60
|
+
|
|
43
61
|
// Caution: changing this can break language selection from third parties!
|
|
44
62
|
export const LANGUAGE_STORAGE_KEY = 'geonetwork-ui-language'
|
|
45
63
|
|