src/app/components/home/home.component.ts
AfterViewInit
OnDestroy
selector | app-home |
styleUrls | ./home.component.scss |
templateUrl | ./home.component.html |
Properties |
Methods |
constructor(configService: ConfigService, router: Router, ga: GoogleAnalyticsService)
|
||||||||||||
Defined in src/app/components/home/home.component.ts:39
|
||||||||||||
Parameters :
|
goToPlayground |
goToPlayground()
|
Returns :
void
|
openData |
openData()
|
Defined in src/app/components/home/home.component.ts:99
|
Returns :
void
|
openDataOld |
openDataOld()
|
Returns :
void
|
openDocs |
openDocs()
|
Defined in src/app/components/home/home.component.ts:94
|
Returns :
void
|
openGithub |
openGithub()
|
Defined in src/app/components/home/home.component.ts:89
|
Returns :
void
|
seekVideo |
seekVideo(seconds: number, id: number)
|
Defined in src/app/components/home/home.component.ts:79
|
Returns :
void
|
Public configService |
Type : ConfigService
|
Defined in src/app/components/home/home.component.ts:42
|
CONTIRBUTORS |
Default value : CONTIRBUTORS
|
Defined in src/app/components/home/home.component.ts:22
|
copyrightYear |
Default value : new Date().getFullYear()
|
Defined in src/app/components/home/home.component.ts:32
|
dataVersion |
Type : string
|
Default value : 'latest'
|
Defined in src/app/components/home/home.component.ts:20
|
faEnvelope |
Default value : faEnvelope
|
Defined in src/app/components/home/home.component.ts:30
|
faGithub |
Default value : faGithub
|
Defined in src/app/components/home/home.component.ts:28
|
faGlobe |
Default value : faGlobe
|
Defined in src/app/components/home/home.component.ts:27
|
faLinkedin |
Default value : faLinkedin
|
Defined in src/app/components/home/home.component.ts:26
|
faPhone |
Default value : faPhone
|
Defined in src/app/components/home/home.component.ts:29
|
Public ga |
Type : GoogleAnalyticsService
|
Defined in src/app/components/home/home.component.ts:44
|
IMAGES |
Default value : IMAGES
|
Defined in src/app/components/home/home.component.ts:23
|
masterSheetLink |
Type : string
|
Default value : ''
|
Defined in src/app/components/home/home.component.ts:33
|
player |
Type : YouTubePlayer
|
Decorators :
@ViewChild('tutorialVideo')
|
Defined in src/app/components/home/home.component.ts:37
|
sheetOptions |
Type : SheetDetails[]
|
Default value : []
|
Defined in src/app/components/home/home.component.ts:34
|
VIDEO_ACTIONS |
Default value : VIDEO_ACTIONS
|
Defined in src/app/components/home/home.component.ts:21
|
videoContainer |
Type : ElementRef<HTMLElement>
|
Decorators :
@ViewChild('tutorialVideoContainer')
|
Defined in src/app/components/home/home.component.ts:36
|
videoSectionSelected |
Type : number
|
Default value : 0
|
Defined in src/app/components/home/home.component.ts:24
|
window |
Default value : window
|
Defined in src/app/components/home/home.component.ts:19
|
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { YouTubePlayer } from '@angular/youtube-player';
import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons';
import { faEnvelope } from '@fortawesome/free-regular-svg-icons';
import { faGlobe, faPhone } from '@fortawesome/free-solid-svg-icons';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
import { ConfigService } from '../../app-config.service';
import { GaAction, GaCategory } from '../../models/ga.model';
import { SheetDetails } from '../../models/sheet.model';
import { CONTIRBUTORS, IMAGES, VIDEO_ACTIONS } from '../../static/home';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
})
export class HomeComponent implements AfterViewInit, OnDestroy {
window = window;
dataVersion = 'latest';
VIDEO_ACTIONS = VIDEO_ACTIONS;
CONTIRBUTORS = CONTIRBUTORS;
IMAGES = IMAGES;
videoSectionSelected = 0;
faLinkedin = faLinkedin;
faGlobe = faGlobe;
faGithub = faGithub;
faPhone = faPhone;
faEnvelope = faEnvelope;
copyrightYear = new Date().getFullYear();
masterSheetLink = '';
sheetOptions: SheetDetails[] = [];
@ViewChild('tutorialVideoContainer') videoContainer!: ElementRef<HTMLElement>;
@ViewChild('tutorialVideo') player!: YouTubePlayer;
private videoContainerResizeObserver?: ResizeObserver;
constructor(
public configService: ConfigService,
private readonly router: Router,
public ga: GoogleAnalyticsService,
) {
this.configService.config$.subscribe((config) => {
this.masterSheetLink = config['masterSheetLink'] as string;
});
this.configService.sheetConfiguration$.subscribe((sheetOptions) => {
this.sheetOptions = sheetOptions;
});
}
ngAfterViewInit(): void {
const actionsDiv = document.getElementById('actionsHeight');
if (actionsDiv) {
actionsDiv.style.maxHeight = `${this.player.height + 50}px`;
actionsDiv.style.overflowY = 'auto';
}
this.videoContainerResizeObserver = new ResizeObserver((entries) => {
const [
{
contentBoxSize: [{ inlineSize: width, blockSize: height }],
},
] = entries;
this.player.width = width;
this.player.height = height;
});
this.videoContainerResizeObserver.observe(this.videoContainer.nativeElement);
}
ngOnDestroy(): void {
this.videoContainerResizeObserver?.disconnect();
}
seekVideo(seconds: number, id: number) {
this.videoSectionSelected = id;
this.player.pauseVideo();
this.player.seekTo(seconds, true);
this.player.playVideo();
this.ga.event(GaAction.CLICK, GaCategory.HOME, `Jump to video section: ${VIDEO_ACTIONS[id].header}`);
}
openGithub() {
window.open('https://github.com/hubmapconsortium/ccf-asct-reporter', '_blank');
this.ga.event(GaAction.NAV, GaCategory.HOME, 'Open Github');
}
openDocs() {
this.router.navigate(['/docs']);
this.ga.event(GaAction.NAV, GaCategory.HOME, 'Open Docs');
}
openData() {
window.open(this.masterSheetLink, '_blank');
this.ga.event(GaAction.NAV, GaCategory.HOME, 'Open Master Tables');
}
openDataOld() {
window.open(
'https://docs.google.com/spreadsheets/d/1j_SLhFipRWUcRZrCDfNH15OWoiLf7cJks7NVppe3htI/edit#gid=1268820100',
'_blank',
);
this.ga.event(GaAction.NAV, GaCategory.HOME, 'Open Old Data Tables');
}
goToPlayground() {
this.router.navigate(['/vis'], {
queryParams: { playground: 'true', selectedOrgans: 'example' },
queryParamsHandling: 'merge',
});
this.ga.event(GaAction.NAV, GaCategory.HOME, 'Launch Playground Tool');
}
}
<div class="home-container">
<!-- NAVBAR -->
<div class="w-100 py-3 px-5">
<div class="d-flex justify-content-between align-items-center w-100">
<div class="navbar-logo">
<img src="./assets/logo-light.svg" alt="" class="w-75 logo-link" routerLink="/" />
</div>
<div class="navbar-options">
<a (click)="openDocs()" class="text-white docs">Docs</a>
<a (click)="openGithub()" class="ml-4 text-white github">GitHub</a>
<a class="ml-4 text-white menu" [matMenuTriggerFor]="nestedMenu.childMenu">
Master Tables
<mat-icon class="icon">expand_more</mat-icon>
</a>
<app-table-nested-menu
#nestedMenu
[sheetDetails]="(configService.allSheetConfigurations$ | async) ?? []"
></app-table-nested-menu>
<a
(click)="
window.open(
'https://docs.google.com/spreadsheets/d/1j_SLhFipRWUcRZrCDfNH15OWoiLf7cJks7NVppe3htI/edit#gid=1268820100'
)
"
class="text-white ml-4"
>Old Tables</a
>
</div>
</div>
</div>
<!-- BACKGROUND -->
<div id="background"></div>
<!-- TITLE -->
<div class="container w-100">
<div class="d-flex justify-content-center align-items-center w-100 flex-column">
<div class="title1 mt-5 pt-4">ASCT+B REPORTER</div>
<div class="pt-2 muted">v2.8</div>
<div class="pt-2 text-center desc">
The CCF ASCT+B Reporter is a visualization tool for displaying anatomical structures, cell types, and biomarker
(ASCT+B) authored by domain experts for different human organs. The tables are used to develop a common
coordinate framework (CCF) of the healthy human body, see also
<span class="linker" (click)="window.open('https://hubmapconsortium.github.io/ccf', '_blank')"
>Hubmap Consortium website</span
>.
</div>
<div class="title-btn mt-4 pt-2">
<button mat-flat-button class="go-to-vis" routerLink="/vis">Go to Visualization</button>
<button mat-flat-button class="go-to-vis" (click)="goToPlayground()">Launch Playground</button>
<mat-menu #menu="matMenu" class="organMenu">
<button
mat-menu-item
*ngFor="let option of sheetOptions"
class="menu-button-item"
routerLink="/vis"
[queryParams]="{ sheet: option.name, version: dataVersion }"
>
<span>{{ option.title }}</span>
</button>
</mat-menu>
</div>
</div>
</div>
<!-- IMAGES -->
<div class="container w-100 h-50 position-relative">
<div class="d-flex justify-content-center align-items-center w-100 h-100 mt-5 pt-3 img-contail">
<img [src]="img.path" alt="" class="w-100 home-img h-100" *ngFor="let img of IMAGES" [alt]="img.alt" />
</div>
</div>
<!-- ABOUT -->
<div class="w-100 my-5 py-5 px-5 about-main-container" id="about">
<div class="text-center container">
<div class="pb-2"></div>
<span class="title2">ABOUT</span>
<p class="mt-3 text-secondary">
The ASCT+B Reporter is a state-of-the-art visualization tool. The video gives an overview of the functionalities
listed below. Please use the selectors below to skip to any section you’d want to specifically know about.
</p>
</div>
<div class="pt-5 mt-3"></div>
<div class="row">
<div class="col-xl-5 col-md-4 col-sm-6">
<div id="actionsHeight" class="pr-3 pl-1">
<div *ngFor="let va of VIDEO_ACTIONS; let i = index">
<button
class="section-selector w-100 my-2"
(click)="seekVideo(va.sec, i)"
[ngClass]="{ 'section-selected': i === videoSectionSelected }"
>
<p class="ss-header">{{ va.header }}</p>
<p class="ss-desc">{{ va.desc }}</p>
</button>
</div>
</div>
</div>
<div class="col-xl-7 col-md-8 col-sm-6">
<div class="w-100 video-tutorial" id="tutorialVideo" #tutorialVideoContainer>
<youtube-player #tutorialVideo videoId="pzUFmDhQEO8" [playerVars]="{ rel: 0, showinfo: 0 }"></youtube-player>
</div>
</div>
</div>
</div>
<!-- SPACING -->
<div class="w-100 mt-5 pt-5"></div>
<!-- CONTRIBUTORS -->
<div class="w-100 my-5 py-5 px-5">
<div class="text-center container">
<p class="title2">CONTRIBUTORS</p>
<p class="mt-3 text-secondary">
Along with various members from the MC-IU Team as well as doctors, researchers and SMEs from various consortia,
below listed are the members of the core team working on building the ASCT+B Reporter
</p>
</div>
<div class="pt-5 container">
<div class="row">
<div class="col-xl-4 col-md-6 col-sm-6 col-lg-4 px-3 mt-4" *ngFor="let con of CONTIRBUTORS; let i = index">
<div class="card text-center con-card">
<div class="card-header">
<img class="contributors-img" alt="" [src]="con.img" alt="sans" width="140px" height="140px" />
</div>
<div class="card-body">
<p class="title4">{{ con.name }}</p>
<p class="desc text-secondary mt-2">
{{ con.desc }}
</p>
<p class="desc text-muted mt-4 profile">
<a class="text-info" [href]="'mailto:' + con.mail">{{ con.mail }}</a>
</p>
</div>
<div class="card-footer border-top">
<div class="d-flex justify-content-center align-items-center">
<div class="mr-2">
<button mat-icon-button class="icon-btn" (click)="window.open(con.link, '_blank')">
<fa-icon [icon]="faGlobe"></fa-icon>
</button>
</div>
<div class="mr-2" *ngIf="con.linkedin">
<button mat-icon-button class="icon-btn" (click)="window.open(con.linkedin, '_blank')">
<fa-icon [icon]="faLinkedin"></fa-icon>
</button>
</div>
<div *ngIf="con.github">
<button mat-icon-button class="icon-btn" (click)="window.open(con.github, '_blank')">
<fa-icon [icon]="faGithub"></fa-icon>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- AFFILIATIONS -->
<div class="my-5 py-5">
<div class="container">
<br />
<div class="text-center">
<p class="title2">AFFILIATIONS</p>
<p class="mt-3 text-secondary">
Various institutions that the CCF ASCT+B Reporter is affiliated with are listed below.
</p>
</div>
<div class="affiliations-image-container p-5">
<div class="row">
<div class="col-lg-4 col-md-4 mt-5">
<img
src="assets/affiliations/iu.jpg"
alt=""
height="100"
class="affiliation-img"
(click)="window.open('https://www.indiana.edu', '_blank')"
/>
</div>
<div class="col-lg-4 col-md-4 mt-5">
<img
src="assets/affiliations/cns.png"
alt=""
class="affiliation-img"
height="100"
(click)="window.open('https://cns.iu.edu', '_blank')"
/>
</div>
<div class="col-lg-4 col-md-4 mt-5">
<img
src="assets/affiliations/hubmap.png"
alt=""
height="100"
class="affiliation-img"
(click)="window.open('https://github.com/hubmapconsortium', '_blank')"
/>
</div>
<br />
</div>
</div>
<br />
</div>
</div>
<!-- FOOTER -->
<app-footer></app-footer>
</div>
./home.component.scss
.example-spacer {
flex: 1 1 auto;
}
.home-container {
width: 100%;
height: 100%;
position: relative;
}
.menu-button-item {
width: 100%;
}
.menu {
position: relative;
color: #fff !important;
cursor: pointer;
margin: 1.5rem !important;
}
.menu:hover {
text-decoration: underline;
}
.icon {
position: absolute;
}
.about-main-container {
position: relative;
}
.video-tutorial {
box-shadow: 0.3125rem 1.25rem 1.875rem #e1e1e1;
border-radius: 0.625rem;
outline: none;
overflow: hidden;
}
.affiliations-image-container {
width: 100%;
text-align: center;
}
.affiliation-img {
cursor: pointer;
}
a {
cursor: pointer;
}
p {
margin: 0;
}
.dark {
color: #262626 !important;
}
.a-nav {
// color: #444a65;
margin-left: 1.875rem;
cursor: pointer;
transition: all 0.2s;
text-decoration: none !important;
font-size: 0.875rem;
color: white;
}
.a-nav:hover {
color: #377eb8;
}
.linker {
color: white;
font-weight: 500;
cursor: pointer;
}
.linker:hover {
text-decoration: underline;
}
.go-to-vis {
padding: 2.3rem 1rem;
font-size: 18pt;
border-radius: 0.625rem;
background-color: #7fd9da;
color: #262626;
font-weight: bold;
margin: 0.5rem 0.5rem;
letter-spacing: 0.02rem;
}
.title-desc {
text-align: justify;
text-justify: inter-word;
color: rgb(164, 164, 164);
font-size: 12pt;
hyphens: auto;
}
.title {
font-size: 4.375rem;
line-height: 4.6875rem;
font-weight: 400;
color: #444a65;
text-align: justify;
margin: 0 auto;
}
@media only screen and (max-width: 1000px) {
.title {
text-align: center;
}
.title-desc {
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
padding-left: 1.25rem;
padding-right: 1.25rem;
}
.title-btn {
display: flex;
width: 100%;
justify-content: center;
}
}
.title1 {
font-family: 'Poppins', sans-serif;
font-size: 5.5rem;
line-height: 5rem;
color: white;
font-weight: 600;
letter-spacing: 0.5rem;
}
.title2 {
font-family: 'Poppins', sans-serif;
font-size: 3.125rem;
line-height: 3.75rem;
color: #262626;
font-weight: 400;
hyphens: auto;
letter-spacing: 0.25rem;
}
.title3 {
font-family: 'Poppins', sans-serif;
font-size: 1.875rem;
line-height: 1.875rem;
color: #262626;
font-weight: 600;
}
.title4 {
font-family: 'Poppins', sans-serif;
font-size: 1.25rem;
line-height: 1.25rem;
color: #262626;
font-weight: 500;
}
.subtitle {
font-size: 1rem;
line-height: 0.9375rem;
color: #e3e3e3;
font-weight: 400;
}
.pro {
border-radius: 50%;
height: 7.5rem;
width: 7.5rem;
object-fit: cover;
border: 0.125rem solid rgb(218, 218, 218);
}
.desc {
font-size: 12pt;
font-weight: 400;
color: white;
line-height: 1.5625rem;
}
.logo1 {
margin-right: 0.625rem;
width: 5.625rem;
cursor: pointer;
color: white;
}
.logo2 {
margin-right: 0.625rem;
width: 6.25rem;
cursor: pointer;
color: white;
}
/* CARDS */
.card {
border: none;
border-radius: 0.625rem;
box-shadow: 0.3125rem 1.75rem 1.5625rem rgba(128, 128, 128, 0.057);
transition: all 0.5s ease;
}
.card:hover {
transition: all 0.5s ease;
box-shadow: 0.3125rem 1.75rem 2.1875rem rgba(128, 128, 128, 0.226);
}
::ng-deep .organMenu {
width: 18.75rem !important;
height: 12.5rem !important;
}
#background {
position: absolute;
top: 0rem;
left: 0rem;
height: 75%;
width: 100%;
background-color: #262626;
z-index: -1;
}
.laptop {
position: relative;
width: 100%;
height: auto;
}
.laptop:after {
content: '';
display: block;
}
.l {
// position: absolute;
width: 100%;
}
.i {
position: absolute;
width: 80%;
left: 7.6875rem;
top: 1.75rem;
z-index: -1;
}
@media (min-width: 576px) {
.i {
position: absolute;
width: 80%;
left: 5.1875rem;
top: 1.125rem;
z-index: -1;
}
}
// Medium devices (tablets, 768px and up)
@media (min-width: 768px) {
.i {
position: absolute;
width: 80%;
left: 6.4375rem;
top: 1.4375rem;
z-index: -1;
}
}
// Extra large devices (large desktops, 1200px and up)
@media (min-width: 1200px) {
.i {
position: absolute;
width: 80%;
left: 7.6875rem;
top: 1.75rem;
z-index: -1;
}
}
.section-selector {
text-align: left;
outline: none;
border: 0.125rem solid #eaeaea;
border-radius: 0.5rem;
padding: 0.625rem 0.625rem 0.625rem 0.625rem;
border-left-width: 0.9375rem;
background-color: white;
transition: all 0.2s;
}
.section-selector:not(.active):hover {
border-color: #444a6590;
}
.section-selector:active {
transform: scale(0.99);
}
.section-selected {
border-color: #444a65 !important;
}
.ss-header {
font-family: 'Poppins', sans-serif;
font-weight: 500;
font-size: 14pt;
padding-bottom: 0.3125rem;
}
.ss-desc {
color: grey;
}
.card-img-top {
max-height: 10vh;
/*not want to take all vertical space*/
object-fit: cover;
/*show all image, autosized, no cut, in available space*/
}
.contributors-img {
border-radius: 50%;
object-fit: cover;
border: 0.1875rem solid #eaeaea;
}
.con-card {
box-shadow: none !important;
border: 0.125rem solid #eaeaea;
border-top-width: 0.9375rem;
border-radius: 0.625rem;
padding: 0.625rem;
height: 30.375rem;
}
.icon-btn {
height: 3.125rem;
width: 3.125rem;
font-size: 1.5625rem;
line-height: 1.875rem;
color: #262626;
}
.text-info {
color: #444a65 !important;
}
#actionsHeight,
.video-tutorial {
height: 450px;
}
.home-img {
position: absolute;
top: 0;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 8s;
animation-name: anim;
-webkit-animation-name: anim;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-iteration-count: infinite;
-webkit-animation-duration: 8s;
}
.home-img:nth-child(1) {
animation-delay: 0s;
-webkit-animation-delay: 0s;
}
.home-img:nth-child(2) {
animation-delay: 4s;
-webkit-animation-delay: 4s;
}
.home-img:nth-child(3) {
animation-delay: 8s;
-webkit-animation-delay: 8s;
}
.home-img:nth-child(4) {
animation-delay: 12s;
-webkit-animation-delay: 12s;
}
.home-img:nth-child(5) {
animation-delay: 16s;
-webkit-animation-delay: 16s;
}
@keyframes anim {
0% {
opacity: 0;
z-index: 100;
}
15% {
opacity: 1;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
z-index: 1;
}
}
.navbar-options {
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.docs,
.github {
padding-left: 1rem;
}
}
.muted {
color: #6c757d;
}
.profile {
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
}