src/app/modules/results-browser/results-browser/results-browser.component.ts
ResultsBrowser is the container component in charge of rendering the label and stats of the results as well as handling the virtual scrolling and click emitters of ResultsBrowserItems.
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-results-browser |
styleUrls | ./results-browser.component.scss |
templateUrl | ./results-browser.component.html |
Properties |
Methods |
Inputs |
Outputs |
constructor(ga: GoogleAnalyticsService)
|
||||||||
Creates an instance of results browser component.
Parameters :
|
aggregateData | |
Type : Immutable<AggregateResult[]>
|
|
Input used to add a list of stats at the top the results browser |
header | |
Type : boolean
|
|
highlighted | |
Type : string
|
|
listResults | |
Type : Immutable<ListResult[]>
|
|
Input array of List Results to display |
resultLabel | |
Type : string
|
|
Input allowing the title of the result browser to be set outside of the component |
itemHovered | |
Type : EventEmitter
|
|
itemUnhovered | |
Type : EventEmitter
|
|
linkClicked | |
Type : EventEmitter
|
|
Output emitting the result that was clicked on and its relevant information. Used for opening and rendering the result viewer. |
listResultDeselected | |
Type : EventEmitter
|
|
Output emitting the link result deselected |
listResultSelected | |
Type : EventEmitter
|
|
Output emitting the link result selected |
asMutable | ||||||
asMutable(value: Immutable
|
||||||
Type parameters :
|
||||||
Parameters :
Returns :
T
|
handleHover | ||||||
handleHover(id: string)
|
||||||
Parameters :
Returns :
void
|
handleLinkClick | ||||||||
handleLinkClick(link: string)
|
||||||||
Notifies on link click
Parameters :
Returns :
void
|
handleSelection | ||||||||||||
handleSelection(result: Immutable<ListResult>, selected: boolean)
|
||||||||||||
Notifies listeners when a selection/deselection is made
Parameters :
Returns :
void
|
handleUnhover |
handleUnhover()
|
Returns :
void
|
onScroll | ||||||||
onScroll(event: Event)
|
||||||||
Handles the scroll event to detect when scroll is at the bottom.
Parameters :
Returns :
void
|
import { Immutable } from '@angular-ru/common/typings/immutability';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { AggregateResult } from 'ccf-database';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
import { ListResult } from '../../../core/models/list-result';
/**
* ResultsBrowser is the container component in charge of rendering the label and stats of
* the results as well as handling the virtual scrolling and click emitters of
* ResultsBrowserItems.
*/
@Component({
selector: 'ccf-results-browser',
templateUrl: './results-browser.component.html',
styleUrls: ['./results-browser.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ResultsBrowserComponent {
/**
* Input array of List Results to display
*/
@Input() listResults!: Immutable<ListResult[]>;
/**
* Input used to add a list of stats at the top the results browser
*/
@Input() aggregateData!: Immutable<AggregateResult[]>;
/**
* Input allowing the title of the result browser to be set outside of the component
*/
@Input() resultLabel!: string;
@Input() highlighted!: string;
@Input() header!: boolean;
/**
* Output emitting the result that was clicked on and its relevant information.
* Used for opening and rendering the result viewer.
*/
@Output() readonly linkClicked = new EventEmitter<string>();
/**
* Output emitting the link result selected
*/
@Output() readonly listResultSelected = new EventEmitter<Immutable<ListResult>>();
/**
* Output emitting the link result deselected
*/
@Output() readonly listResultDeselected = new EventEmitter<Immutable<ListResult>>();
@Output() readonly itemHovered = new EventEmitter<string>();
@Output() readonly itemUnhovered = new EventEmitter();
/**
* Keeps track of whether or not the virtual scroll viewport is scrolled all the way to the bottom.
* Used to determine whether or not to render the gradient at the bottom.
*/
atScrollBottom = false;
/**
* Creates an instance of results browser component.
*
* @param ga Analytics service
*/
constructor(private readonly ga: GoogleAnalyticsService) {}
/**
* Notifies listeners when a selection/deselection is made
*
* @param result the list result
* @param selected whether to select or deselect the result
*/
handleSelection(result: Immutable<ListResult>, selected: boolean): void {
this.ga.event('list_result_selected', 'results_browser', this.resultLabel, +selected);
if (selected) {
this.listResultSelected.next(result);
} else {
this.listResultDeselected.next(result);
}
}
/**
* Notifies on link click
*
* @param link the link clicked
*/
handleLinkClick(link: string): void {
this.linkClicked.emit(link);
}
/**
* Handles the scroll event to detect when scroll is at the bottom.
*
* @param event The scroll event.
*/
onScroll(event: Event): void {
if (!event.target) {
return;
}
const { clientHeight, scrollHeight, scrollTop } = event.target as Element;
const diff = scrollHeight - scrollTop - clientHeight;
this.atScrollBottom = diff < 64;
}
handleHover(id: string): void {
this.itemHovered.emit(id);
}
handleUnhover(): void {
this.itemUnhovered.emit();
}
asMutable<T>(value: Immutable<T>): T {
return value as T;
}
}
<div class="results-browser-container">
<div class="stat-box">
<div id="title">{{ resultLabel }}</div>
<div class="stat-row" *ngFor="let stat of aggregateData">
<div class="stat-value">{{ stat.count }}</div>
<div class="stat-label">{{ stat.label }}</div>
</div>
</div>
<div class="results-browser-list" [class.header-hidden]="!header" (scroll)="onScroll($event)">
<div
class="browser-item-container"
(mouseenter)="handleHover(result.tissueBlock.spatialEntityId)"
(mouseleave)="handleUnhover()"
*ngFor="let result of listResults"
>
<ccf-donor-card
[tissueBlock]="asMutable(result.tissueBlock)"
[selected]="result.selected"
[color]="result.color ?? ''"
(checked)="handleSelection(result, $event)"
(linkClick)="handleLinkClick($event)"
[highlighted]="result.tissueBlock.spatialEntityId === highlighted"
>
</ccf-donor-card>
</div>
</div>
<div class="scroll-gradient" [class.hidden]="!!atScrollBottom"></div>
</div>
./results-browser.component.scss
.results-browser-container {
display: flex;
flex-direction: column;
height: calc(100% - 3rem);
padding: 0 1.5rem 1.5rem 1.5rem;
.stat-box {
margin-bottom: 1.5rem;
line-height: 1.25;
min-height: 7.75rem;
#title {
font-size: 1.25rem;
margin-bottom: 0.75rem;
}
.stat-row {
display: flex;
flex-direction: row;
.stat-value {
margin-right: 1rem;
width: 5.5rem;
text-align: right;
font-weight: 600;
}
.stat-label {
font-weight: 300;
}
}
}
.results-browser-list {
display: flex;
flex-direction: column;
overflow-y: auto;
scrollbar-width: thin;
padding-right: 0.5rem;
height: calc(100vh - 20rem);
&.header-hidden {
height: calc(100vh - 16rem);
}
.browser-item-container {
width: 100%;
}
}
.scroll-gradient {
position: absolute;
height: 3rem;
width: 95%;
bottom: 0;
pointer-events: none;
&.hidden {
display: none;
}
}
}