geonetwork-ui 2.4.0-dev.ac57b75b → 2.4.0-dev.b0bcda82

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.
Files changed (80) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/xml-utils.mjs +5 -3
  2. package/esm2022/libs/common/domain/src/lib/model/record/contact.model.mjs +28 -1
  3. package/esm2022/libs/feature/editor/src/lib/components/contact-card/contact-card.component.mjs +29 -0
  4. package/esm2022/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.mjs +17 -24
  5. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.mjs +170 -0
  6. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-keywords/form-field-keywords.component.mjs +3 -3
  7. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.mjs +47 -0
  8. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +17 -3
  9. package/esm2022/libs/feature/editor/src/lib/components/record-form/record-form.component.mjs +3 -4
  10. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +19 -2
  11. package/esm2022/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.mjs +3 -3
  12. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +6 -1
  13. package/esm2022/libs/ui/elements/src/lib/sortable-list/sortable-list.component.mjs +2 -1
  14. package/esm2022/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.mjs +19 -5
  15. package/esm2022/libs/ui/inputs/src/lib/image-input/image-input.component.mjs +5 -11
  16. package/esm2022/translations/de.json +25 -0
  17. package/esm2022/translations/en.json +25 -0
  18. package/esm2022/translations/es.json +25 -0
  19. package/esm2022/translations/fr.json +26 -1
  20. package/esm2022/translations/it.json +25 -0
  21. package/esm2022/translations/nl.json +25 -0
  22. package/esm2022/translations/pt.json +25 -0
  23. package/fesm2022/geonetwork-ui.mjs +546 -49
  24. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  25. package/libs/common/domain/src/lib/model/record/contact.model.d.ts +1 -0
  26. package/libs/common/domain/src/lib/model/record/contact.model.d.ts.map +1 -1
  27. package/libs/feature/editor/src/lib/components/contact-card/contact-card.component.d.ts +12 -0
  28. package/libs/feature/editor/src/lib/components/contact-card/contact-card.component.d.ts.map +1 -0
  29. package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts +1 -1
  30. package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts.map +1 -1
  31. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.d.ts +47 -0
  32. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.d.ts.map +1 -0
  33. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.d.ts +17 -0
  34. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.d.ts.map +1 -0
  35. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +4 -0
  36. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  37. package/libs/feature/editor/src/lib/components/record-form/record-form.component.d.ts.map +1 -1
  38. package/libs/feature/editor/src/lib/fields.config.d.ts +6 -0
  39. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  40. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts.map +1 -1
  41. package/libs/ui/elements/src/lib/sortable-list/sortable-list.component.d.ts +1 -2
  42. package/libs/ui/elements/src/lib/sortable-list/sortable-list.component.d.ts.map +1 -1
  43. package/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.d.ts +9 -1
  44. package/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.d.ts.map +1 -1
  45. package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts +2 -4
  46. package/libs/ui/inputs/src/lib/image-input/image-input.component.d.ts.map +1 -1
  47. package/package.json +1 -1
  48. package/src/libs/api/metadata-converter/src/lib/xml-utils.ts +5 -5
  49. package/src/libs/common/domain/src/lib/model/record/contact.model.ts +28 -0
  50. package/src/libs/feature/editor/src/lib/components/contact-card/contact-card.component.css +0 -0
  51. package/src/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html +25 -0
  52. package/src/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts +30 -0
  53. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.html +0 -1
  54. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.ts +18 -23
  55. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.css +0 -0
  56. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html +76 -0
  57. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts +271 -0
  58. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-keywords/form-field-keywords.component.html +1 -1
  59. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.css +0 -0
  60. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.html +6 -0
  61. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-open-data/form-field-open-data.component.ts +59 -0
  62. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +12 -1
  63. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +17 -0
  64. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.html +1 -1
  65. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +0 -1
  66. package/src/libs/feature/editor/src/lib/fields.config.ts +20 -1
  67. package/src/libs/feature/search/src/lib/fuzzy-search/fuzzy-search.component.html +1 -1
  68. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +12 -0
  69. package/src/libs/ui/elements/src/lib/sortable-list/sortable-list.component.ts +2 -2
  70. package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +15 -3
  71. package/src/libs/ui/inputs/src/lib/image-input/image-input.component.html +1 -1
  72. package/src/libs/ui/inputs/src/lib/image-input/image-input.component.ts +2 -7
  73. package/translations/de.json +25 -0
  74. package/translations/en.json +25 -0
  75. package/translations/es.json +25 -0
  76. package/translations/fr.json +26 -1
  77. package/translations/it.json +25 -0
  78. package/translations/nl.json +25 -0
  79. package/translations/pt.json +25 -0
  80. package/translations/sk.json +25 -0
