diff --git a/ui/src/app/home/consortium/add-consortium-member.component.html b/ui/src/app/home/consortium/add-consortium-member.component.html index b41131bd7..09c1972ef 100644 --- a/ui/src/app/home/consortium/add-consortium-member.component.html +++ b/ui/src/app/home/consortium/add-consortium-member.component.html @@ -1 +1,494 @@ -

add-consortium-member works!

+
+
+ Back to {{ memberData.publicDisplayName }} +
+
+
Add new consortium member
+

New organization

+
+
+
+ Warning sign +
+
+ Your changes cannot be saved +
+
+ Please fix the issues with the form before trying to save again +
+
+
+
+

Organization details

+ + + +

Name & email domain

+
+ + + + The legal or official name for this organization. Max 41 characters. + +
+ + Organization name cannot be empty + +
+ + Organization name is too long. Please use 41 characters or less. + +
+
+
+
+ + + + The email domain is the remaining address after the @ symbol eg: orcid.org or website.com + +
+ + Email domain is too long. Please use 255 characters or less. + +
+
+ + + +

Billing address

+
+ + +
+ + Street name is too long. Please use 255 characters or less. + +
+
+
+ + +
+ + City name is too long. Please use 40 characters or less. + +
+
+
+ + +
+
+ + +
+ + Please select a country + +
+
+
+ + +
+ + ZIP/Postcode is too long. Please use 20 characters or less. + +
+
+ + + +

+ Trademark license (Required) +

+
+ Can ORCID use this organization's trademarked name and logos? +
+
+
+ + +
+
+ + +
+
+ + Please select a trademark license option + +
+
+ + + +

Membership start date (Required)

+
+ When does this organization's ORCID membership start? All memberships begin on the 1st of the month. +
+
+
+ + +
+ + Please select the membership start date + + + Please select the membership start month + + + Please select the membership start year + +
+ + + +

Main contact

