diff --git a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html index 511e194a22..a205e4c41f 100644 --- a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html +++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html @@ -1,28 +1,25 @@ - -
-
- -
-
- {{ contact.firstName }} {{ contact.lastName }} -
-
{{ contact.email }}
+
+
+ +
+
+ {{ contact.firstName }} {{ contact.lastName }}
+
{{ contact.email }}
- close -
- + close + +
diff --git a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts index 494bed0ad9..10fb9c6ffa 100644 --- a/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts +++ b/libs/feature/editor/src/lib/components/contact-card/contact-card.component.ts @@ -5,13 +5,11 @@ import { Input, Output, } from '@angular/core' -import { - Individual, - Organization, -} from '@geonetwork-ui/common/domain/model/record' +import { Individual } 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' +import { ThumbnailComponent } from '@geonetwork-ui/ui/elements' @Component({ selector: 'gn-ui-contact-card', @@ -19,11 +17,10 @@ import { ButtonComponent } from '@geonetwork-ui/ui/inputs' styleUrls: ['./contact-card.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - imports: [CommonModule, MatIconModule, ButtonComponent], + imports: [CommonModule, MatIconModule, ButtonComponent, ThumbnailComponent], }) export class ContactCardComponent { @Input() contact: Individual - @Input() organization: Organization @Input() removable = true @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.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html index 291b27bba4..69d8a2f22e 100644 --- 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 @@ -16,11 +16,18 @@
@@ -38,20 +45,23 @@ [clearOnSelection]="true" > - - + + + + + + + + - - - +
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 index 680de56f29..b8ca81bc3f 100644 --- 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 @@ -97,7 +97,7 @@ describe('FormFieldContactsForResourceComponent', () => { 'point_of_contact', 'author', ]) - expect(component.rolesToDisplay).toEqual([]) + expect(component.roleSectionsToDisplay).toEqual([]) expect(component.allOrganizations.size).toBe(2) }) @@ -117,7 +117,7 @@ describe('FormFieldContactsForResourceComponent', () => { it('should add role to rolesToDisplay and remove from rolesToPick', () => { component.addRoleToDisplay('owner') expect(component.rolesToPick).not.toContain('owner') - expect(component.rolesToDisplay).toContain('owner') + expect(component.roleSectionsToDisplay).toContain('owner') }) it('should remove contact by index', () => { @@ -156,7 +156,7 @@ describe('FormFieldContactsForResourceComponent', () => { }, } as unknown as SimpleChanges component.ngOnChanges(changes) - expect(component.rolesToDisplay).toEqual([ + expect(component.roleSectionsToDisplay).toEqual([ contactJane.role, contactJohn.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.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts index bfd2fdccf8..b7ebcdcf64 100644 --- 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 @@ -4,10 +4,7 @@ import { ChangeDetectorRef, Component, Input, - OnChanges, OnInit, - SimpleChanges, - Type, } from '@angular/core' import { FormControl } from '@angular/forms' import { @@ -19,10 +16,18 @@ import { UiWidgetsModule } from '@geonetwork-ui/ui/widgets' import { Individual, Organization, + Role, RoleLabels, } from '@geonetwork-ui/common/domain/model/record' import { TranslateModule } from '@ngx-translate/core' -import { debounceTime, distinctUntilChanged, Observable, switchMap } from 'rxjs' +import { + debounceTime, + distinctUntilChanged, + lastValueFrom, + Observable, + Subscription, + switchMap, +} from 'rxjs' import { UserModel } from '@geonetwork-ui/common/domain/model/user' import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface' import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface' @@ -49,14 +54,18 @@ import { SortableListComponent, ], }) -export class FormFieldContactsForResourceComponent - implements OnInit, OnChanges -{ +export class FormFieldContactsForResourceComponent implements OnInit { @Input() control: FormControl + subscription: Subscription = new Subscription() + allUsers$: Observable - rolesToPick: string[] = [ + contactsForRessourceByRole: Map = new Map() + + contactsAsDynElemByRole: Map = new Map() + + rolesToPick: Role[] = [ 'resource_provider', 'custodian', 'owner', @@ -64,12 +73,10 @@ export class FormFieldContactsForResourceComponent 'author', ] - rolesToDisplay = [] + roleSectionsToDisplay: Role[] = [] allOrganizations: Map = new Map() - addOptions: Array<{ buttonLabel: string; eventName: string }> = [] - constructor( private platformServiceInterface: PlatformServiceInterface, private organizationsServiceInterface: OrganizationsServiceInterface, @@ -78,51 +85,109 @@ export class FormFieldContactsForResourceComponent this.allUsers$ = this.platformServiceInterface.getUsers() } - ngOnInit(): void { - this.organizationsServiceInterface.organisations$.subscribe( - (organizations) => { - this.allOrganizations = new Map( - organizations.map((organization) => [organization.name, organization]) - ) - this.changeDetectorRef.markForCheck() - } + async ngOnInit(): Promise { + this.allOrganizations = new Map( + ( + await lastValueFrom(this.organizationsServiceInterface.organisations$) + ).map((organization) => [organization.name, organization]) ) - } + this.updateContactsForRessource() + this.manageRoleSectionsToDisplay(this.control.value) + this.filterRolesToPick() - ngOnChanges(changes: SimpleChanges) { - const contactsForResource = changes['control'] + this.changeDetectorRef.markForCheck() - if ( - contactsForResource && - contactsForResource.currentValue !== contactsForResource.previousValue - ) { - const rolesToAdd = contactsForResource.currentValue.value.map( - (contact: Individual) => contact.role - ) + this.subscription.add( + this.control.valueChanges.subscribe((contactsForResource) => { + console.log(contactsForResource) - console.log(contactsForResource.currentValue) + this.updateContactsForRessource() + this.manageRoleSectionsToDisplay(contactsForResource) + this.filterRolesToPick() - rolesToAdd.forEach((role: string) => { - if (!this.rolesToDisplay.includes(role)) { - this.rolesToDisplay.push(role) - } + this.changeDetectorRef.markForCheck() }) - - this.filterRolesToPick() - - this.changeDetectorRef.markForCheck() - } + ) } addRoleToDisplay(roleToAdd: string) { - this.rolesToDisplay.push(roleToAdd) + this.roleSectionsToDisplay.push(roleToAdd) this.filterRolesToPick() } filterRolesToPick() { this.rolesToPick = this.rolesToPick.filter( - (role) => !this.rolesToDisplay.includes(role) + (role) => !this.roleSectionsToDisplay.includes(role) + ) + } + + updateContactsForRessource() { + this.contactsForRessourceByRole = this.control.value.reduce( + (acc, contact) => { + const completeOrganization = this.allOrganizations.get( + contact.organization.name + ) + + const updatedContact = { + ...contact, + organization: + completeOrganization ?? + ({ name: contact.organization.name } as Organization), + } + + if (!acc.has(contact.role)) { + acc.set(contact.role, []) + } + + acc.get(contact.role).push(updatedContact) + + return acc + }, + new Map() ) + + this.contactsAsDynElemByRole = this.control.value.reduce((acc, contact) => { + const completeOrganization = this.allOrganizations.get( + contact.organization.name + ) + + const updatedContact = { + ...contact, + organization: + completeOrganization ?? + ({ name: contact.organization.name } as Organization), + } + + const contactAsDynElem = { + component: ContactCardComponent, + inputs: { + contact: updatedContact, + removable: false, + }, + } as DynamicElement + + if (!acc.has(contact.role)) { + acc.set(contact.role, []) + } + + acc.get(contact.role).push(contactAsDynElem) + + return acc + }, new Map()) + + this.changeDetectorRef.markForCheck() + } + + manageRoleSectionsToDisplay(contactsForResource: Individual[]) { + const roles = contactsForResource.map( + (contact: Individual) => contact.role + ) as Role[] + + roles.forEach((role: Role) => { + if (!this.roleSectionsToDisplay.includes(role)) { + this.roleSectionsToDisplay.push(role) + } + }) } removeContact(index: number) { @@ -132,6 +197,22 @@ export class FormFieldContactsForResourceComponent this.control.setValue(newContactsforRessource) } + handleContactsChanged(event: DynamicElement[]) { + const newContactsOrdered = event.map( + (contactAsDynElem) => contactAsDynElem.inputs['contact'] + ) as Individual[] + + const role = newContactsOrdered[0].role + + this.contactsForRessourceByRole.set(role, newContactsOrdered) + + const newControlValue = Array.from( + this.contactsForRessourceByRole.values() + ).flat() + + this.control.setValue(newControlValue) + } + protected roleToLabel(role: string): string { return RoleLabels.get(role) } @@ -140,7 +221,9 @@ export class FormFieldContactsForResourceComponent * gn-ui-autocomplete */ displayWithFn: (user: UserModel) => string = (user) => - `${user.name} ${user.surname}` + `${user.name} ${user.surname} ${ + user.organisation ? `(${user.organisation})` : '' + }` /** * gn-ui-autocomplete @@ -159,12 +242,12 @@ export class FormFieldContactsForResourceComponent * gn-ui-autocomplete */ addContact(contact: UserModel, role: string) { - let newContactsForRessource = { + const newContactsForRessource = { firstName: contact.name ?? '', lastName: contact.surname ?? '', - organization: { - name: contact.organisation, - }, + organization: + this.allOrganizations.get(contact.organisation) ?? + ({ name: contact.organisation } as Organization), email: contact.email ?? '', role, address: '', @@ -172,49 +255,10 @@ export class FormFieldContactsForResourceComponent position: '', } as Individual - const newContactOrganization = this.getOrganizationByName( - contact.organisation - ) - - newContactsForRessource = { - ...newContactsForRessource, - organization: newContactOrganization, - } - const newControlValue = [...this.control.value, newContactsForRessource] - this.control.setValue(newControlValue) - } - - getContactsByRole(role: string): Individual[] { - return this.control.value.filter((contact: Individual) => { - return contact.role === role - }) - } - - getOrganizationByName(name: string): Organization { - return this.allOrganizations.get(name) - } + console.log(newControlValue) - getContactByRoleForSortableList(role: string): Array { - return this.control.value - .filter((contact: Individual) => { - return contact.role === role - }) - .map((contact) => ({ - component: ContactCardComponent, - inputs: { - contact, - organization: contact.organization, - removable: false, - }, - })) as Array<{ - component: Type - inputs: Record - }> - } - - handleContactOrderChange(event) { - console.log(event) + this.control.setValue(newControlValue) } }