@@ -0,0 +1,76 @@
1
+ <div class="flex flex-col gap-3">
2
+ <div class="flex flex-row flex-wrap gap-2" data-test="rolesToPick">
3
+ <ng-container *ngFor="let role of rolesToPick">
4
+ <gn-ui-button
5
+ extraClass="px-2 py-1.5"
6
+ (buttonClick)="addRoleToDisplay(role)"
7
+ >
8
+ <div class="flex flex-row gap-1 items-center">
9
+ <span class="text-primary text-[20px] leading-[0] font-bold pb-[5px]"
10
+ >&#8330;</span
11
+ >
12
+ <span class="font-bold" translate>{{ roleToLabel(role) }}</span>
13
+ </div>
14
+ </gn-ui-button>
15
+ </ng-container>
16
+ </div>
17
+ <div
18
+ class="mt-8"
19
+ *ngIf="
20
+ roleSectionsToDisplay && roleSectionsToDisplay.length > 0;
21
+ else noContact
22
+ "
23
+ data-test="displayedRoles"
24
+ >
25
+ <div
26
+ *ngFor="
27
+ let role of roleSectionsToDisplay;
28
+ let index = index;
29
+ let isLast = last
30
+ "
31
+ class="flex flex-col gap-4"
32
+ >
33
+ <div class="flex flex-row justify-between">
34
+ <span class="font-bold text-base" translate>{{
35
+ roleToLabel(role)
36
+ }}</span>
37
+ </div>
38
+
39
+ <gn-ui-autocomplete
40
+ [placeholder]="'Choose a contact'"
41
+ [action]="autoCompleteAction"
42
+ (itemSelected)="addContact($event, role)"
43
+ [displayWithFn]="displayWithFn"
44
+ [minCharacterCount]="1"
45
+ [clearOnSelection]="true"
46
+ >
47
+ </gn-ui-autocomplete>
48
+
49
+ <ng-container *ngIf="contactsForRessourceByRole.get(role) as contacts">
50
+ <ng-container *ngIf="contacts.length > 1">
51
+ <gn-ui-sortable-list
52
+ [elements]="contactsAsDynElemByRole.get(role)"
53
+ (elementsChange)="handleContactsChanged($event)"
54
+ ></gn-ui-sortable-list>
55
+ </ng-container>
56
+ <ng-container *ngIf="contacts.length === 1">
57
+ <ng-container *ngFor="let contact of contacts">
58
+ <gn-ui-contact-card
59
+ [contact]="contact"
60
+ (contactRemoved)="removeContact(index)"
61
+ ></gn-ui-contact-card> </ng-container
62
+ ></ng-container>
63
+ </ng-container>
64
+
65
+ <hr class="border-t-[#D6D3D1] mt-4 mb-6" *ngIf="!isLast" />
66
+ </div>
67
+ </div>
68
+ <ng-template #noContact>
69
+ <div
70
+ class="p-4 border border-primary bg-primary-lightest rounded-lg"
71
+ translate
72
+ >
73
+ editor.record.form.field.contactsForResource.noContact
74
+ </div>
75
+ </ng-template>
76
+ </div>
@@ -0,0 +1,271 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ ChangeDetectorRef,
5
+ Component,
6
+ Input,
7
+ OnDestroy,
8
+ OnInit,
9
+ } from '@angular/core'
10
+ import { FormControl } from '@angular/forms'
11
+ import {
12
+ AutocompleteComponent,
13
+ DropdownSelectorComponent,
14
+ UiInputsModule,
15
+ } from '../../../../../../../../../libs/ui/inputs/src'
16
+ import { UiWidgetsModule } from '../../../../../../../../../libs/ui/widgets/src'
17
+ import {
18
+ Individual,
19
+ Organization,
20
+ Role,
21
+ RoleLabels,
22
+ } from '../../../../../../../../../libs/common/domain/src/lib/model/record'
23
+ import { TranslateModule } from '@ngx-translate/core'
24
+ import {
25
+ debounceTime,
26
+ distinctUntilChanged,
27
+ firstValueFrom,
28
+ Observable,
29
+ Subscription,
30
+ switchMap,
31
+ } from 'rxjs'
32
+ import { UserModel } from '../../../../../../../../../libs/common/domain/src/lib/model/user'
33
+ import { PlatformServiceInterface } from '../../../../../../../../../libs/common/domain/src/lib/platform.service.interface'
34
+ import { OrganizationsServiceInterface } from '../../../../../../../../../libs/common/domain/src/lib/organizations.service.interface'
35
+ import { ContactCardComponent } from '../../../contact-card/contact-card.component'
36
+ import {
37
+ DynamicElement,
38
+ SortableListComponent,
39
+ } from '../../../../../../../../../libs/ui/elements/src'
40
+ import { createFuzzyFilter } from '../../../../../../../../../libs/util/shared/src'
41
+ import { map } from 'rxjs/operators'
42
+
43
+ @Component({
44
+ selector: 'gn-ui-form-field-contacts-for-resource',
45
+ templateUrl: './form-field-contacts-for-resource.component.html',
46
+ styleUrls: ['./form-field-contacts-for-resource.component.css'],
47
+ changeDetection: ChangeDetectionStrategy.OnPush,
48
+ standalone: true,
49
+ imports: [
50
+ DropdownSelectorComponent,
51
+ UiInputsModule,
52
+ CommonModule,
53
+ UiWidgetsModule,
54
+ AutocompleteComponent,
55
+ TranslateModule,
56
+ ContactCardComponent,
57
+ SortableListComponent,
58
+ ],
59
+ })
60
+ export class FormFieldContactsForResourceComponent
61
+ implements OnInit, OnDestroy
62
+ {
63
+ @Input() control: FormControl<Individual[]>
64
+
65
+ subscription: Subscription = new Subscription()
66
+
67
+ allUsers$: Observable<UserModel[]>
68
+
69
+ contactsForRessourceByRole: Map<Role, Individual[]> = new Map()
70
+
71
+ contactsAsDynElemByRole: Map<Role, DynamicElement[]> = new Map()
72
+
73
+ rolesToPick: Role[] = [
74
+ 'resource_provider',
75
+ 'custodian',
76
+ 'owner',
77
+ 'point_of_contact',
78
+ 'author',
79
+ ]
80
+
81
+ roleSectionsToDisplay: Role[] = []
82
+
83
+ allOrganizations: Map<string, Organization> = new Map()
84
+
85
+ constructor(
86
+ private platformServiceInterface: PlatformServiceInterface,
87
+ private organizationsServiceInterface: OrganizationsServiceInterface,
88
+ private changeDetectorRef: ChangeDetectorRef
89
+ ) {
90
+ this.allUsers$ = this.platformServiceInterface.getUsers()
91
+ }
92
+
93
+ async ngOnInit(): Promise<void> {
94
+ this.allOrganizations = new Map<string, Organization>(
95
+ (
96
+ await firstValueFrom(this.organizationsServiceInterface.organisations$)
97
+ ).map((organization) => [organization.name, organization])
98
+ )
99
+ this.updateContactsForRessource()
100
+ this.manageRoleSectionsToDisplay(this.control.value)
101
+ this.filterRolesToPick()
102
+
103
+ this.changeDetectorRef.markForCheck()
104
+
105
+ this.subscription.add(
106
+ this.control.valueChanges.subscribe((contactsForResource) => {
107
+ this.updateContactsForRessource()
108
+ this.manageRoleSectionsToDisplay(contactsForResource)
109
+ this.filterRolesToPick()
110
+
111
+ this.changeDetectorRef.markForCheck()
112
+ })
113
+ )
114
+ }
115
+
116
+ addRoleToDisplay(roleToAdd: string) {
117
+ this.roleSectionsToDisplay.push(roleToAdd)
118
+ this.filterRolesToPick()
119
+ }
120
+
121
+ filterRolesToPick() {
122
+ this.rolesToPick = this.rolesToPick.filter(
123
+ (role) => !this.roleSectionsToDisplay.includes(role)
124
+ )
125
+ }
126
+
127
+ updateContactsForRessource() {
128
+ this.contactsForRessourceByRole = this.control.value.reduce(
129
+ (acc, contact) => {
130
+ const completeOrganization = this.allOrganizations.get(
131
+ contact.organization.name
132
+ )
133
+
134
+ const updatedContact = {
135
+ ...contact,
136
+ organization:
137
+ completeOrganization ??
138
+ ({ name: contact.organization.name } as Organization),
139
+ }
140
+
141
+ if (!acc.has(contact.role)) {
142
+ acc.set(contact.role, [])
143
+ }
144
+
145
+ acc.get(contact.role).push(updatedContact)
146
+
147
+ return acc
148
+ },
149
+ new Map<Role, Individual[]>()
150
+ )
151
+
152
+ this.contactsAsDynElemByRole = this.control.value.reduce((acc, contact) => {
153
+ const completeOrganization = this.allOrganizations.get(
154
+ contact.organization.name
155
+ )
156
+
157
+ const updatedContact = {
158
+ ...contact,
159
+ organization:
160
+ completeOrganization ??
161
+ ({ name: contact.organization.name } as Organization),
162
+ }
163
+
164
+ const contactAsDynElem = {
165
+ component: ContactCardComponent,
166
+ inputs: {
167
+ contact: updatedContact,
168
+ removable: false,
169
+ },
170
+ } as DynamicElement
171
+
172
+ if (!acc.has(contact.role)) {
173
+ acc.set(contact.role, [])
174
+ }
175
+
176
+ acc.get(contact.role).push(contactAsDynElem)
177
+
178
+ return acc
179
+ }, new Map<Role, DynamicElement[]>())
180
+
181
+ this.changeDetectorRef.markForCheck()
182
+ }
183
+
184
+ manageRoleSectionsToDisplay(contactsForResource: Individual[]) {
185
+ const roles = contactsForResource.map(
186
+ (contact: Individual) => contact.role
187
+ ) as Role[]
188
+
189
+ roles.forEach((role: Role) => {
190
+ if (!this.roleSectionsToDisplay.includes(role)) {
191
+ this.roleSectionsToDisplay.push(role)
192
+ }
193
+ })
194
+ }
195
+
196
+ removeContact(index: number) {
197
+ const newContactsforRessource = this.control.value.filter(
198
+ (_, i) => i !== index
199
+ )
200
+ this.control.setValue(newContactsforRessource)
201
+ }
202
+
203
+ handleContactsChanged(event: DynamicElement[]) {
204
+ const newContactsOrdered = event.map(
205
+ (contactAsDynElem) => contactAsDynElem.inputs['contact']
206
+ ) as Individual[]
207
+
208
+ const role = newContactsOrdered[0].role
209
+
210
+ this.contactsForRessourceByRole.set(role, newContactsOrdered)
211
+
212
+ const newControlValue = Array.from(
213
+ this.contactsForRessourceByRole.values()
214
+ ).flat()
215
+
216
+ this.control.setValue(newControlValue)
217
+ }
218
+
219
+ protected roleToLabel(role: string): string {
220
+ return RoleLabels.get(role)
221
+ }
222
+
223
+ /**
224
+ * gn-ui-autocomplete
225
+ */
226
+ displayWithFn: (user: UserModel) => string = (user) =>
227
+ `${user.name} ${user.surname} ${
228
+ user.organisation ? `(${user.organisation})` : ''
229
+ }`
230
+
231
+ /**
232
+ * gn-ui-autocomplete
233
+ */
234
+ autoCompleteAction = (query: string) => {
235
+ const fuzzyFilter = createFuzzyFilter(query)
236
+ return this.allUsers$.pipe(
237
+ switchMap((users) => [
238
+ users.filter((user) => fuzzyFilter(user.username)),
239
+ ]),
240
+ map((results) => results.slice(0, 10)),
241
+ debounceTime(300),
242
+ distinctUntilChanged()
243
+ )
244
+ }
245
+
246
+ /**
247
+ * gn-ui-autocomplete
248
+ */
249
+ addContact(contact: UserModel, role: string) {
250
+ const newContactsForRessource = {
251
+ firstName: contact.name ?? '',
252
+ lastName: contact.surname ?? '',
253
+ organization:
254
+ this.allOrganizations.get(contact.organisation) ??
255
+ ({ name: contact.organisation } as Organization),
256
+ email: contact.email ?? '',
257
+ role,
258
+ address: '',
259
+ phone: '',
260
+ position: '',
261
+ } as Individual
262
+
263
+ const newControlValue = [...this.control.value, newContactsForRessource]
264
+
265
+ this.control.setValue(newControlValue)
266
+ }
267
+
268
+ ngOnDestroy(): void {
269
+ this.subscription.unsubscribe()
270
+ }
271
+ }
@@ -4,7 +4,7 @@
4
4
  [displayWithFn]="displayWithFn"
