File

src/app/shared/components/registration-metadata/registration-metadata.component.ts

Description

Right side registration menu

Metadata

Index

Properties
Methods
Outputs

Constructor

constructor(model: ModelState, registration: RegistrationState, page: PageState)

Creates an instance of registration metadata component.

Parameters :
Name Type Optional Description
model ModelState No

Model state

registration RegistrationState No

Registration state

page PageState No

Page state

Outputs

registrationSelected
Type : EventEmitter

Emits when user has uploaded registration

Methods

checkNameValid
checkNameValid(event: Pick<Person | "firstName" | "lastName">)

Checks to see if a first and last name has been entered

Parameters :
Name Type Optional Description
event Pick<Person | "firstName" | "lastName"> No

Name input event

Returns : void
getErrorMessage
getErrorMessage()

Error message to inform user if orcid is invalid

Returns : string

Error message

handleRegistrationUpload
handleRegistrationUpload(reg: SpatialEntityJsonLd)

Emits registrationSelected and calls editRegistration in state

Parameters :
Name Type Optional
reg SpatialEntityJsonLd No
Returns : void
setSexFromLabel
setSexFromLabel(label: "Female" | "Male")

Updates current sex selected

Parameters :
Name Type Optional Description
label "Female" | "Male" No

Sex selected

Returns : void
updateOrcid
updateOrcid(value: string)

Updates orcid value

Parameters :
Name Type Optional Description
value string No

Orcid value entered

Returns : void

Properties

nameValid
Type : boolean

Checks if first and last name has been entered

Optional orcId
Type : string

Orcid URI converted to regular id

orcidControl
Default value : new FormControl('', [Validators.pattern('^[a-zA-Z0-9]{4}(-[a-zA-Z0-9]{4}){3}$')])

Form control for validating orcid id

uploadText
Type : string

Text to inform user if a registration file has been uploaded

import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';

import { FormControl, Validators } from '@angular/forms';
import { SpatialEntityJsonLd } from 'ccf-body-ui';
import { ModelState } from '../../../core/store/model/model.state';
import { PageState, Person } from '../../../core/store/page/page.state';
import { RegistrationState } from '../../../core/store/registration/registration.state';

/**
 * Right side registration menu
 */
