Skip to content

Commit

Permalink
8934-registration-add-an-affiliation-with-typeahead
Browse files Browse the repository at this point in the history
  • Loading branch information
Leonardo Mendoza Fernadez authored and Leonardo Mendoza Fernadez committed Jan 12, 2024
1 parent ed375a9 commit eea4580
Show file tree
Hide file tree
Showing 17 changed files with 800 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/app/core/register2/register2.backend-validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface HasFormAdapters {
StepA: UntypedFormGroup,
StepB: UntypedFormGroup,
StepC: UntypedFormGroup,
StepC2: UntypedFormGroup,
StepD: UntypedFormGroup
): RegisterForm
}
Expand Down Expand Up @@ -161,6 +162,7 @@ export function Register2BackendValidatorMixin<
StepA: UntypedFormGroup,
StepB: UntypedFormGroup,
StepC: UntypedFormGroup,
StepC2: UntypedFormGroup,
StepD: UntypedFormGroup,

type?: 'shibboleth'
Expand All @@ -169,6 +171,7 @@ export function Register2BackendValidatorMixin<
StepA,
StepB,
StepC,
StepC2,
StepD
)
return this._http
Expand Down
24 changes: 24 additions & 0 deletions src/app/core/register2/register2.form-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,40 @@ export function Register2FormAdapterMixin<T extends Constructor<any>>(base: T) {
return value
}

formGroupToAffiliationRegisterForm(formGroup: UntypedFormGroup) {
console.log(formGroup.value)

const value = formGroup.controls['organization'].value
const departmentName = formGroup.controls['departmentName'].value
const roleTitle = formGroup.controls['roleTitle'].value

if (typeof value === 'string') {
return { affiliationName: { value } }
} else {
return {
affiliationName: { value: value.value },
disambiguatedAffiliationSourceId: {
value: value.disambiguatedAffiliationIdentifier,
},
departmentName: { value: departmentName },
roleTitle: { value: roleTitle },
affiliationType: { value: 'Employment' },
}
}
}