5
5
  [action]="autoCompleteAction"
6
6
  (itemSelected)="handleItemSelection($event)"
7
- [clearOnSelection]="true"
7
+ [preventCompleteOnSelection]="true"
8
8
  [minCharacterCount]="0"
9
9
  [allowSubmit]="false"
10
10
  ></gn-ui-autocomplete>
@@ -0,0 +1,6 @@
1
+ <gn-ui-check-toggle
2
+ [label]="'editor.record.form.classification.opendata' | translate"
3
+ [value]="value"
4
+ (toggled)="onOpenDataToggled($event)"
5
+ data-cy="openDataToggle"
6
+ ></gn-ui-check-toggle>
@@ -0,0 +1,59 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ EventEmitter,
5
+ Input,
6
+ OnChanges,
7
+ OnInit,
8
+ Output,
9
+ SimpleChanges,
10
+ } from '@angular/core'
11
+ import { FormControl } from '@angular/forms'
12
+ import { CheckToggleComponent } from '../../../../../../../../../libs/ui/inputs/src'
13
+ import { TranslateModule } from '@ngx-translate/core'
14
+ import { OPEN_DATA_LICENSES } from './../../../../fields.config'
15
+ import { Subscription } from 'rxjs'
16
+
17
+ @Component({
18
+ selector: 'gn-ui-form-field-open-data',
19
+ templateUrl: './form-field-open-data.component.html',
20
+ styleUrls: ['./form-field-open-data.component.css'],
21
+ standalone: true,
22
+ imports: [CheckToggleComponent, TranslateModule],
23
+ changeDetection: ChangeDetectionStrategy.OnPush,
24
+ })
25
+ export class FormFieldOpenDataComponent implements OnInit {
26
+ @Input() control: FormControl
27
+ value = false
28
+ @Output() visibilityChange = new EventEmitter<boolean>()
29
+ subscription: Subscription
30
+
31
+ get config() {
32
+ return OPEN_DATA_LICENSES
33
+ }
34
+
35
+ ngOnInit() {
36
+ this.initToggle()
37
+ this.subscription = new Subscription()
38
+
39
+ this.subscription.add(
40
+ this.control.valueChanges.subscribe((value) => {
41
+ this.value = this.config.includes(value[0].text)
42
+ this.visibilityChange.emit(this.value)
43
+ })
44
+ )
45
+ }
46
+
47
+ initToggle() {
48
+ this.value = this.config.includes(this.control.value[0].text)
49
+ this.visibilityChange.emit(this.value)
50
+ }
51
+
52
+ onOpenDataToggled(boolean) {
53
+ if (boolean) {
54
+ this.control.setValue([{ text: this.config[0] }])
55
+ }
56
+ this.value = !this.value
57
+ this.visibilityChange.emit(boolean)
58
+ }
59
+ }
@@ -1,4 +1,10 @@
1
- <div class="flex flex-col h-full">
1
+ <ng-container *ngIf="isOpenData">
2
+ <gn-ui-form-field-open-data
3
+ [control]="formControl"
4
+ (visibilityChange)="onVisibilityChange($event)"
5
+ ></gn-ui-form-field-open-data>
6
+ </ng-container>
7
+ <div class="flex flex-col h-full" *ngIf="!isHidden">
2
8
  <ng-container *ngIf="withoutWrapper; else withGenericWrapper">