+
+ Please provide details of the main point of contact for this organization. This person will automatically be assigned the + Main relationship and Voting contact roles for this organization. +
+
+ + +
+ + First or given name is too long. Please use 40 characters or less. + + + Please provide a first or given name + +
+
+
+ + +
+ + Last or family name is too long. Please use 80 characters or less. + + + Please provide a last or family name + +
+
+
+ + +
+ + Job title is too long. Please use 128 characters or less. + +
+
+
+ + + + The contact email for this person + +
+ + Please enter a valid email address, for example contactus@website.com + + + Email is too long. Please use 80 characters or less. + + + Please provide an email address + +
+
+
+ Warning sign +
+
+ Please note +
+
+ It can take up to 24 hours before a new organization is available in the Member Portal. Please contact your ORCID engagement + lead for more information. +
+
+
+ + +
+
+
+
+ \ No newline at end of file diff --git a/ui/src/app/home/consortium/add-consortium-member.component.scss b/ui/src/app/home/consortium/add-consortium-member.component.scss index e69de29bb..768ceb164 100644 --- a/ui/src/app/home/consortium/add-consortium-member.component.scss +++ b/ui/src/app/home/consortium/add-consortium-member.component.scss @@ -0,0 +1,63 @@ +@use '../../../content/scss/bootstrap-variables' as global; + +input { + font-size: 14px; + letter-spacing: 0.25px; +} + +input, +select, +option { + height: 40px; +} + +.ng-invalid:not(form) { + border: 1px solid #d32f2f; + border-radius: 2px; +} + +label { + margin-bottom: 0.25rem; +} + +.error-message { + img { + padding: 0 16px 0 8px !important; + margin-top: -1.75rem; + } + div { + font-size: 0.875rem; + } + border: 2px solid #b71c1c; + border-radius: 4px; +} + +.warning-message { + img { + padding: 0 16px 0 8px !important; + margin-top: -3rem; + } + div { + font-size: 0.875rem; + } + border: 2px solid #ff9c00; + border-radius: 4px; +} + +.radio { + height: 1.125rem; + width: 1.125rem; + accent-color: global.$info; +} + +.date-dropdown { + width: 7.5rem; +} + +.postcode-input-field { + max-width: 180px; +} + +.org-name-input-field { + max-width: 400px; +} diff --git a/ui/src/app/home/consortium/add-consortium-member.component.spec.ts b/ui/src/app/home/consortium/add-consortium-member.component.spec.ts index 4e03beea3..a4f4bdfa0 100644 --- a/ui/src/app/home/consortium/add-consortium-member.component.spec.ts +++ b/ui/src/app/home/consortium/add-consortium-member.component.spec.ts @@ -1,21 +1,94 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing' -import { AddConsortiumMemberComponent } from './add-consortium-member.component'; +import { AddConsortiumMemberComponent } from './add-consortium-member.component' +import { MemberService } from 'src/app/member/service/member.service' +import { AccountService } from 'src/app/account' +import { AlertService } from 'src/app/shared/service/alert.service' +import { ActivatedRoute, Router } from '@angular/router' +import { HttpClientTestingModule } from '@angular/common/http/testing' +import { RouterTestingModule } from '@angular/router/testing' +import { of } from 'rxjs' +import { AlertType } from 'src/app/app.constants' describe('AddConsortiumMemberComponent', () => { - let component: AddConsortiumMemberComponent; - let fixture: ComponentFixture; + let component: AddConsortiumMemberComponent + let fixture: ComponentFixture + + let memberServiceSpy: jasmine.SpyObj + let accountServiceSpy: jasmine.SpyObj + let alertServiceSpy: jasmine.SpyObj + let activatedRoute: jasmine.SpyObj + let router: jasmine.SpyObj beforeEach(() => { + memberServiceSpy = jasmine.createSpyObj('MemberService', ['addConsortiumMember']) + accountServiceSpy = jasmine.createSpyObj('AccountService', ['getAccountData']) + alertServiceSpy = jasmine.createSpyObj('AlertService', ['broadcast']) + TestBed.configureTestingModule({ - declarations: [AddConsortiumMemberComponent] - }); - fixture = TestBed.createComponent(AddConsortiumMemberComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + imports: [HttpClientTestingModule, RouterTestingModule], + declarations: [AddConsortiumMemberComponent], + providers: [ + { provide: MemberService, useValue: memberServiceSpy }, + { provide: AccountService, useValue: accountServiceSpy }, + { provide: AlertService, useValue: alertServiceSpy }, + ], + }) + + accountServiceSpy = TestBed.inject(AccountService) as jasmine.SpyObj + memberServiceSpy = TestBed.inject(MemberService) as jasmine.SpyObj + alertServiceSpy = TestBed.inject(AlertService) as jasmine.SpyObj + router = TestBed.inject(Router) as jasmine.SpyObj + activatedRoute = TestBed.inject(ActivatedRoute) as jasmine.SpyObj + + fixture = TestBed.createComponent(AddConsortiumMemberComponent) + component = fixture.componentInstance + + spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)) + + accountServiceSpy.getAccountData.and.returnValue( + of({ + activated: true, + authorities: ['test', 'test'], + email: 'email@email.com', + firstName: 'name', + langKey: 'en', + lastName: 'surname', + imageUrl: 'url', + salesforceId: 'sfid', + loggedAs: false, + loginAs: 'sfid', + mainContact: false, + mfaEnabled: true, + }) + ) + + fixture.detectChanges() + }) it('should create', () => { - expect(component).toBeTruthy(); - }); -}); + expect(component).toBeTruthy() + }) + + it('should call memberService.updateContact when saving', () => { + memberServiceSpy.addConsortiumMember.and.returnValue(of(true)) + + // set form to valid + for (const control in component.editForm.controls) { + component.editForm.controls[control].clearAsyncValidators() + component.editForm.controls[control].clearValidators() + component.editForm.controls[control].updateValueAndValidity({ onlySelf: true }) + } + component.editForm.updateValueAndValidity() + + component.save() + + expect(memberServiceSpy.addConsortiumMember).toHaveBeenCalled() + }) + + it('alert service and router should be called on save success', () => { + component.onSaveSuccess() + expect(alertServiceSpy.broadcast).toHaveBeenCalledWith(AlertType.CONSORTIUM_MEMBER_ADDED) + expect(router.navigate).toHaveBeenCalled() + }) +}) diff --git a/ui/src/app/home/consortium/add-consortium-member.component.ts b/ui/src/app/home/consortium/add-consortium-member.component.ts index 7480c5552..132190234 100644 --- a/ui/src/app/home/consortium/add-consortium-member.component.ts +++ b/ui/src/app/home/consortium/add-consortium-member.component.ts @@ -24,11 +24,26 @@ export class AddConsortiumMemberComponent implements OnInit { isSaving: boolean = false invalidForm: boolean = false routeData: any - editForm: FormGroup | undefined currentMonth: number | undefined currentYear: number | undefined monthList: [number, string][] | undefined yearList: number[] | undefined + editForm: FormGroup = this.fb.group({ + orgName: [null, [Validators.required, Validators.maxLength(41)]], + emailDomain: [null, [Validators.maxLength(255)]], + street: [null, [Validators.maxLength(255)]], + city: [null, [Validators.maxLength(40)]], + state: [null, [Validators.maxLength(80)]], + country: [null, [Validators.required]], + postcode: [null, [Validators.maxLength(20)]], + trademarkLicense: [null, [Validators.required]], + startMonth: [null, [Validators.required]], + startYear: [null, [Validators.required]], + contactGivenName: [null, [Validators.required, Validators.maxLength(40)]], + contactFamilyName: [null, [Validators.required, Validators.maxLength(80)]], + contactJobTitle: [null, [Validators.maxLength(128)]], + contactEmail: [null, [Validators.required, Validators.pattern(EMAIL_REGEXP), Validators.maxLength(80)]], + }) rolesData = [ { id: 1, selected: false, name: 'Main relationship contact' }, @@ -54,22 +69,6 @@ export class AddConsortiumMemberComponent implements OnInit { this.currentYear = this.dateUtilService.getCurrentYear() this.monthList = this.dateUtilService.getMonthsList() this.yearList = this.dateUtilService.getFutureYearsIncludingCurrent(1) - this.editForm = this.fb.group({ - orgName: [null, [Validators.required, Validators.maxLength(41)]], - emailDomain: [null, [Validators.maxLength(255)]], - street: [null, [Validators.maxLength(255)]], - city: [null, [Validators.maxLength(40)]], - state: [null, [Validators.maxLength(80)]], - country: [null, [Validators.required]], - postcode: [null, [Validators.maxLength(20)]], - trademarkLicense: [null, [Validators.required]], - startMonth: [null, [Validators.required]], - startYear: [null, [Validators.required]], - contactGivenName: [null, [Validators.required, Validators.maxLength(40)]], - contactFamilyName: [null, [Validators.required, Validators.maxLength(80)]], - contactJobTitle: [null, [Validators.maxLength(128)]], - contactEmail: [null, [Validators.required, Validators.pattern(EMAIL_REGEXP), Validators.maxLength(80)]], - }) this.accountService.getAccountData().subscribe((account) => { if (account) { @@ -131,7 +130,7 @@ export class AddConsortiumMemberComponent implements OnInit { this.memberService.addConsortiumMember(newConsortiumMember).subscribe( (res) => { if (res) { - this.onSaveSuccess(newConsortiumMember.orgName) + this.onSaveSuccess() } else { console.error(res) this.onSaveError() @@ -145,7 +144,7 @@ export class AddConsortiumMemberComponent implements OnInit { } } - onSaveSuccess(orgName: string) { + onSaveSuccess() { this.isSaving = false this.alertService.broadcast(AlertType.CONSORTIUM_MEMBER_ADDED) this.router.navigate(['']) diff --git a/ui/src/app/home/contact/contact-update.component.html b/ui/src/app/home/contact/contact-update.component.html index 9cc60509f..a5ccb9e32 100644 --- a/ui/src/app/home/contact/contact-update.component.html +++ b/ui/src/app/home/contact/contact-update.component.html @@ -131,7 +131,7 @@

Roles (Requ
- +
diff --git a/ui/src/app/home/contact/contact-update.component.scss b/ui/src/app/home/contact/contact-update.component.scss index e69de29bb..1995b8700 100644 --- a/ui/src/app/home/contact/contact-update.component.scss +++ b/ui/src/app/home/contact/contact-update.component.scss @@ -0,0 +1,50 @@ +@use '../../../content/scss/bootstrap-variables' as global; + +.input-prompt { + color: global.$black-transparent; +} + +input { + font-size: 14px; + letter-spacing: 0.25px; +} + +.ng-invalid:not(form) { + border: 1px solid #d32f2f; + border-radius: 2px; +} + +.error-message { + img { + padding: 0 16px 0 8px !important; + margin-top: -1.75rem; + } + div { + font-size: 0.875rem; + } + border: 2px solid #b71c1c; + border-radius: 4px; +} + +.warning-message { + img { + padding: 0 16px 0 8px !important; + margin-top: -3rem; + } + div { + font-size: 0.875rem; + } + border: 2px solid #ff9c00; + border-radius: 4px; +} + +.role-checkbox { + height: 1.125rem; + width: 1.125rem; + margin-right: 0.5rem; + vertical-align: middle; +} + +input { + height: 40px; +} diff --git a/ui/src/app/home/contact/contact-update.component.spec.ts b/ui/src/app/home/contact/contact-update.component.spec.ts index d0036f7f4..e51a6f73d 100644 --- a/ui/src/app/home/contact/contact-update.component.spec.ts +++ b/ui/src/app/home/contact/contact-update.component.spec.ts @@ -163,5 +163,6 @@ describe('ContactUpdateComponent', () => { it('alert service and router should be called on save success', () => { component.onSaveSuccess() expect(alertServiceSpy.broadcast).toHaveBeenCalledWith(AlertType.CONTACT_UPDATED) + expect(router.navigate).toHaveBeenCalled() }) })