From 04ef96f8b15ad0a2423237b60d487b39b0fe9b4e Mon Sep 17 00:00:00 2001 From: sagely1 <114952739+sagely1@users.noreply.github.com> Date: Wed, 25 Sep 2024 12:59:56 -0700 Subject: [PATCH] feat(agora): migration Home component (AG-1547) (#2855) --- apps/agora/app/src/app/app.routes.ts | 9 + libs/agora/home/.eslintrc.json | 40 ++++ libs/agora/home/README.md | 7 + libs/agora/home/jest.config.ts | 23 +++ libs/agora/home/project.json | 27 +++ libs/agora/home/src/index.ts | 1 + libs/agora/home/src/lib/home.component.html | 74 ++++++++ libs/agora/home/src/lib/home.component.scss | 174 ++++++++++++++++++ .../agora/home/src/lib/home.component.spec.ts | 22 +++ libs/agora/home/src/lib/home.component.ts | 43 +++++ libs/agora/home/src/lib/home.routes.ts | 4 + libs/agora/home/src/test-setup.ts | 1 + libs/agora/home/tsconfig.json | 28 +++ libs/agora/home/tsconfig.lib.json | 12 ++ libs/agora/home/tsconfig.spec.json | 11 ++ tsconfig.base.json | 1 + 16 files changed, 477 insertions(+) create mode 100644 libs/agora/home/.eslintrc.json create mode 100644 libs/agora/home/README.md create mode 100644 libs/agora/home/jest.config.ts create mode 100644 libs/agora/home/project.json create mode 100644 libs/agora/home/src/index.ts create mode 100644 libs/agora/home/src/lib/home.component.html create mode 100644 libs/agora/home/src/lib/home.component.scss create mode 100644 libs/agora/home/src/lib/home.component.spec.ts create mode 100644 libs/agora/home/src/lib/home.component.ts create mode 100644 libs/agora/home/src/lib/home.routes.ts create mode 100644 libs/agora/home/src/test-setup.ts create mode 100644 libs/agora/home/tsconfig.json create mode 100644 libs/agora/home/tsconfig.lib.json create mode 100644 libs/agora/home/tsconfig.spec.json diff --git a/apps/agora/app/src/app/app.routes.ts b/apps/agora/app/src/app/app.routes.ts index 31179cb8f8..dca237263d 100644 --- a/apps/agora/app/src/app/app.routes.ts +++ b/apps/agora/app/src/app/app.routes.ts @@ -1,6 +1,15 @@ import { Route } from '@angular/router'; export const routes: Route[] = [ + { + path: '', + loadChildren: () => import('@sagebionetworks/agora/home').then((routes) => routes.routes), + data: { + title: "Agora | Explore Alzheimer's Disease Genes", + description: + "Explore transcriptomic, proteomic, and metabolomic evidence for whether or not genes are associated with Alzheimer's disease using the Agora portal.", + }, + }, { path: 'about', loadChildren: () => import('@sagebionetworks/agora/about').then((routes) => routes.routes), diff --git a/libs/agora/home/.eslintrc.json b/libs/agora/home/.eslintrc.json new file mode 100644 index 0000000000..5d8c12012f --- /dev/null +++ b/libs/agora/home/.eslintrc.json @@ -0,0 +1,40 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "env": { + "jest": true + }, + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates", + "plugin:jest/recommended" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "agora", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "agora", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/libs/agora/home/README.md b/libs/agora/home/README.md new file mode 100644 index 0000000000..85de2f2050 --- /dev/null +++ b/libs/agora/home/README.md @@ -0,0 +1,7 @@ +# agora-home + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test agora-home` to execute the unit tests. diff --git a/libs/agora/home/jest.config.ts b/libs/agora/home/jest.config.ts new file mode 100644 index 0000000000..0ede43b8e1 --- /dev/null +++ b/libs/agora/home/jest.config.ts @@ -0,0 +1,23 @@ +/* eslint-disable */ +export default { + displayName: 'agora-home', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../../coverage/libs/agora/home', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/libs/agora/home/project.json b/libs/agora/home/project.json new file mode 100644 index 0000000000..75792f8785 --- /dev/null +++ b/libs/agora/home/project.json @@ -0,0 +1,27 @@ +{ + "name": "agora-home", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/agora/home/src", + "prefix": "agora", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/agora/home"], + "options": { + "jestConfig": "libs/agora/home/jest.config.ts" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "lint-fix": { + "executor": "@nx/eslint:lint", + "options": { + "fix": true + } + } + }, + "tags": ["type:feature", "scope:agora", "language:typescript"], + "implicitDependencies": [] +} diff --git a/libs/agora/home/src/index.ts b/libs/agora/home/src/index.ts new file mode 100644 index 0000000000..8fc032ecba --- /dev/null +++ b/libs/agora/home/src/index.ts @@ -0,0 +1 @@ +export * from './lib/home.routes'; diff --git a/libs/agora/home/src/lib/home.component.html b/libs/agora/home/src/lib/home.component.html new file mode 100644 index 0000000000..e0a2c04927 --- /dev/null +++ b/libs/agora/home/src/lib/home.component.html @@ -0,0 +1,74 @@ +<div id="home-page"> + <div class="section"> + <div class="background"> + <img [src]="backgroundBox1Path" alt="background" /> + <img [src]="backgroundBox2Path" alt="background" /> + <img [src]="backgroundBox3Path" alt="background" /> + </div> + <div class="content"> + <div class="text-marquee"> + <div> + <h1 class="home-heading">Discover Alzheimer's Disease Genes</h1> + </div> + <p class="description mb-lg"> + Agora hosts high-dimensional human transcriptomic, proteomic, and metabolomic evidence for + whether or not genes are associated with Alzheimer’s disease (AD). Agora also contains a + list of over 900 nascent AD drug targets that were nominated by researchers from the + National Institute on Aging's + <a class="link" href="https://www.nia.nih.gov/research/amp-ad" target="_blank">AMP-AD</a> + consortium and <a class="link" href="https://treatad.org/" target="_blank">TREAT-AD</a> + centers, as well as by other AD research teams. + <a + class="link" + href="https://help.adknowledgeportal.org/apd/Agora-Resources.2646671361.html" + target="_blank" + > + Learn more + </a> + </p> + </div> + <div class="card-container"> + <button routerLink="/genes/comparison" class="card-link"> + <div class="card"> + <div> + <h2>Gene Comparison</h2> + <p> + Compare differential RNA and protein expression results for 20k+ human genes in AD. + Build custom result sets by sorting, filtering, and searching for genes of interest. + </p> + </div> + <div class="icon-container"> + <img [src]="geneComparisonIconPath" alt="gene icon" /> + <img [src]="arrowPath" alt="arrow" /> + </div> + </div> + </button> + <div class="card"> + <div> + <h2>Gene Search</h2> + <p> + Search for a gene by name or Ensembl gene ID to view related experimental evidence, + find detailed information about nominations, and explore its association with AD. + </p> + </div> + <!-- <gene-search [location]="'home'"></gene-search> --> + </div> + <button routerLink="/genes/nominated-targets" class="card-link"> + <div class="card"> + <div> + <h2>Nominated Targets</h2> + <p> + Browse the list of over 900 genes that research teams have nominated as potential + new therapeutic targets for AD treatment or prevention. + </p> + </div> + <div class="icon-container"> + <img [src]="nominatedTargetsIconPath" alt="target icon" /> + <img [src]="arrowPath" alt="arrow" /> + </div> + </div> + </button> + </div> + </div> + </div> +</div> diff --git a/libs/agora/home/src/lib/home.component.scss b/libs/agora/home/src/lib/home.component.scss new file mode 100644 index 0000000000..c32d29765e --- /dev/null +++ b/libs/agora/home/src/lib/home.component.scss @@ -0,0 +1,174 @@ +@import 'libs/agora/styles/src/lib/variables'; +@import 'libs/agora/styles/src/lib/mixins'; + +.section { + display: flex; + flex-direction: column; + gap: 40px; + position: relative; + color: var(--color-primary); + max-width: 90vw; + margin: 0 auto; + padding: var(--spacing-md) 0; + + @media (min-width: 750px) { + max-width: 80vw; + } + + @media (min-width: 990px) { + background-color: none; + } + + @include respond-to('ex-large') { + padding: var(--spacing-xl) 100px; + } +} + +.content { + max-width: 1350px; + margin: 0 auto; +} + +.text-marquee { + display: flex; + flex-direction: column; + gap: 40px; + padding: var(--spacing-md); +} + +.description { + width: 70%; + font-size: var(--font-size-xl); + line-height: 2rem; + + @media (min-width: 990px) { + width: 100%; + } + + a { + white-space: nowrap; + } + + p { + flex: 1; + text-align: center; + } +} + +.home-heading { + color: var(--color-primary); + font-size: 60px; + line-height: 68px; + font-weight: bold; + margin: 0; +} + +.home-search { + width: 100%; + max-width: 960px; + margin-left: auto; + margin-right: auto; +} + +.card-container { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: var(--spacing-lg); + + @media (min-width: 990px) { + flex-wrap: nowrap; + } + + > div, + > button { + width: 100%; + + @media (min-width: 990px) { + width: 33%; + } + } +} + +.card-link { + border: none; + margin: 0; + padding: 0; + overflow: visible; + outline: none; + background: transparent; + color: inherit; + font: inherit; + line-height: normal; + appearance: none; + text-align: unset; + cursor: pointer; + + .card { + height: 100%; + } +} + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + background-color: white; + box-sizing: border-box; + border-radius: 20px; + border: 1px solid var(--color-border); + padding: var(--spacing-lg); + flex-shrink: 0; + + h2 { + font-weight: bold; + font-size: var(--font-size-xxl); + } + + p { + font-size: var(--font-size-xl); + line-height: var(--line-height-xxl); + } + + .icon-container { + display: flex; + justify-content: space-between; + align-items: flex-end; + } +} + +.background { + position: fixed; + z-index: -1; + top: 0; + left: 0; + width: 100%; + height: 100%; + + img { + position: absolute; + width: 30vh; + + &:first-child { + position: absolute; + bottom: 12vh; + left: -5vh; + transform: rotate(260deg); + } + + &:nth-child(2) { + position: absolute; + bottom: 60vh; + right: -10vh; + transform: rotate(30deg); + } + + &:last-child { + position: absolute; + width: 45vh; + bottom: 0; + right: -18vh; + transform: rotate(125deg); + } + } +} diff --git a/libs/agora/home/src/lib/home.component.spec.ts b/libs/agora/home/src/lib/home.component.spec.ts new file mode 100644 index 0000000000..535d03b53c --- /dev/null +++ b/libs/agora/home/src/lib/home.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { HomeComponent } from './home.component'; +import { provideHttpClient } from '@angular/common/http'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture<HomeComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [], + providers: [provideHttpClient()], + }).compileComponents(); + + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/libs/agora/home/src/lib/home.component.ts b/libs/agora/home/src/lib/home.component.ts new file mode 100644 index 0000000000..0bd4a59f12 --- /dev/null +++ b/libs/agora/home/src/lib/home.component.ts @@ -0,0 +1,43 @@ +import { CommonModule } from '@angular/common'; +import { Component } from '@angular/core'; +import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; + +@Component({ + selector: 'agora-home', + standalone: true, + imports: [CommonModule], + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'], +}) +export class HomeComponent { + backgroundBox1Path!: SafeUrl; + backgroundBox2Path!: SafeUrl; + backgroundBox3Path!: SafeUrl; + + geneComparisonIconPath!: SafeUrl; + nominatedTargetsIconPath!: SafeUrl; + arrowPath!: SafeUrl; + + constructor(private sanitizer: DomSanitizer) { + this.loadBackgroundImages(); + this.loadIcons(); + } + + loadBackgroundImages() { + this.backgroundBox1Path = this.sanitize('/agora-assets/images/background1.svg'); + this.backgroundBox2Path = this.sanitize('/agora-assets/images/background2.svg'); + this.backgroundBox3Path = this.sanitize('/agora-assets/images/background3.svg'); + } + + loadIcons() { + this.geneComparisonIconPath = this.sanitize('/agora-assets/images/gene-comparison-icon.svg'); + this.nominatedTargetsIconPath = this.sanitize( + '/agora-assets/images/nominated-targets-icon.svg', + ); + this.arrowPath = this.sanitize('/agora-assets/images/card-arrow.svg'); + } + + sanitize(path: string) { + return this.sanitizer.bypassSecurityTrustUrl(path); + } +} diff --git a/libs/agora/home/src/lib/home.routes.ts b/libs/agora/home/src/lib/home.routes.ts new file mode 100644 index 0000000000..ee27d4f3ab --- /dev/null +++ b/libs/agora/home/src/lib/home.routes.ts @@ -0,0 +1,4 @@ +import { Routes } from '@angular/router'; +import { HomeComponent } from './home.component'; + +export const routes: Routes = [{ path: '', component: HomeComponent }]; diff --git a/libs/agora/home/src/test-setup.ts b/libs/agora/home/src/test-setup.ts new file mode 100644 index 0000000000..1100b3e8a6 --- /dev/null +++ b/libs/agora/home/src/test-setup.ts @@ -0,0 +1 @@ +import 'jest-preset-angular/setup-jest'; diff --git a/libs/agora/home/tsconfig.json b/libs/agora/home/tsconfig.json new file mode 100644 index 0000000000..f2860a9cd7 --- /dev/null +++ b/libs/agora/home/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "target": "es2020", + "esModuleInterop": true + }, + "angularCompilerOptions": { + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/libs/agora/home/tsconfig.lib.json b/libs/agora/home/tsconfig.lib.json new file mode 100644 index 0000000000..b228a1a081 --- /dev/null +++ b/libs/agora/home/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] +} diff --git a/libs/agora/home/tsconfig.spec.json b/libs/agora/home/tsconfig.spec.json new file mode 100644 index 0000000000..317e26be1d --- /dev/null +++ b/libs/agora/home/tsconfig.spec.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "target": "es2016", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts", "jest.config.ts"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 299b525047..aebe758e87 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -20,6 +20,7 @@ "@sagebionetworks/agora/about": ["libs/agora/about/src/index.ts"], "@sagebionetworks/agora/api-client-angular": ["libs/agora/api-client-angular/src/index.ts"], "@sagebionetworks/agora/config": ["libs/agora/config/src/index.ts"], + "@sagebionetworks/agora/home": ["libs/agora/home/src/index.ts"], "@sagebionetworks/agora/models": ["libs/agora/models/index.ts"], "@sagebionetworks/agora/news": ["libs/agora/news/src/index.ts"], "@sagebionetworks/agora/not-found": ["libs/agora/not-found/src/index.ts"],