3
9
  <ng-container *ngTemplateOutlet="fieldContent"></ng-container>
4
10
  </ng-container>
@@ -87,4 +93,9 @@
87
93
  [control]="formControl"
88
94
  ></gn-ui-form-field-keywords>
89
95
  </ng-container>
96
+ <ng-container *ngIf="isContactsForResource">
97
+ <gn-ui-form-field-contacts-for-resource
98
+ [control]="formControl"
99
+ ></gn-ui-form-field-contacts-for-resource>
100
+ </ng-container>
90
101
  </ng-template>
@@ -3,6 +3,7 @@ import {
3
3
  ChangeDetectionStrategy,
4
4
  Component,
5
5
  ElementRef,
6
+ EventEmitter,
6
7
  Input,
7
8
  Output,
8
9
  ViewChild,
@@ -32,6 +33,8 @@ import { FormFieldOverviewsComponent } from './form-field-overviews/form-field-o
32
33
  import { map, take } from 'rxjs/operators'
33
34
  import { EditorFacade } from '../../../+state/editor.facade'
34
35
  import { FormFieldConfig } from '../../../models'
36
+ import { FormFieldContactsForResourceComponent } from './form-field-contacts-for-resource/form-field-contacts-for-resource.component'
37
+ import { FormFieldOpenDataComponent } from './form-field-open-data/form-field-open-data.component'
35
38
 
36
39
  @Component({
37
40
  selector: 'gn-ui-form-field',
@@ -59,6 +62,8 @@ import { FormFieldConfig } from '../../../models'
59
62
  FormFieldKeywordsComponent,
60
63
  TranslateModule,
61
64
  FormFieldOverviewsComponent,
65
+ FormFieldContactsForResourceComponent,
66
+ FormFieldOpenDataComponent,
62
67
  ],
63
68
  })
