File

src/app/modules/results-browser/donor-card/donor-card.component.ts

Description

Donor card component which displays data from a patient

Metadata

Index

Properties
Methods
Inputs
Outputs
HostBindings

Constructor

constructor(ga: GoogleAnalyticsService)

Creates an instance of donor card component.

Parameters :
Name Type Optional Description
ga GoogleAnalyticsService No

Analytics service

Inputs

color
Type : string

Allows color of the checkbox background to be set from outside the component

expanded
Type : boolean
Default value : false

Allows the expanded state of the card to be set from outside the component

highlighted
Type : boolean
Default value : false
selected
Type : boolean
Default value : false

Allows the selected state to be set from outside the component

tissueBlock
Type : TissueBlockResult

Tissue Block to generate the donor card from

Outputs

checked
Type : EventEmitter

Emits the new checked state whenever it changes

linkClick
Type : EventEmitter

Emit the url of any link when clicked.

HostBindings

class
Type : "ccf-donor-card"
Default value : 'ccf-donor-card'

HTML Class Name

Methods

handleCheckbox
handleCheckbox()

Handles the logic that needs to run when the checkbox is clicked on.

Returns : void
linkHandler
linkHandler(url: string)

Handles what happens when an info card is clicked. Passes up the link click event unless the card isn't selected In which case it selects it for ease of use.

Parameters :
Name Type Optional Description
url string No

the URL to emit up.

Returns : void
toggleExpansion
toggleExpansion()

Ensures that the expanded variable is only changed if selected first.

Returns : void

Properties

Readonly clsName
Type : string
Default value : 'ccf-donor-card'
Decorators :
@HostBinding('class')

HTML Class Name

hoverState
Type : string
Default value : ''

To keep track of which element, if any, are hovered over.

import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { TissueBlockResult } from 'ccf-database';
import { GoogleAnalyticsService } from 'ngx-google-analytics';

/**
 * Donor card component which displays data from a patient
 */