formGroupToFullRegistrationForm(
StepA: UntypedFormGroup,
StepB: UntypedFormGroup,
StepC: UntypedFormGroup,
StepC2: UntypedFormGroup,
StepD: UntypedFormGroup
): RegisterForm {
return {
...StepA.value.personal,
...StepB.value.password,
...StepC.value.activitiesVisibilityDefault,
...StepC2.value.affiliations,
...StepD.value.sendOrcidNews,
...StepD.value.termsOfUse,
...StepD.value.captcha,
Expand Down
9 changes: 7 additions & 2 deletions src/app/core/register2/register2.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { UntypedFormGroup } from '@angular/forms'
import { Observable } from 'rxjs'
import { catchError, first, map, retry, switchMap } from 'rxjs/operators'
import { Observable, throwError } from 'rxjs'
import { catchError, first, map, retry, switchMap, tap } from 'rxjs/operators'
import { PlatformInfo, PlatformInfoService } from 'src/app/cdk/platform-info'
import { RequestInfoForm } from 'src/app/types'
import {
Expand Down Expand Up @@ -85,6 +85,7 @@ export class Register2Service extends _RegisterServiceMixingBase {
StepA: UntypedFormGroup,
StepB: UntypedFormGroup,
StepC: UntypedFormGroup,
StepC2: UntypedFormGroup,
StepD: UntypedFormGroup,
reactivation: ReactivationLocal,
requestInfoForm?: RequestInfoForm,
Expand All @@ -96,6 +97,7 @@ export class Register2Service extends _RegisterServiceMixingBase {
StepA,
StepB,
StepC,
StepC2,
StepD
)
this.addOauthContext(registerForm, requestInfoForm)
Expand Down Expand Up @@ -134,6 +136,9 @@ export class Register2Service extends _RegisterServiceMixingBase {
)
)
.pipe(
tap((value) => {
throw 'nothing'
}),
retry(3),
catchError((error) =>
this._errorHandler.handleError(error, ERROR_REPORT.REGISTER)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<ng-container [formGroup]="form">
<h3 i18n="@@register.currentEmployment" class="orc-font-body margin-top-12">
Current employment
</h3>

<div class="announce">
<div>
<img src="/assets/vectors/personal-email-icon.svg" aria-hidden="true" />
</div>
<div class="content">
<div>
<h3 class="orc-font-body" i18n="@@register.thisLooksLikeAPersonalEmail">
Affiliation found
</h3>
</div>
<div>
<ng-container>
Based on your emails we think you are currently affiliated with
</ng-container>
<strong>The University of Bath.</strong>
<ng-container
>We’ve pre-selected this organization for you in the form
below.</ng-container
>

<div>
When you complete registration an employment affiliation will be
automatically added to your new ORCID record.
</div>
</div>
</div>
</div>

<section id="{{ type }}-organization">
<div
id="organization"
class="title"
[ngClass]="{
'orc-font-body': !platform.columns12,
'orc-font-body-large': platform.columns12
}"
>
<div class="row">
<h2
[ngClass]="{
'orc-font-body': !platform.columns12,
'orc-font-body-large': platform.columns12
}"
>
<strong i18n="@@shared.organization"> Organization </strong>
<span *ngIf="!platform.columns12" class="required">*</span>
</h2>
<p *ngIf="platform.columns12" class="required-information mat-caption">
<span class="required">*</span>
<ng-container i18n="@@shared.requiredInformation"
>Required information
</ng-container>
</p>
</div>
</div>
<hr />

<div class="row">
<label
for="organization-input"
id="organization-label"
class="mat-caption"
[ngClass]="{
error: organizationIsInvalidAndTouched
}"
>
<strong i18n="@@shared.organization" id="organizationLabel"
>Organization</strong
>
<span class="required">*</span>
</label>
</div>

<div class="input-container" id="cy-org-dd-div">
<mat-form-field
appearance="outline"
class="mat-form-field-min"
id="cy-org-dd-mat-form"
[ngClass]="{
'two-line-hint': selectedOrganizationFromDatabase?.value.length > 50
}"
>
<input
aria-labelledby="organizationLabel"
id="organization-input"
matInput
formControlName="organization"
[matAutocomplete]="auto"
[attr.aria-invalid]="organizationIsInvalidAndTouched"
[placeholder]="organizationPlaceholder"
/>
<mat-autocomplete
autoActiveFirstOption
#auto="matAutocomplete"
[displayWith]="autoCompleteDisplayOrganization"
id="cy-org-dd"
>
<ng-container *ngIf="filteredOptions" id="cy-org-filtered-options">
<mat-option
*ngFor="let option of filteredOptions | async"
[value]="option"
>
<div class="row orc-font-body-small title">
{{ option.value }}
</div>
<div class="row orc-font-small-print">
{{ option.city }} {{ option.region }} {{ option.country }}
</div>
</mat-option>
</ng-container>
</mat-autocomplete>
<mat-hint
*ngIf="selectedOrganizationFromDatabase && displayOrganizationHint"
>
<ng-container i18n="@@record.identifyAS">Identify as:</ng-container>
{{ selectedOrganizationFromDatabase.value }}
</mat-hint>
<mat-hint
*ngIf="
!selectedOrganizationFromDatabase &&
form.get('organization').value &&
displayOrganizationHint
"
i18n="@@record.unidentifiedOrganization"
>
Unidentified organization
</mat-hint>

<button
class="clear"
matSuffix
mat-icon-button
aria-label="Clear"
(click)="clearForm()"
*ngIf="form.get('organization').value"
>
<mat-icon>close</mat-icon>
</button>
<mat-error
role="alert"
aria-describedby="organization-label"
class="mat-caption"
*ngIf="organizationFormTouched"
i18n="@@shared.pleaseEnterAnOrganization"
>
Please enter an organization
</mat-error>
<mat-error
*ngIf="form.get('organization').errors?.maxlength"
i18n="@@shared.maxLength.less_than_one_thousand"
>
Must be less than 1000 characters
</mat-error>
</mat-form-field>
</div>
</section>

<div class="input-container">
<mat-label class="orc-font-small-print"
><ng-container i18n="@@register.xxxxx">Department</ng-container>
<label id="family-names-input-label" i18n="@@register.optional"
>(Optional)</label
></mat-label
>
<mat-form-field appearance="outline" [hideRequiredMarker]="true">
<input
aria-labelledby="family-names-input-label"
id="family-names-input"
formControlName="departmentName"
matInput
[placeholder]="departmentPlaceholder"
/>
</mat-form-field>
</div>
<div class="input-container">
<mat-label class="orc-font-small-print"
><ng-container i18n="@@register.xxxxx">Role/Job title</ng-container>
<label id="family-names-input-label" i18n="@@register.optional"
>(Optional)</label
></mat-label
>
<mat-form-field appearance="outline" [hideRequiredMarker]="true">
<input
aria-labelledby="family-names-input-label"
id="family-names-input"
formControlName="roleTitle"
matInput
[placeholder]="rolePlaceholder"
/>
</mat-form-field>
</div>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:host {
display: flex;
flex-direction: column;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'

import { Overlay } from '@angular/cdk/overlay'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'
import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'
import { RouterTestingModule } from '@angular/router/testing'
import { PlatformInfoService } from '../../../cdk/platform-info'
import { MdePopoverModule } from '../../../cdk/popover'
import { SnackbarService } from '../../../cdk/snackbar/snackbar.service'
import { WINDOW_PROVIDERS } from '../../../cdk/window'
import { ErrorHandlerService } from '../../../core/error-handler/error-handler.service'
import { ReactivationService } from '../../../core/reactivation/reactivation.service'
import { Register2Service } from '../../../core/register2/register2.service'
import { FormCurrentEmploymentComponent } from './form-current-employment.component'

describe('FormPersonalComponent', () => {
let component: FormCurrentEmploymentComponent
let fixture: ComponentFixture<FormCurrentEmploymentComponent>

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, MdePopoverModule, RouterTestingModule],
declarations: [FormCurrentEmploymentComponent],
providers: [
WINDOW_PROVIDERS,
ReactivationService,
Register2Service,
PlatformInfoService,
ErrorHandlerService,
SnackbarService,
MatSnackBar,
MatDialog,
Overlay,
],
}).compileComponents()
})

beforeEach(() => {
fixture = TestBed.createComponent(FormCurrentEmploymentComponent)
component = fixture.componentInstance
fixture.detectChanges()
})

it('should create', () => {
expect(component).toBeTruthy()
})
})
Loading

0 comments on commit eea4580

Please sign in to comment.