64
69
  export class FormFieldComponent {
@@ -71,6 +76,7 @@ export class FormFieldComponent {
71
76
  }
72
77
 
73
78
  @Output() valueChange: Observable<unknown>
79
+ isHidden = false
74
80
 
75
81
  @ViewChild('titleInput') titleInput: ElementRef
76
82
 
@@ -89,6 +95,10 @@ export class FormFieldComponent {
89
95
  this.titleInput.nativeElement.children[0].focus()
90
96
  }
91
97
 
98
+ onVisibilityChange(visibility: boolean) {
99
+ this.isHidden = visibility
100
+ }
101
+
92
102
  get isTitle() {
93
103
  return this.model === 'title'
94
104
  }
@@ -122,8 +132,15 @@ export class FormFieldComponent {
122
132
  get isKeywords() {
123
133
  return this.model === 'keywords'
124
134
  }
135
+ get isContactsForResource() {
136
+ return this.model === 'contactsForResource'
137
+ }
125
138
 
126
139
  get withoutWrapper() {
127
140
  return this.model === 'title' || this.model === 'abstract'
128
141
  }
142
+
143
+ get isOpenData() {
144
+ return this.model === 'licenses'
145
+ }
129
146
  }
@@ -14,7 +14,7 @@
14
14
  >
15
15
  <div
16
16
  *ngIf="section.labelKey"
17
- class="text-2xl font-petrona text-secondary"
17
+ class="text-2xl font-title text-secondary"
18
18
  translate
19
19
  >
20
20
  {{ section.labelKey }}
@@ -24,7 +24,6 @@ export class RecordFormComponent {
24
24
  if (!model) {
25
25
  return
26
26
  }
27
- console.log(newValue)
28
27
  this.facade.updateRecordField(model, newValue)
29
28
  }
30
29
 
@@ -83,6 +83,13 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
83
83
  },
