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&#39;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"],