geonetwork-ui 2.10.0-dev.9b93be024 → 2.10.0-dev.a9cc01fc7
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 +223 -101
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +51 -16
- package/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +14 -2
- package/src/libs/api/repository/src/lib/gn4/gn4.provider.ts +6 -1
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +6 -0
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +0 -1
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +10 -1
- package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.html +18 -3
- package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +33 -40
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-constraints-shortcuts/form-field-constraints-shortcuts.component.ts +34 -34
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html +8 -15
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.ts +6 -4
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html +8 -7
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts +6 -6
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.css +3 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.html +1 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +57 -3
- package/src/libs/ui/elements/src/index.ts +1 -0
- package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.html +16 -0
- package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.ts +26 -0
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +1 -1
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +0 -1
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +0 -4
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +27 -66
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +30 -10
- package/src/libs/ui/inputs/src/lib/button/button.component.ts +4 -0
- package/src/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.html +0 -1
- package/src/libs/util/shared/src/lib/record/quality-score.util.ts +33 -18
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/src/libs/util/shared/src/lib/utils/user-display.ts +23 -0
- package/tailwind.base.css +11 -2
- package/translations/de.json +1 -0
- package/translations/en.json +1 -0
- 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
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
} from '@angular/core'
|
|
9
9
|
import {
|
|
10
10
|
CatalogRecord,
|
|
11
|
+
Individual,
|
|
11
12
|
Keyword,
|
|
13
|
+
Role,
|
|
14
|
+
RoleLabels,
|
|
12
15
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
13
16
|
import { DateService, getTemporalRangeUnion } from '../../../../../../libs/util/shared/src'
|
|
14
17
|
import { MarkdownParserComponent } from '../markdown-parser/markdown-parser.component'
|
|
@@ -19,17 +22,18 @@ import {
|
|
|
19
22
|
import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
|
|
20
23
|
import {
|
|
21
24
|
BadgeComponent,
|
|
25
|
+
ButtonComponent,
|
|
22
26
|
CopyTextButtonComponent,
|
|
23
27
|
} from '../../../../../../libs/ui/inputs/src'
|
|
24
28
|
import { ContentGhostComponent } from '../content-ghost/content-ghost.component'
|
|
25
29
|
import { NgIcon, provideIcons } from '@ng-icons/core'
|
|
26
30
|
import { matOpenInNew } from '@ng-icons/material-icons/baseline'
|
|
27
31
|
import { matMailOutline } from '@ng-icons/material-icons/outline'
|
|
28
|
-
import { ThumbnailComponent } from '../thumbnail/thumbnail.component'
|
|
29
32
|
import { GnUiLinkifyDirective } from './linkify.directive'
|
|
30
33
|
import { GnUiHumanizeDateDirective } from '../../../../../../libs/util/shared/src'
|
|
31
34
|
|
|
32
35
|
import { SpatialExtentComponent } from '../../../../../../libs/ui/map/src'
|
|
36
|
+
import { ContactPillComponent } from '../contact-pill/contact-pill.component'
|
|
33
37
|
|
|
34
38
|
@Component({
|
|
35
39
|
selector: 'gn-ui-metadata-info',
|
|
@@ -42,15 +46,16 @@ import { SpatialExtentComponent } from '../../../../../../libs/ui/map/src'
|
|
|
42
46
|
TranslatePipe,
|
|
43
47
|
MarkdownParserComponent,
|
|
44
48
|
ExpandablePanelComponent,
|
|
49
|
+
ButtonComponent,
|
|
45
50
|
BadgeComponent,
|
|
46
51
|
ContentGhostComponent,
|
|
47
|
-
ThumbnailComponent,
|
|
48
52
|
MaxLinesComponent,
|
|
49
53
|
CopyTextButtonComponent,
|
|
50
54
|
NgIcon,
|
|
51
55
|
GnUiLinkifyDirective,
|
|
52
56
|
GnUiHumanizeDateDirective,
|
|
53
57
|
SpatialExtentComponent,
|
|
58
|
+
ContactPillComponent,
|
|
54
59
|
],
|
|
55
60
|
viewProviders: [
|
|
56
61
|
provideIcons({
|
|
@@ -132,18 +137,33 @@ export class MetadataInfoComponent {
|
|
|
132
137
|
return getTemporalRangeUnion(temporalExtents, this.dateService)
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
get shownOrganization() {
|
|
136
|
-
return this.metadata.ownerOrganization
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
get resourceContact() {
|
|
140
|
-
return this.metadata.contactsForResource?.[0]
|
|
141
|
-
}
|
|
142
|
-
|
|
143
140
|
fieldReady(propName: string) {
|
|
144
141
|
return !this.incomplete || propName in this.metadata
|
|
145
142
|
}
|
|
146
143
|
|
|
144
|
+
get contactGroups(): {
|
|
145
|
+
role: Role
|
|
146
|
+
roleLabel: string
|
|
147
|
+
contacts: Individual[]
|
|
148
|
+
}[] {
|
|
149
|
+
const groups: { role: Role; roleLabel: string; contacts: Individual[] }[] =
|
|
150
|
+
[]
|
|
151
|
+
const indexByRole = new Map<Role, number>()
|
|
152
|
+
for (const contact of this.metadata.contactsForResource ?? []) {
|
|
153
|
+
if (indexByRole.has(contact.role)) {
|
|
154
|
+
groups[indexByRole.get(contact.role)].contacts.push(contact)
|
|
155
|
+
} else {
|
|
156
|
+
indexByRole.set(contact.role, groups.length)
|
|
157
|
+
groups.push({
|
|
158
|
+
role: contact.role,
|
|
159
|
+
roleLabel: RoleLabels.get(contact.role),
|
|
160
|
+
contacts: [contact],
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return groups
|
|
165
|
+
}
|
|
166
|
+
|
|
147
167
|
onKeywordClick(keyword: Keyword) {
|
|
148
168
|
this.keyword.emit(keyword)
|
|
149
169
|
}
|
|
@@ -26,6 +26,7 @@ export class ButtonComponent {
|
|
|
26
26
|
| 'light'
|
|
27
27
|
| 'gray'
|
|
28
28
|
| 'black'
|
|
29
|
+
| 'primary-light'
|
|
29
30
|
) {
|
|
30
31
|
// btn-classes are written in full to be picked up by tailwind
|
|
31
32
|
switch (value) {
|
|
@@ -47,6 +48,9 @@ export class ButtonComponent {
|
|
|
47
48
|
case 'black':
|
|
48
49
|
this.btnClass = 'gn-ui-btn-black'
|
|
49
50
|
break
|
|
51
|
+
case 'primary-light':
|
|
52
|
+
this.btnClass = 'gn-ui-btn-primary-light'
|
|
53
|
+
break
|
|
50
54
|
case 'default':
|
|
51
55
|
default:
|
|
52
56
|
this.btnClass = 'gn-ui-btn-default'
|
|
@@ -3,27 +3,41 @@ import {
|
|
|
3
3
|
RecordKind,
|
|
4
4
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
5
5
|
|
|
6
|
+
type TValidatorEntry = {
|
|
7
|
+
validator: (metadata: Partial<CatalogRecord>) => boolean
|
|
8
|
+
alias?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
type TValidatorMapper = {
|
|
7
|
-
[key: string]:
|
|
12
|
+
[key: string]: TValidatorEntry
|
|
8
13
|
}
|
|
9
14
|
|
|
10
15
|
const ValidatorMapper: TValidatorMapper = {
|
|
11
|
-
title: (record) => !!record?.title,
|
|
12
|
-
abstract: (record) => !!record?.abstract,
|
|
13
|
-
keywords: (record) => (record?.keywords?.length ?? 0) > 0,
|
|
14
|
-
legalConstraints:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
title: { validator: (record) => !!record?.title },
|
|
17
|
+
abstract: { validator: (record) => !!record?.abstract },
|
|
18
|
+
keywords: { validator: (record) => (record?.keywords?.length ?? 0) > 0 },
|
|
19
|
+
legalConstraints: {
|
|
20
|
+
validator: (record) =>
|
|
21
|
+
!!(
|
|
22
|
+
record?.legalConstraints?.length &&
|
|
23
|
+
record.legalConstraints.some((c) => c?.text?.trim().length > 0)
|
|
24
|
+
),
|
|
25
|
+
},
|
|
26
|
+
contacts: {
|
|
27
|
+
validator: (record) =>
|
|
28
|
+
!!record?.contacts?.[0]?.email &&
|
|
29
|
+
record.contacts[0].email !== 'missing@missing.com',
|
|
30
|
+
},
|
|
31
|
+
updateFrequency: {
|
|
32
|
+
validator: (record) =>
|
|
33
|
+
!!record?.updateFrequency && record.updateFrequency !== 'unknown',
|
|
34
|
+
},
|
|
35
|
+
topics: { validator: (record) => (record?.topics?.length ?? 0) > 0 },
|
|
36
|
+
organisation: {
|
|
37
|
+
validator: (record) => !!record?.contacts?.[0]?.organization?.name,
|
|
38
|
+
alias: 'contacts',
|
|
39
|
+
},
|
|
40
|
+
source: { validator: (record) => !!record?.extras?.sourcesIdentifiers },
|
|
27
41
|
} as const
|
|
28
42
|
|
|
29
43
|
export type ValidatorMapperKeys = keyof typeof ValidatorMapper & string
|
|
@@ -67,6 +81,7 @@ export function getQualityValidators(
|
|
|
67
81
|
|
|
68
82
|
return filteredProps.map((name) => ({
|
|
69
83
|
name,
|
|
70
|
-
validator: () => ValidatorMapper[name](record),
|
|
84
|
+
validator: () => ValidatorMapper[name].validator(record),
|
|
85
|
+
alias: ValidatorMapper[name].alias,
|
|
71
86
|
}))
|
|
72
87
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { UserModel } from '../../../../../../libs/common/domain/src/lib/model/user'
|
|
2
|
+
import { Individual } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
3
|
+
|
|
4
|
+
export function getIndividualDisplayName(individual: Individual): string {
|
|
5
|
+
const nameParts = [individual.firstName, individual.lastName]
|
|
6
|
+
.filter(Boolean)
|
|
7
|
+
.join(' ')
|
|
8
|
+
const orgPart = individual.organization?.name
|
|
9
|
+
? ` (${individual.organization.name})`
|
|
10
|
+
: ''
|
|
11
|
+
if (nameParts) return `${nameParts}${orgPart}`
|
|
12
|
+
return individual.organization?.name ?? individual.email ?? ''
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function toIndividual(user: UserModel): Individual {
|
|
16
|
+
return {
|
|
17
|
+
firstName: user.name,
|
|
18
|
+
lastName: user.surname,
|
|
19
|
+
email: user.email,
|
|
20
|
+
role: 'unspecified',
|
|
21
|
+
organization: user.organisation ? { name: user.organisation } : undefined,
|
|
22
|
+
}
|
|
23
|
+
}
|
package/tailwind.base.css
CHANGED
|
@@ -74,7 +74,10 @@
|
|
|
74
74
|
--bg-hover: var(--gn-ui-button-bg-hover, var(--color-background));
|
|
75
75
|
--font-size: var(--gn-ui-button-font-size, 1em);
|
|
76
76
|
--color: var(--gn-ui-button-color, var(--color-main));
|
|
77
|
-
|
|
77
|
+
--disabled-opacity: var(--gn-ui-button-disabled-opacity, 0.5);
|
|
78
|
+
--justify: var(--gn-ui-button-justify, center);
|
|
79
|
+
justify-content: var(--justify);
|
|
80
|
+
@apply flex flex-row items-center
|
|
78
81
|
text-[length:--font-size] leading-none
|
|
79
82
|
text-[color:--color]
|
|
80
83
|
p-[--padding] rounded-[--rounded] w-[--width] h-[--height] overflow-hidden
|
|
@@ -82,7 +85,7 @@
|
|
|
82
85
|
hover:bg-[--bg-hover] focus:bg-[--bg-hover] active:bg-[--background]
|
|
83
86
|
outline-none
|
|
84
87
|
relative
|
|
85
|
-
disabled:opacity-
|
|
88
|
+
disabled:opacity-[--disabled-opacity] disabled:pointer-events-none
|
|
86
89
|
focus:z-10 active:z-10 hover:z-10;
|
|
87
90
|
}
|
|
88
91
|
/* makes sure icons will not make the buttons grow vertically */
|
|
@@ -134,6 +137,12 @@
|
|
|
134
137
|
bg-white border-white focus:ring-4 focus:ring-gray-300;
|
|
135
138
|
}
|
|
136
139
|
|
|
140
|
+
.gn-ui-btn-primary-light {
|
|
141
|
+
@apply gn-ui-btn text-primary-darkest
|
|
142
|
+
bg-primary-white hover:bg-primary focus:bg-primary hover:text-white focus:text-white active:bg-primary-darker
|
|
143
|
+
border-transparent;
|
|
144
|
+
}
|
|
145
|
+
|
|
137
146
|
.gn-ui-card-s {
|
|
138
147
|
@apply min-h-[64px] w-full xs:min-w-[260px] xs:max-w-[280px] sm:min-w-[300px] sm:max-w-[500px] md:min-w-[230px];
|
|
139
148
|
}
|
package/translations/de.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "Aktualisierungsfrequenz nicht angegeben",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "Aktualisierungsfrequenz angegeben",
|
|
522
522
|
"record.metadata.related": "Entdecken Sie den Katalog",
|
|
523
|
+
"record.metadata.resource.contacts": "Kontakte zur Ressource",
|
|
523
524
|
"record.metadata.resourceCreated": "Erstellt",
|
|
524
525
|
"record.metadata.resourcePublished": "Veröffentlicht",
|
|
525
526
|
"record.metadata.resourceUpdated": "Zuletzt aktualisiert",
|
package/translations/en.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "Update frequency is not specified",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "Update frequency is specified",
|
|
522
522
|
"record.metadata.related": "Explore the catalog",
|
|
523
|
+
"record.metadata.resource.contacts": "Contacts for the resource",
|
|
523
524
|
"record.metadata.resourceCreated": "Created",
|
|
524
525
|
"record.metadata.resourcePublished": "Published",
|
|
525
526
|
"record.metadata.resourceUpdated": "Last updated",
|
package/translations/es.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "",
|
|
522
522
|
"record.metadata.related": "",
|
|
523
|
+
"record.metadata.resource.contacts": "",
|
|
523
524
|
"record.metadata.resourceCreated": "",
|
|
524
525
|
"record.metadata.resourcePublished": "",
|
|
525
526
|
"record.metadata.resourceUpdated": "",
|
package/translations/fr.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "La fréquence de mise à jour n'est pas renseignée",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "La fréquence de mise à jour est renseignée",
|
|
522
522
|
"record.metadata.related": "Explorez le catalogue",
|
|
523
|
+
"record.metadata.resource.contacts": "Contacts liés à la donnée",
|
|
523
524
|
"record.metadata.resourceCreated": "Créé",
|
|
524
525
|
"record.metadata.resourcePublished": "Publié",
|
|
525
526
|
"record.metadata.resourceUpdated": "Mis à jour",
|
package/translations/it.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "La frequenza di aggiornamento non è specificata",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "La frequenza di aggiornamento è specificata",
|
|
522
522
|
"record.metadata.related": "Vedi anche",
|
|
523
|
+
"record.metadata.resource.contacts": "Contatti per la risorsa",
|
|
523
524
|
"record.metadata.resourceCreated": "Creato",
|
|
524
525
|
"record.metadata.resourcePublished": "Pubblicato",
|
|
525
526
|
"record.metadata.resourceUpdated": "Ultimo aggiornamento",
|
package/translations/nl.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "",
|
|
522
522
|
"record.metadata.related": "",
|
|
523
|
+
"record.metadata.resource.contacts": "",
|
|
523
524
|
"record.metadata.resourceCreated": "",
|
|
524
525
|
"record.metadata.resourcePublished": "",
|
|
525
526
|
"record.metadata.resourceUpdated": "",
|
package/translations/pt.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "",
|
|
522
522
|
"record.metadata.related": "",
|
|
523
|
+
"record.metadata.resource.contacts": "",
|
|
523
524
|
"record.metadata.resourceCreated": "",
|
|
524
525
|
"record.metadata.resourcePublished": "",
|
|
525
526
|
"record.metadata.resourceUpdated": "",
|
package/translations/sk.json
CHANGED
|
@@ -520,6 +520,7 @@
|
|
|
520
520
|
"record.metadata.quality.updateFrequency.failed": "Frekvencia aktualizácie nie je určená",
|
|
521
521
|
"record.metadata.quality.updateFrequency.success": "Frekvencia aktualizácie je určená",
|
|
522
522
|
"record.metadata.related": "Súvisiace záznamy",
|
|
523
|
+
"record.metadata.resource.contacts": "Kontakty k zdroju",
|
|
523
524
|
"record.metadata.resourceCreated": "",
|
|
524
525
|
"record.metadata.resourcePublished": "",
|
|
525
526
|
"record.metadata.resourceUpdated": "",
|