@Component({
  selector: 'ccf-donor-card',
  templateUrl: './donor-card.component.html',
  styleUrls: ['./donor-card.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DonorCardComponent {
  /** HTML Class Name */
  @HostBinding('class') readonly clsName = 'ccf-donor-card';

  /** Tissue Block to generate the donor card from */
  @Input() tissueBlock!: TissueBlockResult;

  /** Allows the selected state to be set from outside the component */
  @Input() selected = false;

  /** Allows color of the checkbox background to be set from outside the component */
  @Input() color!: string;

  /** Allows the expanded state of the card to be set from outside the component */
  @Input() expanded = false;

  @Input() highlighted = false;

  /** Emits the new checked state whenever it changes */
  @Output() readonly checked = new EventEmitter<boolean>();

  /** Emit the url of any link when clicked. */
  @Output() readonly linkClick = new EventEmitter<string>();

  /** To keep track of which element, if any, are hovered over. */
  hoverState = '';

  /**
   * Creates an instance of donor card component.
   *
   * @param ga Analytics service
   */
  constructor(private readonly ga: GoogleAnalyticsService) {}

  /**
   * Handles the logic that needs to run when the checkbox is clicked on.
   */
  handleCheckbox(): void {
    this.selected = !this.selected;
    this.ga.event('selected_toggled', 'donor_card', this.tissueBlock.label, +this.selected);
    this.checked.emit(this.selected);
    this.expanded = false;
  }

  /**
   * Ensures that the expanded variable is only changed if selected first.
   */
  toggleExpansion(): void {
    if (this.selected) {
      this.expanded = !this.expanded;
      this.ga.event('expanded_toggled', 'donor_card', this.tissueBlock.label, +this.expanded);
    }
  }

  /**
   * Handles what happens when an info card is clicked.
   * Passes up the link click event unless the card isn't selected
   * In which case it selects it for ease of use.
   *
   * @param url the URL to emit up.
   */
  linkHandler(url: string): void {
    this.ga.event('link_clicked', 'donor_card', this.tissueBlock.label);
    if (this.selected) {
      this.linkClick.emit(url);
    } else {
      this.selected = true;
      this.checked.emit(this.selected);
    }
  }
}
<div class="main-container">
  <div
    class="checkbox-background"
    [class.selected]="selected"
    [class.highlighted]="highlighted"
    [ngStyle]="{ 'background-color': selected ? color : 'transparent' }"
    (click)="handleCheckbox()"
  >
    <mat-checkbox [checked]="selected" class="checkbox" [class.checkselected]="selected"></mat-checkbox>
  </div>

  <div
    class="hoverable default-padding donor mat-elevation-z2"
    [class.hover-enabled]="selected"
    [class.expanded]="expanded"
    [class.highlighted]="highlighted"
  >
    <div class="d-flex">
      <mat-icon class="icon-size icon-dark mr-5">person</mat-icon>

      <div class="donor-info">
        <div class="title description">{{ tissueBlock.donor.label }}</div>
        <div class="description">{{ tissueBlock.donor.description }}</div>
      </div>
    </div>
    <div class="hover-state mat-elevation-z4" (click)="linkHandler(tissueBlock.donor.link)">
      <div class="hover-title">DONOR</div>
      <mat-icon class="icon-size hover-icon">open_in_new</mat-icon>
    </div>

    <mat-icon (click)="toggleExpansion()" class="icon-size ml-5 selectable" *ngIf="selected">{{
      expanded ? 'expand_less' : 'expand_more'
    }}</mat-icon>
  </div>
</div>

<ng-container *ngIf="expanded">
  <div class="expanded-view mat-elevation-z2 align-end">
    <div class="info-block hover-enabled default-padding">
      <mat-icon class="icon-size icon-dark mr-5">bubble_chart</mat-icon>
      <div class="text-content">
        <div class="description">{{ tissueBlock.label }}</div>
        <div class="description">{{ tissueBlock.description }}</div>
      </div>

      <div class="hover-state mat-elevation-z4" (click)="linkHandler(tissueBlock.link)">
        <div class="hover-title">TISSUE BLOCK</div>
        <mat-icon class="icon-size hover-icon">open_in_new</mat-icon>
      </div>
    </div>

    <ccf-tissue-section-vis
      *ngIf="tissueBlock.sections.length > 1"
      [totalTissueSections]="tissueBlock.sectionCount"
      [tissueSections]="tissueBlock.sections"
    ></ccf-tissue-section-vis>

    <ng-container *ngIf="tissueBlock.datasets.length > 0">
      <ccf-thumbnail-carousel (linkClicked)="linkHandler($event.link)" class="mt-05" [data]="tissueBlock.datasets">
      </ccf-thumbnail-carousel>
    </ng-container>
  </div>

  <div class="expanded-view w-80 mat-elevation-z2 align-end" *ngFor="let section of tissueBlock.sections">
    <div class="default-padding info-block hover-enabled">
      <mat-icon class="icon-size mr-5 icon-light">bubble_chart</mat-icon>
      <div class="text-content">
        <div class="description">{{ section.label }}</div>
        <div class="description">{{ section.description }}</div>
      </div>

      <div class="hover-state mat-elevation-z4" (click)="linkHandler(section.link)">
        <div class="hover-title">TISSUE SECTION</div>
        <mat-icon class="icon-size hover-icon">open_in_new</mat-icon>
      </div>
    </div>

    <ng-container *ngIf="section.datasets.length > 0">
      <ccf-thumbnail-carousel (linkClicked)="linkHandler($event.link)" class="mt-05" [data]="section.datasets">
      </ccf-thumbnail-carousel>
    </ng-container>
  </div>
</ng-container>

./donor-card.component.scss

:host {
  width: 100%;

  .main-container {
    display: flex;
    min-height: 3rem;
    width: 100%;
    align-items: center;
    padding-left: 0.5rem;
  }

  .checkbox-background {
    height: 2rem;
    width: 2rem;
    border-radius: 50%;
    margin-right: 0.5rem;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;

    &.highlighted {
      ::ng-deep .mdc-checkbox__ripple {
        opacity: 0.04;
      }
    }
  }

  .align-end {
    margin-left: auto;
  }

  .info-block {
    display: flex;
    font-size: 0.75rem;
    line-height: 1rem;
    width: 100%;
    align-items: center;

    &:not(:first-child) {
      margin-top: 0.5rem;
    }

    .text-content {
      .title {
        font-weight: 600;
      }
    }
  }

  .donor {
    display: flex;
    font-size: 0.75rem;
    line-height: 1rem;
    align-items: center;
    flex-grow: 1;
    height: 2.5rem;

    &:hover,
    &.highlighted {
      box-shadow:
        0px 6px 2px -2px rgba(0, 0, 0, 0.2),
        0px 4px 4px 0px rgba(0, 0, 0, 0.14),
        0px 2px 10px 0px rgba(0, 0, 0, 0.12);
    }

    .hover-state {
      width: 19.5rem !important;
    }

    .donor-info {
      .title {
        font-weight: 600;
      }
    }
  }

  .hoverable {
    position: relative;
  }

  .hover-enabled {
    position: relative;

    &:hover {
      .hover-state {
        opacity: 1;
      }
    }
  }

  .hover-state {
    transition: opacity 0.15s ease-in-out;
    opacity: 0;
    cursor: pointer;
    position: absolute;
    height: 100%;
    width: 100%;
    top: 0;
    margin-left: -0.5rem;
    align-items: center;
    display: flex;
    justify-content: flex-end;
    padding-right: 1rem;
    font-size: 0.75rem;

    .hover-title {
      font-weight: lighter;
    }

    .hover-icon {
      margin-left: 1rem;
    }
  }

  .default-padding {
    padding: 0.5rem;
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
  }

  .expanded-view {
    margin-top: 0.25rem;
    width: 85%;
    margin-bottom: 0.25rem;
  }

  .d-flex {
    display: flex;
    align-items: center;
  }

  .icon-size {
    height: 1.5rem;
    width: 1.5rem;
    font-size: 1.5rem;
  }

  .selectable {
    cursor: pointer;
  }

  .w-80 {
    width: 80% !important;

    .info-block {
      .text-content {
        .description {
          width: 16rem !important;
        }
      }
    }
  }

  .ml-5 {
    margin-left: 0.5rem;
  }

  .mr-5 {
    margin-right: 0.5rem;
  }

  .mt-05 {
    margin-top: 0.5rem;
  }

  .description {
    width: 17rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""