diff --git a/libs/common/domain/src/lib/model/record/contact.model.ts b/libs/common/domain/src/lib/model/record/contact.model.ts
index ebe025902e..3372fb603c 100644
--- a/libs/common/domain/src/lib/model/record/contact.model.ts
+++ b/libs/common/domain/src/lib/model/record/contact.model.ts
@@ -1,4 +1,5 @@
import { Organization } from './organization.model'
+import { marker } from '@biesbjerg/ngx-translate-extract-marker'
export const RoleValues = [
'unspecified',
@@ -24,6 +25,39 @@ export const RoleValues = [
'user', // Party who uses the resource
]
+export const RoleLabels = new Map([
+ ['unspecified', marker('metadata.contactForResource.role.unspecified')],
+ ['other', marker('metadata.contactForResource.role.other')],
+ ['author', marker('metadata.contactForResource.role.author')],
+ ['collaborator', marker('metadata.contactForResource.role.collaborator')],
+ ['contributor', marker('metadata.contactForResource.role.contributor')],
+ ['custodian', marker('metadata.contactForResource.role.custodian')],
+ ['distributor', marker('metadata.contactForResource.role.distributor')],
+ ['editor', marker('metadata.contactForResource.role.editor')],
+ ['funder', marker('metadata.contactForResource.role.funder')],
+ ['mediator', marker('metadata.contactForResource.role.mediator')],
+ ['originator', marker('metadata.contactForResource.role.originator')],
+ ['owner', marker('metadata.contactForResource.role.owner')],
+ [
+ 'point_of_contact',
+ marker('metadata.contactForResource.role.point_of_contact'),
+ ],
+ [
+ 'principal_investigator',
+ marker('metadata.contactForResource.role.principal_investigator'),
+ ],
+ ['processor', marker('metadata.contactForResource.role.processor')],
+ ['publisher', marker('metadata.contactForResource.role.publisher')],
+ [
+ 'resource_provider',
+ marker('metadata.contactForResource.role.resource_provider'),
+ ],
+ ['rights_holder', marker('metadata.contactForResource.role.rights_holder')],
+ ['sponsor', marker('metadata.contactForResource.role.sponsor')],
+ ['stakeholder', marker('metadata.contactForResource.role.stakeholder')],
+ ['user', marker('metadata.contactForResource.role.user')],
+])
+
export type Role = typeof RoleValues[number]
export interface Individual {
diff --git a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.css b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.css
similarity index 100%
rename from libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.css
rename to libs/feature/editor/src/lib/components/contact-card/contact-card.component.css
diff --git a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.html b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html
similarity index 92%
rename from libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.html
rename to libs/feature/editor/src/lib/components/contact-card/contact-card.component.html
index ac23076b16..849b22ef30 100644
--- a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.html
+++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html
@@ -9,7 +9,8 @@
>{{ contact.firstName }} {{ contact.lastName }}
✕
diff --git a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.spec.ts b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.spec.ts
new file mode 100644
index 0000000000..1ce24cb81e
--- /dev/null
+++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.spec.ts
@@ -0,0 +1,78 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing'
+import { ContactCardComponent } from './contact-card.component'
+import {
+ Individual,
+ Organization,
+} from '@geonetwork-ui/common/domain/model/record'
+import { MatIconModule } from '@angular/material/icon'
+import { CommonModule } from '@angular/common'
+import { ButtonComponent } from '@geonetwork-ui/ui/inputs'
+
+describe('ContactCardComponent', () => {
+ let component: ContactCardComponent
+ let fixture: ComponentFixture
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ CommonModule,
+ MatIconModule,
+ ButtonComponent,
+ ContactCardComponent,
+ ],
+ }).compileComponents()
+ })
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ContactCardComponent)
+ component = fixture.componentInstance
+ fixture.detectChanges()
+ })
+
+ it('should create the component', () => {
+ expect(component).toBeTruthy()
+ })
+
+ it('should have a defined contact input', () => {
+ const mockContact: Individual = {
+ firstName: 'John',
+ lastName: 'Doe',
+ organization: { name: 'Org1' } as Organization,
+ email: 'john.doe@example.com',
+ role: 'admin',
+ address: '',
+ phone: '',
+ position: '',
+ }
+ component.contact = mockContact
+ fixture.detectChanges()
+ expect(component.contact).toEqual(mockContact)
+ })
+
+ it('should have a defined organization input', () => {
+ const mockOrganization: Organization = {
+ name: 'Org1',
+ }
+ component.organization = mockOrganization
+ fixture.detectChanges()
+ expect(component.organization).toEqual(mockOrganization)
+ })
+
+ it('should emit contactRemoved event with the correct contact', () => {
+ const mockContact: Individual = {
+ firstName: 'John',
+ lastName: 'Doe',
+ organization: { name: 'Org1' } as Organization,
+ email: 'john.doe@example.com',
+ role: 'admin',
+ address: '',
+ phone: '',
+ position: '',
+ }
+ component.contact = mockContact
+
+ const contactRemovedSpy = jest.spyOn(component.contactRemoved, 'emit')
+ component.removeContact(mockContact)
+ expect(contactRemovedSpy).toHaveBeenCalledWith(mockContact)
+ })
+})
diff --git a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.stories.ts b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.stories.ts
new file mode 100644
index 0000000000..3c75b032e8
--- /dev/null
+++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.stories.ts
@@ -0,0 +1,54 @@
+import {
+ applicationConfig,
+ componentWrapperDecorator,
+ Meta,
+ moduleMetadata,
+ StoryObj,
+} from '@storybook/angular'
+import { ContactCardComponent } from './contact-card.component'
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
+import { importProvidersFrom } from '@angular/core'
+import { MatIconModule } from '@angular/material/icon'
+import { CommonModule } from '@angular/common'
+import { ButtonComponent } from '@geonetwork-ui/ui/inputs'
+
+export default {
+ title: 'Elements/ContactCardComponent',
+ component: ContactCardComponent,
+ decorators: [
+ moduleMetadata({
+ imports: [
+ CommonModule,
+ MatIconModule,
+ ButtonComponent,
+ ContactCardComponent,
+ ],
+ }),
+ applicationConfig({
+ providers: [importProvidersFrom(BrowserAnimationsModule)],
+ }),
+ componentWrapperDecorator(
+ (story) => `${story}
`
+ ),
+ ],
+} as Meta
+
+export const Primary: StoryObj = {
+ args: {
+ contact: {
+ firstName: 'John',
+ lastName: 'Doe',
+ organization: {
+ name: 'Example Organization',
+ },
+ email: 'john.doe@example.com',
+ role: 'Developer',
+ address: '123 Main St',
+ phone: '123-456-7890',
+ position: 'Senior Developer',
+ },
+ organization: {
+ name: 'Example Organization',
+ },
+ },
+}
diff --git a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.ts b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts
similarity index 78%
rename from libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.ts
rename to libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts
index b919d8e7a7..a178564f4b 100644
--- a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.ts
+++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts
@@ -14,14 +14,14 @@ import { CommonModule } from '@angular/common'
import { ButtonComponent } from '@geonetwork-ui/ui/inputs'
@Component({
- selector: 'gn-ui-editor-contact-card',
- templateUrl: './editor-contact-card.component.html',
- styleUrls: ['./editor-contact-card.component.css'],
+ selector: 'gn-ui-contact-card',
+ templateUrl: './contact-card.component.html',
+ styleUrls: ['./contact-card.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, MatIconModule, ButtonComponent],
})
-export class EditorContactCardComponent {
+export class ContactCardComponent {
@Input() contact: Individual
@Input() organization: Organization
@Output() contactRemoved = new EventEmitter()
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.css b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html
new file mode 100644
index 0000000000..530521aa53
--- /dev/null
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+ ₊
+ {{ roleToLabel(role) }}
+
+
+
+
+
0"
+ data-test="displayedRoles"
+ >
+
+
+ {{
+ roleToLabel(role)
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.spec.ts
new file mode 100644
index 0000000000..680de56f29
--- /dev/null
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.spec.ts
@@ -0,0 +1,181 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing'
+import { FormFieldContactsForResourceComponent } from './form-field-contacts-for-resource.component'
+import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
+import { BehaviorSubject } from 'rxjs'
+import {
+ Individual,
+ Organization,
+} from '@geonetwork-ui/common/domain/model/record'
+import { ChangeDetectorRef, SimpleChanges } from '@angular/core'
+import { UserModel } from '@geonetwork-ui/common/domain/model/user'
+import { CommonModule } from '@angular/common'
+import { TranslateModule } from '@ngx-translate/core'
+import { ContactCardComponent } from '../../../contact-card/contact-card.component'
+import {
+ DropdownSelectorComponent,
+ UiInputsModule,
+} from '@geonetwork-ui/ui/inputs'
+import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
+import { FormControl } from '@angular/forms'
+
+const organizationBarbie: Organization = {
+ name: 'Barbie Inc.',
+}
+
+const organizationGoogle: Organization = {
+ name: 'Google',
+}
+
+class MockPlatformServiceInterface {
+ getUsers = jest.fn(() => new BehaviorSubject([]))
+}
+
+class MockOrganizationsServiceInterface {
+ organisations$ = new BehaviorSubject([organizationBarbie, organizationGoogle])
+}
+
+describe('FormFieldContactsForResourceComponent', () => {
+ let component: FormFieldContactsForResourceComponent
+ let fixture: ComponentFixture
+
+ const contactJohn: Individual = {
+ firstName: 'John',
+ lastName: 'Doe',
+ organization: { name: 'Org1' } as Organization,
+ email: 'john.doe@example.com',
+ role: 'author',
+ }
+
+ const contactJane: Individual = {
+ firstName: 'John',
+ lastName: 'Doe',
+ organization: { name: 'Org1' } as Organization,
+ email: 'john.doe@example.com',
+ role: 'custodian',
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ FormFieldContactsForResourceComponent,
+ CommonModule,
+ TranslateModule.forRoot(),
+ UiInputsModule,
+ ContactCardComponent,
+ DropdownSelectorComponent,
+ ],
+ providers: [
+ {
+ provide: PlatformServiceInterface,
+ useClass: MockPlatformServiceInterface,
+ },
+ {
+ provide: OrganizationsServiceInterface,
+ useClass: MockOrganizationsServiceInterface,
+ },
+ ChangeDetectorRef,
+ ],
+ }).compileComponents()
+ })
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FormFieldContactsForResourceComponent)
+ component = fixture.componentInstance
+ component.control = new FormControl([])
+ fixture.detectChanges()
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+
+ it('should initialize with default values', () => {
+ expect(component.rolesToPick).toEqual([
+ 'resource_provider',
+ 'custodian',
+ 'owner',
+ 'point_of_contact',
+ 'author',
+ ])
+ expect(component.rolesToDisplay).toEqual([])
+ expect(component.allOrganizations.size).toBe(2)
+ })
+
+ it('should fetch users on initialization', () => {
+ const platformService = TestBed.inject(PlatformServiceInterface)
+ expect(platformService.getUsers).toHaveBeenCalled()
+ })
+
+ it('should subscribe to organizations and update the allOrganizations map', () => {
+ component.ngOnInit()
+ expect(component.allOrganizations.size).toBe(2)
+ expect(component.allOrganizations.get('Barbie Inc.')).toEqual(
+ organizationBarbie
+ )
+ })
+
+ it('should add role to rolesToDisplay and remove from rolesToPick', () => {
+ component.addRoleToDisplay('owner')
+ expect(component.rolesToPick).not.toContain('owner')
+ expect(component.rolesToDisplay).toContain('owner')
+ })
+
+ it('should remove contact by index', () => {
+ component.control.setValue([
+ { firstName: 'John', lastName: 'Doe' } as Individual,
+ ])
+ component.removeContact(0)
+ expect(component.control.value.length).toBe(0)
+ })
+
+ it('should add a new contact with correct data', async () => {
+ const contact = {
+ name: 'John',
+ surname: 'Doe',
+ organisation: 'Org1',
+ email: 'john.doe@example.com',
+ } as UserModel
+ jest
+ .spyOn(component, 'getOrganizationByName')
+ .mockReturnValue({ name: 'Org1' } as Organization)
+ await component.addContact(contact, 'owner')
+ expect(component.control.value.length).toBe(1)
+ expect(component.control.value[0].firstName).toBe('John')
+ expect(component.control.value[0].lastName).toBe('Doe')
+ expect(component.control.value[0].organization.name).toBe('Org1')
+ })
+
+ it('should handle ngOnChanges and update rolesToDisplay', () => {
+ const changes = {
+ control: {
+ currentValue: {
+ value: [contactJane, contactJohn],
+ },
+ previousValue: { value: [] },
+ firstChange: false,
+ },
+ } as unknown as SimpleChanges
+ component.ngOnChanges(changes)
+ expect(component.rolesToDisplay).toEqual([
+ contactJane.role,
+ contactJohn.role,
+ ])
+ })
+
+ it('should return contacts by role', () => {
+ const contacts: Individual[] = [
+ { role: 'owner' } as Individual,
+ { role: 'custodian' } as Individual,
+ { role: 'owner' } as Individual,
+ ]
+ component.control.setValue(contacts)
+ const result = component.getContactsByRole('owner')
+ expect(result.length).toBe(2)
+ })
+
+ it('should return the correct organization by name', () => {
+ const org = { name: 'Org1' } as Organization
+ component.allOrganizations.set('Org1', org)
+ expect(component.getOrganizationByName('Org1')).toBe(org)
+ })
+})
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts
new file mode 100644
index 0000000000..1d84bd24f4
--- /dev/null
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts
@@ -0,0 +1,183 @@
+import { CommonModule } from '@angular/common'
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ Input,
+ OnChanges,
+ OnInit,
+ SimpleChanges,
+} from '@angular/core'
+import { FormControl } from '@angular/forms'
+import {
+ AutocompleteComponent,
+ DropdownSelectorComponent,
+ UiInputsModule,
+} from '@geonetwork-ui/ui/inputs'
+import { UiWidgetsModule } from '@geonetwork-ui/ui/widgets'
+import {
+ Individual,
+ Organization,
+ RoleLabels,
+} from '@geonetwork-ui/common/domain/model/record'
+import { TranslateModule } from '@ngx-translate/core'
+import { debounceTime, distinctUntilChanged, Observable, switchMap } from 'rxjs'
+import { UserModel } from '@geonetwork-ui/common/domain/model/user'
+import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
+import { ContactCardComponent } from '@geonetwork-ui/ui/elements'
+import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
+
+@Component({
+ selector: 'gn-ui-form-field-contacts-for-resource',
+ templateUrl: './form-field-contacts-for-resource.component.html',
+ styleUrls: ['./form-field-contacts-for-resource.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [
+ DropdownSelectorComponent,
+ UiInputsModule,
+ CommonModule,
+ UiWidgetsModule,
+ AutocompleteComponent,
+ TranslateModule,
+ ContactCardComponent,
+ ],
+})
+export class FormFieldContactsForResourceComponent
+ implements OnInit, OnChanges
+{
+ @Input() control: FormControl
+
+ allUser$: Observable
+
+ rolesToPick: string[] = [
+ 'resource_provider',
+ 'custodian',
+ 'owner',
+ 'point_of_contact',
+ 'author',
+ ]
+
+ rolesToDisplay = []
+
+ allOrganizations: Map = new Map()
+
+ constructor(
+ private platformServiceInterface: PlatformServiceInterface,
+ private organizationsServiceInterface: OrganizationsServiceInterface,
+ private changeDetectorRef: ChangeDetectorRef
+ ) {
+ this.allUser$ = this.platformServiceInterface.getUsers()
+ }
+
+ ngOnInit(): void {
+ this.organizationsServiceInterface.organisations$.subscribe(
+ (organizations) => {
+ this.allOrganizations = new Map(
+ organizations.map((organization) => [organization.name, organization])
+ )
+ this.changeDetectorRef.markForCheck()
+ }
+ )
+ }
+
+ addRoleToDisplay(roleToAdd: string) {
+ this.rolesToPick.splice(
+ this.rolesToPick.findIndex((role) => role === roleToAdd),
+ 1
+ )
+ this.rolesToDisplay.push(roleToAdd)
+ }
+
+ removeContact(index: number) {
+ const newContactsforRessource = this.control.value.filter(
+ (_, i) => i !== index
+ )
+ this.control.setValue(newContactsforRessource)
+ }
+
+ protected roleToLabel(role: string): string {
+ return RoleLabels.get(role)
+ }
+
+ /**
+ * gn-ui-autocomplete
+ */
+ displayWithFn: (user: UserModel) => string = (user) =>
+ `${user.name} ${user.surname}`
+
+ /**
+ * gn-ui-autocomplete
+ */
+ autoCompleteAction = (query: string) => {
+ return this.allUser$.pipe(
+ switchMap((users) => [
+ users.filter((user) => user.username.includes(query)),
+ ]),
+ debounceTime(300),
+ distinctUntilChanged()
+ )
+ }
+
+ /**
+ * gn-ui-autocomplete
+ */
+ async addContact(contact: UserModel, role: string) {
+ let newContactsforRessource = {
+ firstName: contact.name ?? '',
+ lastName: contact.surname ?? '',
+ organization: {
+ name: contact.organisation,
+ },
+ email: contact.email ?? '',
+ role,
+ address: '',
+ phone: '',
+ position: '',
+ } as Individual
+
+ const newContactOrganization = this.getOrganizationByName(
+ contact.organisation
+ )
+
+ newContactsforRessource = {
+ ...newContactsforRessource,
+ organization: newContactOrganization,
+ }
+
+ const newControlValue = [...this.control.value, newContactsforRessource]
+
+ this.control.setValue(newControlValue)
+ }
+
+ async ngOnChanges(changes: SimpleChanges): Promise {
+ const contactsForResource = changes['control']
+
+ if (
+ contactsForResource &&
+ contactsForResource.currentValue !== contactsForResource.previousValue
+ ) {
+ const rolesToAdd = contactsForResource.currentValue.value.map(
+ (contact: Individual) => contact.role
+ )
+
+ rolesToAdd.forEach((role: string) => {
+ if (!this.rolesToDisplay.includes(role)) {
+ this.rolesToDisplay.push(role)
+ }
+ })
+
+ this.changeDetectorRef.markForCheck()
+ }
+ }
+
+ getContactsByRole(role: string): Individual[] {
+ return this.control.value.filter((contact: Individual) => {
+ return contact.role === role
+ })
+ }
+
+ getOrganizationByName(name: string): Organization {
+ return this.allOrganizations.get(name)
+ }
+}
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
index 5ac61e653d..33b31e74ef 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
@@ -81,4 +81,9 @@
[control]="formControl"
>
+
+
+
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.spec.ts
index 6337d1d9b3..0747f0eefa 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.spec.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.spec.ts
@@ -10,6 +10,28 @@ import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/for
import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
import { FormFieldComponent } from './form-field.component'
import { FormFieldTemporalExtentsComponent } from './form-field-temporal-extents/form-field-temporal-extents.component'
+import { FormFieldContactsForResourceComponent } from './form-field-contacts-for-resource/form-field-contacts-for-resource.component'
+import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
+import { NO_ERRORS_SCHEMA } from '@angular/core'
+import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
+import { BehaviorSubject } from 'rxjs'
+import { Organization } from '@geonetwork-ui/common/domain/model/record'
+
+const organizationBarbie: Organization = {
+ name: 'Barbie Inc.',
+}
+
+const organizationGoogle: Organization = {
+ name: 'Google',
+}
+
+class MockPlatformService {
+ getUsers = jest.fn(() => new BehaviorSubject([]))
+}
+
+class MockOrganizationsService {
+ organisations$ = new BehaviorSubject([organizationBarbie, organizationGoogle])
+}
describe('FormFieldComponent', () => {
let component: FormFieldComponent
@@ -18,7 +40,16 @@ describe('FormFieldComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormFieldComponent, TranslateModule.forRoot()],
- }).compileComponents()
+ providers: [
+ { provide: PlatformServiceInterface, useClass: MockPlatformService },
+ {
+ provide: OrganizationsServiceInterface,
+ useClass: MockOrganizationsService,
+ },
+ ],
+ schemas: [NO_ERRORS_SCHEMA],
+ })
+ .compileComponents()
fixture = TestBed.createComponent(FormFieldComponent)
component = fixture.componentInstance
@@ -149,4 +180,17 @@ describe('FormFieldComponent', () => {
expect(formField).toBeTruthy()
})
})
+ describe('contacts for resource field', () => {
+ let formField
+ beforeEach(() => {
+ component.model = 'contactsForResource'
+ fixture.detectChanges()
+ formField = fixture.debugElement.query(
+ By.directive(FormFieldContactsForResourceComponent)
+ ).componentInstance
+ })
+ it('creates a contacts for resource field', () => {
+ expect(formField).toBeTruthy()
+ })
+ })
})
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
index 44621437a5..ca0c01259a 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
@@ -29,6 +29,7 @@ import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency
import { CatalogRecordKeys } from '@geonetwork-ui/common/domain/model/record'
import { FormFieldKeywordsComponent } from './form-field-keywords/form-field-keywords.component'
import { FormFieldConfig } from '../../../models'
+import { FormFieldContactsForResourceComponent } from './form-field-contacts-for-resource/form-field-contacts-for-resource.component'
@Component({
selector: 'gn-ui-form-field',
@@ -55,6 +56,7 @@ import { FormFieldConfig } from '../../../models'
FormFieldArrayComponent,
FormFieldKeywordsComponent,
TranslateModule,
+ FormFieldContactsForResourceComponent,
],
})
export class FormFieldComponent {
@@ -110,6 +112,9 @@ export class FormFieldComponent {
get isKeywords() {
return this.model === 'keywords'
}
+ get isContactsForResource() {
+ return this.model === 'contactsForResource'
+ }
get withoutWrapper() {
return this.model === 'title' || this.model === 'abstract'
diff --git a/libs/feature/editor/src/lib/components/record-form/record-form.component.html b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
index 277b79d049..208206241e 100644
--- a/libs/feature/editor/src/lib/components/record-form/record-form.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
@@ -14,7 +14,7 @@
>
{{ section.labelKey }}
diff --git a/libs/feature/editor/src/lib/fields.config.ts b/libs/feature/editor/src/lib/fields.config.ts
index 8c22644b48..57bd3626f1 100644
--- a/libs/feature/editor/src/lib/fields.config.ts
+++ b/libs/feature/editor/src/lib/fields.config.ts
@@ -83,6 +83,14 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
},
}
+export const CONTACTS_FOR_RESOURCE_FIELD: EditorField = {
+ model: 'contactsForResource',
+ formFieldConfig: {
+ // labelKey: marker('editor.record.form.field.contactsForResource')
+ labelKey: '',
+ },
+}
+
/************************************************************
*************** SECTIONS *****************
************************************************************
@@ -146,7 +154,7 @@ export const DATA_MANAGERS_SECTION: EditorSection = {
labelKey: marker('editor.record.form.section.dataManagers.label'),
descriptionKey: marker('editor.record.form.section.dataManagers.description'),
hidden: false,
- fields: [],
+ fields: [CONTACTS_FOR_RESOURCE_FIELD],
}
export const DATA_POINT_OF_CONTACT_SECTION: EditorSection = {
diff --git a/libs/ui/elements/src/index.ts b/libs/ui/elements/src/index.ts
index 15ee8b6cb3..10008ff8e2 100644
--- a/libs/ui/elements/src/index.ts
+++ b/libs/ui/elements/src/index.ts
@@ -3,7 +3,7 @@ export * from './lib/avatar/avatar.component'
export * from './lib/content-ghost/content-ghost.component'
export * from './lib/download-item/download-item.component'
export * from './lib/downloads-list/downloads-list.component'
-export * from './lib/editor-contact-card/editor-contact-card.component'
+export * from '../../../feature/editor/src/lib/components/contact-card/contact-card.component'
export * from './lib/error/error.component'
export * from './lib/image-overlay-preview/image-overlay-preview.component'
export * from './lib/link-card/link-card.component'
diff --git a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.spec.ts b/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.spec.ts
deleted file mode 100644
index 90e0e6e922..0000000000
--- a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.spec.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { NO_ERRORS_SCHEMA } from '@angular/core'
-import { ComponentFixture, TestBed } from '@angular/core/testing'
-import { EditorContactCardComponent } from './editor-contact-card.component'
-
-describe('LinkCardComponent', () => {
- let component: EditorContactCardComponent
- let fixture: ComponentFixture
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- schemas: [NO_ERRORS_SCHEMA],
- imports: [EditorContactCardComponent],
- }).compileComponents()
- })
-
- beforeEach(() => {
- fixture = TestBed.createComponent(EditorContactCardComponent)
- component = fixture.componentInstance
- component.link = {
- name: 'Consulter sur Géoclip',
- description:
- 'Lorem ipsum dolor sit amet, consect etur adipiscing elit. Donec id condim entum ex. Etiam sed molestie est.',
- url: new URL('https://example.com/someurlpath'),
- type: 'link',
- }
- fixture.detectChanges()
- })
-
- it('should create', () => {
- expect(component).toBeTruthy()
- })
-})
diff --git a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.stories.ts b/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.stories.ts
deleted file mode 100644
index d4ddcde93d..0000000000
--- a/libs/ui/elements/src/lib/editor-contact-card/editor-contact-card.component.stories.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import {
- applicationConfig,
- componentWrapperDecorator,
- Meta,
- moduleMetadata,
- StoryObj,
-} from '@storybook/angular'
-import { EditorContactCardComponent } from './editor-contact-card.component'
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
-import { importProvidersFrom } from '@angular/core'
-
-export default {
- title: 'Elements/LinkCardComponent',
- component: EditorContactCardComponent,
- decorators: [
- moduleMetadata({
- imports: [EditorContactCardComponent],
- }),
- applicationConfig({
- providers: [importProvidersFrom(BrowserAnimationsModule)],
- }),
- componentWrapperDecorator(
- (story) => `${story}
`
- ),
- ],
-} as Meta
-
-export const Primary: StoryObj = {
- args: {
- compact: false,
- link: {
- type: 'link',
- name: 'Consulter sur Géoclip',
- description:
- 'Lorem ipsum dolor sit amet, consect etur adipiscing elit. Donec id condim entum ex. Etiam sed molestie est.',
- url: new URL('https://example.com/someurlpath'),
- },
- },
-}
diff --git a/libs/ui/elements/src/lib/ui-elements.module.ts b/libs/ui/elements/src/lib/ui-elements.module.ts
index 6897aaef22..274cbc06fe 100644
--- a/libs/ui/elements/src/lib/ui-elements.module.ts
+++ b/libs/ui/elements/src/lib/ui-elements.module.ts
@@ -31,7 +31,6 @@ import { MarkdownParserComponent } from './markdown-parser/markdown-parser.compo
import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-overlay-preview.component'
import { UserFeedbackItemComponent } from './user-feedback-item/user-feedback-item.component'
import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
-import { EditorContactCardComponent } from './editor-contact-card/editor-contact-card.component'
@NgModule({
imports: [
@@ -51,7 +50,6 @@ import { EditorContactCardComponent } from './editor-contact-card/editor-contact
TimeSincePipe,
BadgeComponent,
MaxLinesComponent,
- EditorContactCardComponent,
],
declarations: [
MetadataInfoComponent,
@@ -79,7 +77,6 @@ import { EditorContactCardComponent } from './editor-contact-card/editor-contact
ContentGhostComponent,
DownloadItemComponent,
DownloadsListComponent,
- EditorContactCardComponent,
ApiCardComponent,
RelatedRecordCardComponent,
MetadataContactComponent,
diff --git a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
index 138118521c..847aedbfed 100644
--- a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
+++ b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.spec.ts
@@ -302,7 +302,6 @@ describe('AutocompleteComponent', () => {
}
describe('when true', () => {
beforeEach(() => {
- component.clearOnSelection = true
component.itemSelected.subscribe((event) => (selectionEmitted = event))
fixture.detectChanges()
component.handleSelection(selectionEvent)
@@ -313,8 +312,11 @@ describe('AutocompleteComponent', () => {
it('emits selection event', () => {
expect(selectionEmitted).toEqual('first')
})
- describe('if clear on selection', () => {
+ describe('if completeOnSelection on selection', () => {
it('set input value to last entered text', () => {
+ component.clearOnSelection = false
+ component.completeOnSelection = true
+
component.control.setValue('second')
component.handleSelection(selectionEvent)
expect(component.inputRef.nativeElement.value).toEqual('second')
@@ -323,6 +325,16 @@ describe('AutocompleteComponent', () => {
expect(component.inputRef.nativeElement.value).toEqual('second')
})
})
+ describe('if clearOnSelection on selection', () => {
+ it('set input value to empty string', () => {
+ component.clearOnSelection = true
+ component.completeOnSelection = false
+
+ component.control.setValue('second')
+ component.handleSelection(selectionEvent)
+ expect(component.inputRef.nativeElement.value).toEqual('')
+ })
+ })
})
})
diff --git a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
index 02761e908d..3e5efe0d8a 100644
--- a/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
+++ b/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts
@@ -61,6 +61,7 @@ export class AutocompleteComponent
@Input() action: (value: string) => Observable
@Input() value?: AutocompleteItem
@Input() clearOnSelection = false
+ @Input() completeOnSelection = false
@Input() autoFocus = false
@Input() minCharacterCount? = 3
@Input() allowSubmit = true
@@ -209,10 +210,14 @@ export class AutocompleteComponent
handleSelection(event: MatAutocompleteSelectedEvent) {
this.cancelEnter = true
this.itemSelected.emit(event.option.value)
- if (this.clearOnSelection) {
+ if (this.completeOnSelection) {
this.lastInputValue$.pipe(first()).subscribe((any) => {
this.inputRef.nativeElement.value = any
})
+ return
+ }
+ if (this.clearOnSelection) {
+ this.inputRef.nativeElement.value = ''
}
}
}
diff --git a/translations/de.json b/translations/de.json
index 8e2341a956..1a485beea4 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -168,18 +168,15 @@
"editor.record.form.bottomButtons.comeBackLater": "",
"editor.record.form.bottomButtons.next": "",
"editor.record.form.bottomButtons.previous": "",
- "editor.record.form.field.abstract": "",
+ "editor.record.form.field.abstract": "Kurzbeschreibung",
"editor.record.form.field.keywords": "Schlagwörter",
"editor.record.form.field.license": "Lizenz",
- "editor.record.form.field.recordUpdated": "",
- "editor.record.form.field.resourceUpdated": "",
- "editor.record.form.field.temporalExtents": "",
+ "editor.record.form.field.recordUpdated": "Datensatz zuletzt aktualisiert",
+ "editor.record.form.field.resourceUpdated": "Letztes Aktualisierungsdatum",
+ "editor.record.form.field.temporalExtents": "Zeitlicher Umfang",
"editor.record.form.field.title": "",
- "editor.record.form.field.uniqueIdentifier": "",
- "editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "Kurzbeschreibung",
- "editor.record.form.keywords": "Schlüsselwörter",
- "editor.record.form.license": "Lizenz",
+ "editor.record.form.field.uniqueIdentifier": "Eindeutige Kennung (ID)",
+ "editor.record.form.field.updateFrequency": "Aktualisierungshäufigkeit",
"editor.record.form.license.cc-by": "Creative Commons CC-BY",
"editor.record.form.license.cc-by-sa": "Creative Commons CC-BY-SA",
"editor.record.form.license.cc-zero": "Creative Commons CC-0",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "Metadaten-Titel",
- "editor.record.form.record.updated": "Datensatz zuletzt aktualisiert",
- "editor.record.form.resourceUpdated": "Letztes Aktualisierungsdatum",
- "editor.record.form.temporalExtents": "Zeitlicher Umfang",
"editor.record.form.temporalExtents.addDate": "Zeitpunkt",
"editor.record.form.temporalExtents.addRange": "Zeitraum",
"editor.record.form.temporalExtents.date": "Datum",
"editor.record.form.temporalExtents.range": "Datumsbereich",
- "editor.record.form.unique.identifier": "Eindeutige Kennung (ID)",
- "editor.record.form.updateFrequency": "Aktualisierungshäufigkeit",
"editor.record.form.updateFrequency.planned": "Die Daten sollten regelmäßig aktualisiert werden.",
"editor.record.loadError.body": "Der Datensatz konnte nicht geladen werden:",
"editor.record.loadError.closeMessage": "Verstanden",
@@ -287,6 +278,27 @@
"map.select.layer": "Datenquelle",
"map.wfs.urlInput.hint": "Geben Sie die WFS URL ein",
"map.wms.urlInput.hint": "Geben Sie die WMS URL ein",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "Suche",
"nav.back": "Zurück",
"next": "weiter",
diff --git a/translations/en.json b/translations/en.json
index b9078b516d..73681ff475 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "Metadata title",
"editor.record.form.field.uniqueIdentifier": "Unique identifier",
"editor.record.form.field.updateFrequency": "Update frequency",
- "editor.record.form.abstract": "Abstract",
- "editor.record.form.keywords": "Keywords",
- "editor.record.form.license": "License",
"editor.record.form.license.cc-by": "Creative Commons CC-BY",
"editor.record.form.license.cc-by-sa": "Creative Commons CC-BY-SA",
"editor.record.form.license.cc-zero": "Creative Commons CC-0",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "Data point of contact",
"editor.record.form.section.geographicalCoverage.label": "Geographical coverage",
"editor.record.form.section.useAndAccessConditions.label": "Use and access conditions",
- "editor.record.form.metadata.title": "Metadata title",
- "editor.record.form.record.updated": "Record updated",
- "editor.record.form.resourceUpdated": "Last update date",
- "editor.record.form.temporalExtents": "Temporal extent",
"editor.record.form.temporalExtents.addDate": "Time instant",
"editor.record.form.temporalExtents.addRange": "Time period",
"editor.record.form.temporalExtents.date": "Date",
"editor.record.form.temporalExtents.range": "Date range",
- "editor.record.form.unique.identifier": "Unique identifier",
- "editor.record.form.updateFrequency": "Update frequency",
"editor.record.form.updateFrequency.planned": "The data should be updated regularly.",
"editor.record.loadError.body": "The record could not be loaded:",
"editor.record.loadError.closeMessage": "Understood",
@@ -287,6 +278,27 @@
"map.select.layer": "Data source",
"map.wfs.urlInput.hint": "Enter WFS service URL",
"map.wms.urlInput.hint": "Enter WMS service URL",
+ "metadata.contactForResource.role.author": "Author",
+ "metadata.contactForResource.role.collaborator": "Collaborator",
+ "metadata.contactForResource.role.contributor": "Contributor",
+ "metadata.contactForResource.role.custodian": "Custodian",
+ "metadata.contactForResource.role.distributor": "Distributor",
+ "metadata.contactForResource.role.editor": "Editor",
+ "metadata.contactForResource.role.funder": "Funder",
+ "metadata.contactForResource.role.mediator": "Mediator",
+ "metadata.contactForResource.role.originator": "Originator",
+ "metadata.contactForResource.role.other": "Other",
+ "metadata.contactForResource.role.owner": "Owner",
+ "metadata.contactForResource.role.point_of_contact": "Point of contact",
+ "metadata.contactForResource.role.principal_investigator": "Principal investigator",
+ "metadata.contactForResource.role.processor": "Processor",
+ "metadata.contactForResource.role.publisher": "Publisher",
+ "metadata.contactForResource.role.resource_provider": "Resource provider",
+ "metadata.contactForResource.role.rights_holder": "Rights holder",
+ "metadata.contactForResource.role.sponsor": "Sponsor",
+ "metadata.contactForResource.role.stakeholder": "Stakeholder",
+ "metadata.contactForResource.role.unspecified": "Unspecified",
+ "metadata.contactForResource.role.user": "User",
"multiselect.filter.placeholder": "Search",
"nav.back": "Back",
"next": "next",
diff --git a/translations/es.json b/translations/es.json
index b5a2d014cd..4fb5d2f07c 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "",
"editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "",
- "editor.record.form.temporalExtents": "",
"editor.record.form.temporalExtents.addDate": "",
"editor.record.form.temporalExtents.addRange": "",
"editor.record.form.temporalExtents.date": "",
"editor.record.form.temporalExtents.range": "",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "",
"editor.record.form.updateFrequency.planned": "",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
diff --git a/translations/fr.json b/translations/fr.json
index c481e041ce..86196e1151 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -174,12 +174,9 @@
"editor.record.form.field.recordUpdated": "Date de dernière révision",
"editor.record.form.field.resourceUpdated": "Date de dernière révision",
"editor.record.form.field.temporalExtents": "Étendue temporelle",
- "editor.record.form.field.title": "Titre",
+ "editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "Identifiant unique",
"editor.record.form.field.updateFrequency": "Fréquence de mise à jour",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "Licence",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "Point de contact de la metadonee",
"editor.record.form.section.geographicalCoverage.label": "Couverture geographique",
"editor.record.form.section.useAndAccessConditions.label": "Conditions d'acces et usage",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "Date de dernière révision",
- "editor.record.form.temporalExtents": "Étendue temporelle",
"editor.record.form.temporalExtents.addDate": "Date déterminée",
"editor.record.form.temporalExtents.addRange": "Période de temps",
"editor.record.form.temporalExtents.date": "Date concernée",
"editor.record.form.temporalExtents.range": "Période concernée",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "Fréquence de mise à jour",
"editor.record.form.updateFrequency.planned": "Ces données doivent être mise à jour régulièrement.",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "Source de données",
"map.wfs.urlInput.hint": "Entrez l'URL du service WFS",
"map.wms.urlInput.hint": "Entrez l'URL du service WMS",
+ "metadata.contactForResource.role.author": "Auteur",
+ "metadata.contactForResource.role.collaborator": "Collaborateur",
+ "metadata.contactForResource.role.contributor": "Contributeur",
+ "metadata.contactForResource.role.custodian": "Gestionnaire",
+ "metadata.contactForResource.role.distributor": "Distributeur",
+ "metadata.contactForResource.role.editor": "Éditeur",
+ "metadata.contactForResource.role.funder": "Financeur",
+ "metadata.contactForResource.role.mediator": "Médiateur",
+ "metadata.contactForResource.role.originator": "Créateur",
+ "metadata.contactForResource.role.other": "Autre",
+ "metadata.contactForResource.role.owner": "Propriétaire",
+ "metadata.contactForResource.role.point_of_contact": "Point de contact",
+ "metadata.contactForResource.role.principal_investigator": "Chercheur principal",
+ "metadata.contactForResource.role.processor": "Processeur",
+ "metadata.contactForResource.role.publisher": "Éditeur",
+ "metadata.contactForResource.role.resource_provider": "Fournisseur",
+ "metadata.contactForResource.role.rights_holder": "Détenteur des droits",
+ "metadata.contactForResource.role.sponsor": "Sponsor",
+ "metadata.contactForResource.role.stakeholder": "Partie prenante",
+ "metadata.contactForResource.role.unspecified": "Non spécifié",
+ "metadata.contactForResource.role.user": "Utilisateur",
"multiselect.filter.placeholder": "Rechercher",
"nav.back": "Retour",
"next": "suivant",
diff --git a/translations/it.json b/translations/it.json
index 73f3bbeca0..a15e4468b6 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "",
"editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "Licenza",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "",
- "editor.record.form.temporalExtents": "",
"editor.record.form.temporalExtents.addDate": "",
"editor.record.form.temporalExtents.addRange": "",
"editor.record.form.temporalExtents.date": "",
"editor.record.form.temporalExtents.range": "",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "",
"editor.record.form.updateFrequency.planned": "",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "Sorgente dati",
"map.wfs.urlInput.hint": "Inserisci URL del servizio WFS",
"map.wms.urlInput.hint": "Inserisci URL del servizio WMS",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "Cerca",
"nav.back": "Indietro",
"next": "successivo",
diff --git a/translations/nl.json b/translations/nl.json
index b706426447..a8ac362d4d 100644
--- a/translations/nl.json
+++ b/translations/nl.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "",
"editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "",
- "editor.record.form.temporalExtents": "",
"editor.record.form.temporalExtents.addDate": "",
"editor.record.form.temporalExtents.addRange": "",
"editor.record.form.temporalExtents.date": "",
"editor.record.form.temporalExtents.range": "",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "",
"editor.record.form.updateFrequency.planned": "",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
diff --git a/translations/pt.json b/translations/pt.json
index ef163b9e4f..f22aee5e88 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "",
"editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "",
- "editor.record.form.temporalExtents": "",
"editor.record.form.temporalExtents.addDate": "",
"editor.record.form.temporalExtents.addRange": "",
"editor.record.form.temporalExtents.date": "",
"editor.record.form.temporalExtents.range": "",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "",
"editor.record.form.updateFrequency.planned": "",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
diff --git a/translations/sk.json b/translations/sk.json
index 4fe8fe1082..80b02618bd 100644
--- a/translations/sk.json
+++ b/translations/sk.json
@@ -177,9 +177,6 @@
"editor.record.form.field.title": "",
"editor.record.form.field.uniqueIdentifier": "",
"editor.record.form.field.updateFrequency": "",
- "editor.record.form.abstract": "",
- "editor.record.form.keywords": "",
- "editor.record.form.license": "Licencia",
"editor.record.form.license.cc-by": "",
"editor.record.form.license.cc-by-sa": "",
"editor.record.form.license.cc-zero": "",
@@ -205,16 +202,10 @@
"editor.record.form.section.dataPointOfContact.label": "",
"editor.record.form.section.geographicalCoverage.label": "",
"editor.record.form.section.useAndAccessConditions.label": "",
- "editor.record.form.metadata.title": "",
- "editor.record.form.record.updated": "",
- "editor.record.form.resourceUpdated": "",
- "editor.record.form.temporalExtents": "",
"editor.record.form.temporalExtents.addDate": "",
"editor.record.form.temporalExtents.addRange": "",
"editor.record.form.temporalExtents.date": "",
"editor.record.form.temporalExtents.range": "",
- "editor.record.form.unique.identifier": "",
- "editor.record.form.updateFrequency": "",
"editor.record.form.updateFrequency.planned": "",
"editor.record.loadError.body": "",
"editor.record.loadError.closeMessage": "",
@@ -287,6 +278,27 @@
"map.select.layer": "Zdroj dát",
"map.wfs.urlInput.hint": "Zadajte URL adresu služby WFS",
"map.wms.urlInput.hint": "Zadajte URL adresu služby WMS",
+ "metadata.contactForResource.role.author": "",
+ "metadata.contactForResource.role.collaborator": "",
+ "metadata.contactForResource.role.contributor": "",
+ "metadata.contactForResource.role.custodian": "",
+ "metadata.contactForResource.role.distributor": "",
+ "metadata.contactForResource.role.editor": "",
+ "metadata.contactForResource.role.funder": "",
+ "metadata.contactForResource.role.mediator": "",
+ "metadata.contactForResource.role.originator": "",
+ "metadata.contactForResource.role.other": "",
+ "metadata.contactForResource.role.owner": "",
+ "metadata.contactForResource.role.point_of_contact": "",
+ "metadata.contactForResource.role.principal_investigator": "",
+ "metadata.contactForResource.role.processor": "",
+ "metadata.contactForResource.role.publisher": "",
+ "metadata.contactForResource.role.resource_provider": "",
+ "metadata.contactForResource.role.rights_holder": "",
+ "metadata.contactForResource.role.sponsor": "",
+ "metadata.contactForResource.role.stakeholder": "",
+ "metadata.contactForResource.role.unspecified": "",
+ "metadata.contactForResource.role.user": "",
"multiselect.filter.placeholder": "Hľadať",
"nav.back": "Späť",
"next": "Ďalej",