84
84
  }
85
85
 
86
+ export const CONTACTS_FOR_RESOURCE_FIELD: EditorField = {
87
+ model: 'contactsForResource',
88
+ formFieldConfig: {
89
+ labelKey: '',
90
+ },
91
+ }
92
+
86
93
  export const RECORD_GRAPHICAL_OVERVIEW_FIELD: EditorField = {
87
94
  model: 'overviews',
88
95
  formFieldConfig: {
@@ -157,7 +164,7 @@ export const DATA_MANAGERS_SECTION: EditorSection = {
157
164
  labelKey: marker('editor.record.form.section.dataManagers.label'),
158
165
  descriptionKey: marker('editor.record.form.section.dataManagers.description'),
159
166
  hidden: false,
160
- fields: [],
167
+ fields: [CONTACTS_FOR_RESOURCE_FIELD],
161
168
  }
162
169
 
163
170
  export const DATA_POINT_OF_CONTACT_SECTION: EditorSection = {
@@ -194,3 +201,15 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
194
201
  },
195
202
  ],
196
203
  }
204
+
205
+ /************************************************************
206
+ *************** LICENSES *****************
207
+ ************************************************************
208
+ */
209
+ export const OPEN_DATA_LICENSES: string[] = [
210
+ 'etalab',
211
+ 'etalab-v2',
212
+ 'odbl',
213
+ 'odc-by',
214
+ 'pddl',
215
+ ]
@@ -6,6 +6,6 @@
6
6
  (inputSubmitted)="handleInputSubmission($event)"