@Component({
  selector: 'ccf-registration-metadata',
  templateUrl: './registration-metadata.component.html',
  styleUrls: ['./registration-metadata.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegistrationMetadataComponent {
  /** Emits when user has uploaded registration */
  @Output() readonly registrationSelected = new EventEmitter<void>();

  /** Checks if first and last name has been entered */
  nameValid!: boolean;

  /** Orcid URI converted to regular id */
  orcId?: string;

  /** Text to inform user if a registration file has been uploaded */
  uploadText!: string;

  /** Form control for validating orcid id */
  orcidControl = new FormControl('', [Validators.pattern('^[a-zA-Z0-9]{4}(-[a-zA-Z0-9]{4}){3}$')]);

  /**
   * Creates an instance of registration metadata component.
   * @param model Model state
   * @param registration Registration state
   * @param page Page state
   */
  constructor(
    readonly model: ModelState,
    readonly registration: RegistrationState,
    readonly page: PageState,
  ) {
    page.user$.subscribe((user) => {
      this.checkNameValid(user);
      this.orcId = page.uriToOrcid(user.orcidId);
    });
    registration.state$.subscribe((reg) => {
      this.uploadText = reg.initialRegistration ? 'File(s) uploaded' : 'No file(s) uploaded';
    });
  }

  /**
   * Error message to inform user if orcid is invalid
   * @returns Error message
   */
  getErrorMessage(): string {
    return this.orcidControl.hasError('pattern') ? 'Not a valid ORCID' : '';
  }

  /**
   * Updates orcid value
   * @param value Orcid value entered
   */
  updateOrcid(value: string): void {
    this.page.setOrcidId(value);
  }

  /**
   * Emits registrationSelected and calls editRegistration in state
   * @param event Registration uploaded
   */
  handleRegistrationUpload(reg: SpatialEntityJsonLd): void {
    this.registrationSelected.emit();
    this.registration.editRegistration(reg);
  }

  /**
   * Checks to see if a first and last name has been entered
   * @param event Name input event
   */
  checkNameValid(event: Pick<Person, 'firstName' | 'lastName'>): void {
    this.nameValid = event.firstName.length > 0 && event.lastName.length > 0;
  }

  /**
   * Updates current sex selected
   * @param label Sex selected
   */
  setSexFromLabel(label: 'Female' | 'Male'): void {
    this.model.setSex(label.toLowerCase() as 'male' | 'female');
  }
}
<div class="author-section">
  <h2 class="section-title">Author Data</h2>

  <ccf-name-input [name]="$any(page.user$ | async)" (nameChange)="page.setUserName($event); checkNameValid($event)">
  </ccf-name-input>

  <mat-form-field class="orcid-input">
    <mat-label>ORCID identifier (optional)</mat-label>
    <input
      matInput
      class="input"
      [value]="orcId"
      [formControl]="orcidControl"
      (input)="updateOrcid($any($event.target).value)"
      matTooltip="Add ORCID id."
      maxlength="19"
    />
    <mat-error *ngIf="orcidControl.invalid">{{ getErrorMessage() }}</mat-error>
  </mat-form-field>
</div>

<div class="donor-section">
  <h2 class="section-title">Donor Data</h2>

  <div class="sex-toggle">
    <div class="label">Donor Sex:</div>
    <mat-radio-group class="radio-group" [value]="model.sex$ | async" (change)="setSexFromLabel($event.value)">
      <mat-radio-button class="radio" value="male">Male</mat-radio-button>
      <mat-radio-button class="radio" value="female">Female</mat-radio-button>
    </mat-radio-group>
  </div>

  <div class="organ-selector">
    <div class="label">Select an organ:</div>
    <mat-form-field class="form-field" appearance="fill" subscriptSizing="dynamic">
      <div *ngIf="(model.organ$ | async) === undefined" class="label">Organs</div>
      <mat-select
        disableOptionCentering="true"
        panelClass="organ-select"
        [value]="model.organ$ | async"
        (selectionChange)="model.setOrgan($event.value); model.setOrganDefaults()"
        hideSingleSelectionIndicator="true"
      >
        <mat-option class="organ-select-option" *ngFor="let organ of page.organOptions$ | async" [value]="organ">
          {{ organ.name }}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>

  <div class="upload-registration">
    <div class="label">Upload previous registration data (optional):</div>

    <ccf-json-file-reader
      (parsedJson)="handleRegistrationUpload($any($event))"
      label="Upload"
      matTooltip="Upload a preexisting registration"
    ></ccf-json-file-reader>

    <div>{{ uploadText }}</div>
  </div>
</div>

./registration-metadata.component.scss

:host {
  display: flex;
  flex-direction: column;
  gap: 2rem;

  .section-title {
    font-weight: 400;
    line-height: 1.5rem;
    margin: 0;
    padding-bottom: 1.5rem;
  }

  .label {
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.5rem;
  }

  ::ng-deep .mat-mdc-form-field-infix {
    padding-bottom: 0 !important;
    min-height: inherit;
  }

  ::ng-deep .mdc-text-field {
    padding: 0;
    padding-bottom: 0.3rem !important;
  }

  .author-section {
    display: flex;
    flex-direction: column;

    .orcid-input {
      width: 100%;
      font-size: 1rem;
    }
  }

  .donor-section {
    display: flex;
    flex-direction: column;

    .sex-toggle {
      display: flex;
      align-items: center;
      padding-bottom: 1.5rem;

      .label {
        padding-right: 1rem;
      }

      mat-radio-group {
        display: flex;
        gap: 3rem;
      }
    }

    .organ-selector {
      padding-bottom: 1.5rem;

      ::ng-deep .mat-mdc-select-value {
        font-size: 1rem;
      }
    }

    .upload-registration {
      display: flex;
      flex-direction: column;
      gap: 1rem;

      ccf-json-file-reader {
        ::ng-deep button {
          width: 10rem;
          height: 2rem;
          padding: 0.25rem 1rem;
          border-radius: 0.125rem;
        }
      }
    }
  }

  ::ng-deep .mdc-line-ripple::before,
  .mdc-line-ripple::after {
    border-bottom-width: 0.125rem !important;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""