Skip to content

Commit 0c178a5

Browse files
committed
enabling profile search
1 parent 5d15a79 commit 0c178a5

File tree

11 files changed

+120
-153
lines changed

11 files changed

+120
-153
lines changed

src/app/browser/browser.module.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {SearchService} from '../shared/search/service/search.service';
1111
import { AnnotationService } from './services/annotation/annotation.service';
1212
import {TermService} from './services/term/term.service';
1313
import {GeneService} from './services/gene/gene.service';
14-
import {DiseaseService} from './services/disease/disease.service';
1514
import {OntologyService} from './services/ontology/ontology.service';
1615
// Components
1716
import {TermComponent} from './pages/term/term.component';
@@ -33,7 +32,7 @@ import {ProfileSearchComponent} from './pages/profile-search/profile-search.comp
3332
GlobalMaterialModules,
3433
ExtrasModule
3534
],
36-
providers: [SearchService, TermService, GeneService, DiseaseService, DialogService,
35+
providers: [SearchService, TermService, GeneService, DialogService,
3736
OntologyService, AnnotationService],
3837
declarations: [TermComponent, DiseaseComponent,
3938
GeneComponent,

src/app/browser/pages/disease/disease.component.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import {ActivatedRoute, Router} from '@angular/router';
33
import {MatTableDataSource} from '@angular/material/table';
44
import {MatSort} from '@angular/material/sort';
55
import {MatPaginator} from '@angular/material/paginator';
6-
import { Disease, Gene, SimpleTerm, Term, TermCategory } from '../../models/models';
6+
import { Disease, SimpleTerm, Term, TermCategory } from '../../models/models';
77
import { AnnotationService } from '../../services/annotation/annotation.service';
8-
import {DiseaseService} from '../../services/disease/disease.service';
98
import {DialogService} from '../../../shared/dialog-excel-download/dialog.service';
109

1110
@Component({
@@ -28,7 +27,7 @@ export class DiseaseComponent {
2827

2928
@ViewChild('genePaginator', {static: true}) genePaginator: MatPaginator;
3029

31-
constructor(private route: ActivatedRoute, private diseaseService: DiseaseService,
30+
constructor(private route: ActivatedRoute,
3231
public dialogService: DialogService, public annotationService: AnnotationService,
3332
private router: Router) {
3433
this.route.params.subscribe((params) => {

src/app/browser/pages/profile-search/profile-search.component.html

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="news container">
1+
<div class="container profile-container">
22
<h1 class="center">Profile Search</h1>
33
<h4 class="center">This tool will find diseases that share your profile of phenotypes. Similarly, there is a
44
<a href="https://monarchinitiative.org/analyze/phenotypes" target="_blank">tool</a> that
@@ -59,29 +59,41 @@ <h3>Your Phenotype Profile</h3>
5959
{{term.id}} - {{term.name}}
6060
</mat-chip>
6161
</mat-chip-list>
62-
<mat-table class="intersecting-table mat-elevation-z6" [dataSource]="associationData"
63-
matSort matSortActive="created" matSortDisableClear matSortDirection="desc">
64-
<!-- Number Column -->
65-
<ng-container matColumnDef="diseaseId">
66-
<mat-header-cell *matHeaderCellDef>Disease Identifier</mat-header-cell>
67-
<mat-cell *matCellDef="let row">
68-
<a routerLink="/browse/disease/{{row.diseaseId}}">{{row.diseaseId}}</a>
69-
</mat-cell>
70-
</ng-container>
71-
<!-- Created Column -->
72-
<ng-container matColumnDef="diseaseName">
73-
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>
74-
Disease Name
75-
</mat-header-cell>
76-
<mat-cell *matCellDef="let row">{{row.diseaseName}}</mat-cell>
77-
</ng-container>
62+
<div class="tab-output-container mat-elevation-z6">
63+
<div class="filter-container">
64+
<div class="filter-header">
65+
<mat-form-field>
66+
<input id="termFilterInput" matInput (keyup)="applyTermFilter($event.target.value)"
67+
placeholder="Filter">
68+
</mat-form-field>
69+
</div>
70+
</div>
71+
<mat-table class="intersecting-table" [dataSource]="dataSource"
72+
matSort matSortActive="created" matSortDisableClear matSortDirection="desc">
73+
<!-- Number Column -->
74+
<ng-container matColumnDef="diseaseId">
75+
<mat-header-cell *matHeaderCellDef>Disease Identifier</mat-header-cell>
76+
<mat-cell *matCellDef="let row">
77+
<a routerLink="/browse/disease/{{row.id}}">{{row.id}}</a>
78+
</mat-cell>
79+
</ng-container>
80+
<!-- Created Column -->
81+
<ng-container matColumnDef="diseaseName">
82+
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>
83+
Disease Name
84+
</mat-header-cell>
85+
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
86+
</ng-container>
7887

79-
<mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
80-
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
81-
<mat-paginator [length]="resultsLength" [pageSize]="30"></mat-paginator>
82-
</mat-table>
83-
<p class="not-found" *ngIf="resultsLength === 0"><strong>No intersecting diseases for found your
84-
phenotypes.</strong></p>
88+
<mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
89+
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
90+
</mat-table>
91+
<div class="associationsPaging">
92+
<p>{{resultsLength}} diseases found.</p>
93+
</div>
94+
<p class="not-found" *ngIf="resultsLength === 0"><strong>No intersecting diseases for found your
95+
phenotypes.</strong></p>
96+
</div>
8597
<button class="back-btn" mat-raised-button (click)="resetStepper()">Reset</button>
8698
</div>
8799
</div>

src/app/browser/pages/profile-search/profile-search.component.scss

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@
4545
margin-top: 1rem;
4646
}
4747

48-
.intersecting-table {
49-
margin-top: 0.5rem;
50-
}
51-
52-
5348
.query-chip {
5449
color: white;
5550
font-size: 12px;
@@ -60,3 +55,34 @@
6055
.not-found {
6156
text-align: center;
6257
}
58+
59+
.tab-output-container {
60+
display: flex;
61+
flex-direction: column;
62+
min-width: 300px;
63+
}
64+
65+
.filter-container {
66+
display: flex;
67+
flex-direction: column;
68+
min-width: 300px;
69+
}
70+
71+
.filter-header {
72+
min-height: 64px;
73+
padding: 8px 24px 0;
74+
}
75+
76+
.mat-form-field {
77+
font-size: 14px;
78+
width: 100%;
79+
}
80+
81+
.profile-container {
82+
margin: 0 10%;
83+
}
84+
85+
.tab-output-container {
86+
margin: 1rem 0 0 0;
87+
background-color: white;
88+
}

src/app/browser/pages/profile-search/profile-search.component.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import {Component, OnInit, ViewChild} from '@angular/core';
2-
import {Observable} from "rxjs";
2+
import { MatTableDataSource } from '@angular/material/table';
3+
import { Observable, of } from 'rxjs';
34
import {UntypedFormControl} from "@angular/forms";
4-
import {filter, map, switchMap} from "rxjs/operators";
5-
import {TermService} from "../../services/term/term.service";
6-
import {SearchService} from "../../../shared/search/service/search.service";
5+
import { catchError, debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
6+
import { AnnotationService } from '../../services/annotation/annotation.service';
7+
import { OntologyService } from '../../services/ontology/ontology.service';
78
import {MatStepper} from "@angular/material/stepper";
89
import {MatSort} from "@angular/material/sort";
910
import {MatPaginator} from "@angular/material/paginator";
10-
import {Term} from "../../models/models";
11+
import { SimpleTerm, Term } from '../../models/models';
1112

1213
@Component({
1314
selector: 'app-custom',
@@ -17,28 +18,28 @@ import {Term} from "../../models/models";
1718
export class ProfileSearchComponent implements OnInit {
1819

1920
@ViewChild('stepper') stepper: MatStepper;
20-
@ViewChild(MatPaginator) paginator: MatPaginator;
2121
@ViewChild(MatSort) sort: MatSort;
2222

2323
myControl = new UntypedFormControl();
24-
filteredOptions: Observable<[]>;
25-
selectedTerms: Term[] = [];
24+
filteredOptions: Observable<SimpleTerm[]>;
25+
selectedTerms: SimpleTerm[] = [];
2626
submittedTerms = false;
27+
dataSource: MatTableDataSource<SimpleTerm>;
2728
associationData;
2829
loadingIntersectingAssociations = true;
2930
intersectingAssocationError = false;
3031
displayedColumns: string[] = ['diseaseId', 'diseaseName'];
3132
resultsLength = 0;
3233

33-
constructor(private searchService: SearchService, private termService: TermService) {
34+
constructor(private ontologyService: OntologyService, private annotationService: AnnotationService) {
3435
}
3536

3637
ngOnInit(): void {
3738
this.filteredOptions = this.myControl.valueChanges
3839
.pipe(
39-
filter(x => x != null && x != ''),
40+
filter(x => x != null && x != '' && x.length >= 3),
4041
switchMap(val =>
41-
this.searchService.searchAll(val)
42+
this.ontologyService.search(val, 10)
4243
),
4344
map(response => response.terms)
4445
);
@@ -59,19 +60,28 @@ export class ProfileSearchComponent implements OnInit {
5960
this.submittedTerms = true;
6061
this.loadingIntersectingAssociations = true;
6162
let termIds = this.selectedTerms.map(term => term.id);
62-
// this.termService.searchIntersectingAnnotations(termIds).pipe(
63-
// map(data => {
64-
// // Flip flag to show that loading has finished.
65-
// this.loadingIntersectingAssociations = false;
66-
// this.resultsLength = data.associations.length;
67-
// return data.associations;
68-
// }),
69-
// catchError(() => {
70-
// this.intersectingAssocationError = true;
71-
// this.loadingIntersectingAssociations = false;
72-
// return of([]);
73-
// })
74-
// ).subscribe(data => this.associationData = data);
63+
this.annotationService.searchProfile(termIds.join(",")).pipe(
64+
debounceTime(1000),
65+
distinctUntilChanged(),
66+
map(data => {
67+
this.loadingIntersectingAssociations = false;
68+
this.resultsLength = data.length;
69+
return data;
70+
}),
71+
catchError(() => {
72+
this.intersectingAssocationError = true;
73+
this.loadingIntersectingAssociations = false;
74+
return of([]);
75+
})
76+
).subscribe(data =>
77+
this.dataSource = new MatTableDataSource(data)
78+
);
79+
}
80+
81+
applyTermFilter(filterValue: string) {
82+
filterValue = filterValue.trim(); // Remove whitespace
83+
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
84+
this.dataSource.filter = filterValue;
7585
}
7686

7787
resetStepper() {

src/app/browser/pages/term/term.component.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ <h3 class="card-title">Hierarchy</h3>
1818
<span class="tree-counts" [ngStyle]="{'margin-left': '-100px', 'margin-right': '5px'}"
1919
matTooltip="{{parent.descendantCount}}" *ngIf="parent.descendantCount !== 0"
2020
matTooltipPosition="above"> </span>
21-
<a class="link" routerLink="../{{parent.id}}">{{parent.name | translate: parent.translations: selectedLanguage.language}}</a>
21+
<a class="link" routerLink="../{{parent.id}}">{{parent.name | translate: parent.translations: selectedLanguage.language: "name"}}</a>
2222
</li>
2323
<li>
2424
<div class="term">
2525
<span class="tree-counts" [ngStyle]="{'margin-left': '-115px'}"
2626
*ngIf="treeData.descendantCount !== 0" matTooltip="{{treeData.descendantCount}}"
2727
matTooltipPosition="above"> </span>
28-
<strong>{{term.name | translate: term.translations: selectedLanguage.language}}</strong>
28+
<strong>{{term.name | translate: term.translations: selectedLanguage.language: "name"}}</strong>
2929
</div>
3030
<ul>
3131
<li *ngFor="let child of treeData.children" class="children">
3232
<span class="tree-counts" [ngStyle]="setTreeStyles(child)" *ngIf="child.descendantCount !== 0"
3333
matTooltip="{{child.descendantCount}}" matTooltipPosition="above"> </span>
34-
<a class="link" routerLink="../{{child.id}}">{{child.name | translate: child.translations: selectedLanguage.language}}</a>
34+
<a class="link" routerLink="../{{child.id}}">{{child.name | translate: child.translations: selectedLanguage.language: "name"}}</a>
3535
</li>
3636
</ul>
3737
</li>
@@ -51,7 +51,7 @@ <h3 class="card-title">Hierarchy</h3>
5151
</div>
5252
<div *ngIf="treeData && term">
5353
<div>
54-
<span class="item-title">{{termTitle | translate: term.translations: selectedLanguage.language}}&nbsp;</span>
54+
<span class="item-title">{{termTitle | translate: term.translations: selectedLanguage.language: "name"}}&nbsp;</span>
5555
<span class="item-id" *ngIf="paramId !== term.id">
5656
<span class="crossout">{{paramId}}</span>
5757
<i class="material-icons obsolete-arrow">arrow_right_alt</i></span>
@@ -70,7 +70,7 @@ <h3 class="card-title">Hierarchy</h3>
7070
<hr class="underline-hr">
7171
<div>
7272
<p>
73-
{{term.definition !== "" ? term.definition : "No definition found."}}
73+
{{term.definition !== "" ? (term.definition | translate: term.translations: selectedLanguage.language: "definition") : "No definition found."}}
7474
</p>
7575
</div>
7676
<mat-list>

src/app/browser/services/annotation/annotation.service.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ export class AnnotationService {
2121
return this.httpClient.get<GeneAssociation>(environment.ONTOLOGY_NETWORK_ANNOTATION_API + id);
2222
}
2323

24-
searchGene(query: string, limit: number): Observable<SimpleTerm> {
25-
return this.httpClient.get<SimpleTerm>(`${environment.ONTOLOGY_NETWORK_SEARCH_API}gene?q=${query}&limit=${limit}`);
24+
searchGene(query: string, limit: number): Observable<SimpleTerm[]> {
25+
return this.httpClient.get<SimpleTerm[]>(`${environment.ONTOLOGY_NETWORK_SEARCH_API}gene?q=${query}&limit=${limit}`);
2626
}
2727

28-
searchDisease(query: string, limit: number): Observable<SimpleTerm> {
29-
return this.httpClient.get<SimpleTerm>(`${environment.ONTOLOGY_NETWORK_SEARCH_API}disease?q=${query}&limit=${limit}`);
28+
searchDisease(query: string, limit: number): Observable<SimpleTerm[]> {
29+
return this.httpClient.get<SimpleTerm[]>(`${environment.ONTOLOGY_NETWORK_SEARCH_API}disease?q=${query}&limit=${limit}`);
30+
}
31+
32+
searchProfile(query: string): Observable<SimpleTerm[]> {
33+
return this.httpClient.get<SimpleTerm[]>(`${environment.ONTOLOGY_NETWORK_SEARCH_API}disease/intersect?p=${query}`);
3034
}
3135
}

src/app/browser/services/disease/disease.service.spec.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/app/browser/services/disease/disease.service.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)