7
7
  (inputCleared)="handleInputCleared()"
8
8
  [value]="searchInputValue$ | async"
9
- [clearOnSelection]="true"
9
+ [preventCompleteOnSelection]="true"
10
10
  [autoFocus]="autoFocus"
11
11
  ></gn-ui-autocomplete>
@@ -54,6 +54,18 @@ export class ResultsTableContainerComponent implements OnDestroy {
54
54
  next: () => {
55
55
  this.recordsRepository.clearRecordDraft(uniqueIdentifier)
56
56
  this.searchFacade.requestNewResults()
57
+ this.notificationsService.showNotification(
58
+ {
59
+ type: 'success',
60
+ title: this.translateService.instant(
61
+ 'editor.record.deleteSuccess.title'
62
+ ),
63
+ text: `${this.translateService.instant(
64
+ 'editor.record.deleteSuccess.body'
65
+ )}`,
66
+ },
67
+ 2500
68
+ )
57
69
  },
58
70
  error: (error) => {
59
71
  this.notificationsService.showNotification({
@@ -17,7 +17,7 @@ import {
17
17
  import { MatIconModule } from '@angular/material/icon'
18
18
  import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
19
19
 
20
- type DynamicElement = {
20
+ export type DynamicElement = {
21
21
  component: Type<unknown>
22
22
  inputs: Record<string, unknown>
23
23
  }
@@ -40,7 +40,7 @@ type DynamicElement = {
40
40
  })
41
41
  export class SortableListComponent {
42
42
  @Input() elements: Array<DynamicElement>
43
- @Input() addOptions: Array<{ buttonLabel: string; eventName: string }>
43
+ @Input() addOptions: Array<{ buttonLabel: string; eventName: string }> = []
44
44
  @Output() elementsChange = new EventEmitter<Array<DynamicElement>>()
45
45
  @Output() add = new EventEmitter<string>()
46
46
 
@@ -61,6 +61,7 @@ export class AutocompleteComponent
61
61
  @Input() action: (value: string) => Observable<AutocompleteItem[]>
62
62
  @Input() value?: AutocompleteItem
63
63
  @Input() clearOnSelection = false
64
+ @Input() preventCompleteOnSelection = false
64
65
  @Input() autoFocus = false
65
66
  @Input() minCharacterCount? = 3
66
67
  @Input() allowSubmit = true
@@ -206,13 +207,24 @@ export class AutocompleteComponent
206
207
  this.inputSubmitted.emit(this.inputRef.nativeElement.value)
207
208
  }
208
209
 
210
+ /**
211
+ * This function is triggered when an item is selected in the list of displayed items.
212
+ * If preventCompleteOnSelection is true then the input will be left as entered by the user.
213
+ * If preventCompleteOnSelection is false (by default) then the input will be completed with the item selected by the user.
214
+ * If clearOnSelection is true then the input will be cleared upon selection.
215
+ * @param event
216
+ */
209
217
  handleSelection(event: MatAutocompleteSelectedEvent) {
210
218
  this.cancelEnter = true
211
219
  this.itemSelected.emit(event.option.value)
212
- if (this.clearOnSelection) {
213
- this.lastInputValue$.pipe(first()).subscribe((any) => {
214
- this.inputRef.nativeElement.value = any
220
+ if (this.preventCompleteOnSelection) {
221
+ this.lastInputValue$.pipe(first()).subscribe((lastInputValue) => {
222
+ this.inputRef.nativeElement.value = lastInputValue
215
223
  })
224
+ return
225
+ }
226
+ if (this.clearOnSelection) {
227
+ this.inputRef.nativeElement.value = ''
216
228
  }
217
229
  }
218
230
  }
@@ -51,7 +51,7 @@
51
51
  <div class="w-full h-full flex flex-col gap-2">
52
52
  <label
53
53
  gnUiFilesDrop
54
- class="block flex-1 border-2 border-dashed border-gray-300 rounded-lg p-6 flex flex-col items-center justify-center gap-4 hover:cursor-pointer"
54
+ class="block flex-1 border-2 border-dashed border-gray-300 rounded-lg p-6 flex flex-col items-center justify-center gap-4"
55
55
  (dragFilesOver)="handleDragFilesOver($event)"
56
56
  (dropFiles)="handleDropFiles($event)"
57
57
  >