Skip to content
Commits on Source (12)
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
......@@ -36,7 +36,8 @@
],
"scripts": [],
"allowedCommonJsDependencies": [
"@phylocanvas/phylocanvas.gl"
"@phylocanvas/phylocanvas.gl",
"earcut"
]
},
"configurations": {
......@@ -136,5 +137,7 @@
}
}
},
"defaultProject": "s-locus-finder-reporter-frontend"
"cli": {
"analytics": false
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "@sing-group/s-locus-finder-reporter-frontend",
"version": "1.0.0-alpha.23",
"version": "1.0.0-alpha.34",
"description": "A frontend application for S-Locus Finder reports.",
"author": {
"name": "Alex Gómez González",
......@@ -22,30 +22,34 @@
"test": "npx ng test"
},
"private": true,
"engines": {
"npm" : ">=8.19.0 <10.0.0",
"node" : "^16.14.0 || ^18.10.0"
},
"dependencies": {
"@angular/animations": "~13.1.0",
"@angular/cdk": "^13.1.3",
"@angular/common": "~13.1.0",
"@angular/compiler": "~13.1.0",
"@angular/core": "~13.1.0",
"@angular/forms": "~13.1.0",
"@angular/material": "^13.1.3",
"@angular/platform-browser": "~13.1.0",
"@angular/platform-browser-dynamic": "~13.1.0",
"@angular/router": "~13.1.0",
"@deck.gl/core": "^8.7.0",
"@deck.gl/layers": "^8.7.0",
"@luma.gl/constants": "^8.5.10",
"@luma.gl/core": "^8.5.10",
"@phylocanvas/phylocanvas.gl": "^1.39.0",
"@angular/animations": "^16.2.7",
"@angular/cdk": "^16.2.6",
"@angular/common": "^16.2.7",
"@angular/compiler": "^16.2.7",
"@angular/core": "^16.2.7",
"@angular/forms": "^16.2.7",
"@angular/material": "^16.2.6",
"@angular/platform-browser": "^16.2.7",
"@angular/platform-browser-dynamic": "^16.2.7",
"@angular/router": "^16.2.7",
"@deck.gl/core": "8.7.0",
"@deck.gl/layers": "8.7.0",
"@luma.gl/constants": "8.5.10",
"@luma.gl/core": "8.5.10",
"@phylocanvas/phylocanvas.gl": "1.50.0",
"rxjs": "~7.4.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
"zone.js": "~0.13.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^13.2.5",
"@angular/cli": "~13.1.4",
"@angular/compiler-cli": "~13.1.0",
"@angular-devkit/build-angular": "^16.2.4",
"@angular/cli": "^16.2.4",
"@angular/compiler-cli": "^16.2.7",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~3.10.0",
......@@ -54,6 +58,6 @@
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.5.2"
"typescript": "~5.1.6"
}
}
......@@ -4,9 +4,9 @@
</span>
<span class="example-spacer"></span>
<div class="collapse navbar-collapse">
<input #toSearch id="search" (keyup.enter)="this.onFamilySearch(toSearch.value)" type="text" placeholder="Search"
<input #toSearch id="search" type="text" placeholder="Search"
class="search" [matAutocomplete]="auto" [formControl]="control">
<mat-autocomplete #auto="matAutocomplete">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="this.onFamilySearch(toSearch.value)">
<mat-option *ngFor="let family of filteredFamilies | async" [value]="family">
{{family}}
</mat-option>
......
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {DataService} from './services/data.service';
import {Router} from '@angular/router';
import {MatSnackBar} from '@angular/material/snack-bar';
import {Observable} from "rxjs";
import {FormControl} from "@angular/forms";
import {UntypedFormControl} from "@angular/forms";
import {map, startWith} from 'rxjs/operators';
import {MatSnackBar} from "@angular/material/snack-bar";
@Component({
......@@ -15,7 +15,7 @@ import {map, startWith} from 'rxjs/operators';
export class AppComponent implements OnInit {
@ViewChild('toSearch') searchInput!: ElementRef<HTMLInputElement>;
public databaseName?: string;
public control = new FormControl();
public control = new UntypedFormControl();
public filteredFamilies: Observable<string[]> | undefined;
private families: string[] = []
......@@ -49,6 +49,7 @@ export class AppComponent implements OnInit {
}
public onFamilySearch(toSearch: string): void {
console.log(toSearch);
this.dataService.findFamilyName(toSearch)
.subscribe(familyNames => {
if (familyNames.length === 0) {
......
......@@ -6,22 +6,25 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {HttpClientModule} from '@angular/common/http';
import {FamilyComponent} from './components/family/family.component';
import {ResultComponent} from './components/result/result.component';
import {MatDialogModule} from '@angular/material/dialog';
import {DataService} from './services/data.service';
import {MatCardModule} from '@angular/material/card';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatSnackBarModule} from '@angular/material/snack-bar';
import {MatTableModule} from '@angular/material/table';
import {MatButtonModule} from '@angular/material/button';
import {MatIconModule} from '@angular/material/icon';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatFormFieldModule} from '@angular/material/form-field';
import {DialogComponent} from './components/dialog/dialog.component';
import {MatPaginatorModule} from '@angular/material/paginator';
import {MatSortModule} from '@angular/material/sort';
import {FamiliesTreeComponent} from './components/families-tree/families-tree.component';
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {ReactiveFormsModule} from "@angular/forms";
import {MatDialogModule} from "@angular/material/dialog";
import {MatCardModule} from "@angular/material/card";
import {MatSnackBarModule} from "@angular/material/snack-bar";
import {MatTableModule} from "@angular/material/table";
import {MatButtonModule} from "@angular/material/button";
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatPaginatorModule} from "@angular/material/paginator";
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {MatInputModule} from "@angular/material/input";
import {MatSelectModule} from "@angular/material/select";
import {MatListModule} from "@angular/material/list";
@NgModule({
......@@ -49,7 +52,10 @@ import {ReactiveFormsModule} from "@angular/forms";
MatPaginatorModule,
MatSortModule,
MatAutocompleteModule,
ReactiveFormsModule
ReactiveFormsModule,
MatInputModule,
MatSelectModule,
MatListModule
],
providers: [{
provide: APP_INITIALIZER,
......
import {Component, Inject, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {MatSnackBar} from '@angular/material/snack-bar';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
@Component({
selector: 'slf-dialog',
......@@ -11,17 +11,22 @@ import {MatSnackBar} from '@angular/material/snack-bar';
export class DialogComponent implements OnInit {
private readonly existFirstValue: boolean;
private readonly existSecondValue: boolean;
public readonly firstValue:string;
public readonly secondValue:string;
public readonly firstValue: string;
public readonly secondValue: string;
constructor(public dialogRef: MatDialogRef<DialogComponent>,
private router: Router,
@Inject(MAT_DIALOG_DATA) public data: { firstValue:string,existFirstValue: boolean, secondValue:string,existSecondValue: boolean },
@Inject(MAT_DIALOG_DATA) public data: {
firstValue: string,
existFirstValue: boolean,
secondValue: string,
existSecondValue: boolean
},
private readonly snackBar: MatSnackBar) {
this.existFirstValue = data.existFirstValue;
this.existSecondValue = data.existSecondValue;
this.firstValue=data.firstValue
this.secondValue=data.secondValue
this.firstValue = data.firstValue
this.secondValue = data.secondValue
}
......@@ -49,7 +54,6 @@ export class DialogComponent implements OnInit {
verticalPosition: 'bottom',
duration: 4000
});
}
}
}
......
<h2>Description</h2>
<h4>{{databaseDescription}}</h4>
<!--<mat-card style="background: #3f51b5">
<mat-card-title style="color: white">Description</mat-card-title>
<mat-card-content> {{databaseDescription}}</mat-card-content>
<mat-card *ngIf="databaseDescription">
<mat-card-header>
<mat-card-title>Description</mat-card-title>
</mat-card-header>
<mat-card-content>{{databaseDescription}}</mat-card-content>
</mat-card>
--->
<div #demo id="demo" (click)="onGoToFamily()"></div>
<mat-card>
<mat-card-header>
<mat-card-title>Families tree</mat-card-title>
</mat-card-header>
<mat-card-content>
<div #tree id="tree" (click)="onGoToFamily()"></div>
</mat-card-content>
</mat-card>
......@@ -2,10 +2,10 @@ import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core';
import PhylocanvasGL, {TreeTypes} from '@phylocanvas/phylocanvas.gl';
import {Router} from '@angular/router';
import {DataService} from 'src/app/services/data.service';
import {MatDialog} from '@angular/material/dialog';
import {DialogComponent} from '../dialog/dialog.component';
import {MatSnackBar} from '@angular/material/snack-bar';
import {forkJoin, map, take} from 'rxjs';
import {MatDialog} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
@Component({
selector: 'slf-families-tree',
......@@ -13,7 +13,7 @@ import {forkJoin, map, take} from 'rxjs';
styleUrls: ['./families-tree.component.scss']
})
export class FamiliesTreeComponent implements AfterViewInit {
@ViewChild('demo') demoDiv!: ElementRef<HTMLDivElement>;
@ViewChild('tree') treeDiv!: ElementRef<HTMLDivElement>;
private tree: PhylocanvasGL;
public databaseDescription?: string;
......@@ -44,25 +44,48 @@ export class FamiliesTreeComponent implements AfterViewInit {
this.dataService.getDatabaseInfo()
.subscribe(info => {
this.databaseDescription=info.description
this.databaseDescription = info.description
});
}
private count_nodes(newickTree: string): number {
const regex: RegExp = /[^:;,()\s]*(?:\s*:\s*[\d.]+\s*)?([,);])|(\S)/g;
newickTree += ";";
return (function recurse(): [string, number] {
let all: string, delim: string, ch: string;
// @ts-ignore
[all, delim, ch] = regex.exec(newickTree);
let count: number = 1; // Current node
if (ch == "(") {
let child_count: number;
while ("(,".includes(ch)) {
[ch, child_count] = recurse();
count += child_count;
}
[all, delim, ch] = regex.exec(newickTree);
}
return [delim, count];
})()[1];
}
private renderizeTree(newickTree: string, styles: { [key: string]: { fillColour: string } }): void {
const screenSize = this.demoDiv.nativeElement.getBoundingClientRect();
const screenSize: DOMRect = this.treeDiv.nativeElement.getBoundingClientRect();
const nodeSize: number = 16;
screenSize.width = screenSize.width * 0.95;
screenSize.height = screenSize.height * 3;
screenSize.height = 100 + this.count_nodes(newickTree) * nodeSize;
this.tree = new PhylocanvasGL(
this.demoDiv.nativeElement,
this.treeDiv.nativeElement,
{
interactive: false,
showLabels: true,
showLeafLabels: true,
size: screenSize,
alignLabels: true,
nodeSize: 16,
nodeSize: nodeSize,
fillColour: '#3f51b5',
source: newickTree,
type: TreeTypes.Rectangular,
......@@ -80,7 +103,7 @@ export class FamiliesTreeComponent implements AfterViewInit {
const param = this.tree['props']['selectedIds'];
if (param !== undefined) {
const familyId = param[0];
let idMultipleValues=familyId.split(/(?=[A-Z])/);
let idMultipleValues = familyId.split(/(?=[A-Z])/);
if (idMultipleValues.length > 1) {
forkJoin(
{
......@@ -89,7 +112,7 @@ export class FamiliesTreeComponent implements AfterViewInit {
secondValue: this.dataService.hasFamily(idMultipleValues[1]).pipe(take(1))
}
).subscribe(familiesPresence => {
this.onOpenDialog(idMultipleValues[0],familiesPresence['firstValue'],idMultipleValues[1],familiesPresence['secondValue']);
this.onOpenDialog(idMultipleValues[0], familiesPresence['firstValue'], idMultipleValues[1], familiesPresence['secondValue']);
});
} else {
this.dataService.hasFamily(familyId)
......@@ -108,10 +131,15 @@ export class FamiliesTreeComponent implements AfterViewInit {
}
}
private onOpenDialog(firstValue:string,existFirstValue: boolean,secondValue:string, existSecondValue: boolean): void {
private onOpenDialog(firstValue: string, existFirstValue: boolean, secondValue: string, existSecondValue: boolean): void {
const dialogRef = this.dialog.open(DialogComponent, {
width: '450px',
data: {'firstValue':firstValue,'existFirstValue':existFirstValue,'secondValue':secondValue, 'existSecondValue': existSecondValue}
data: {
'firstValue': firstValue,
'existFirstValue': existFirstValue,
'secondValue': secondValue,
'existSecondValue': existSecondValue
}
});
}
}
<mat-card>
<mat-card-title>{{id}}</mat-card-title>
<mat-card-header>
<mat-card-title>{{id}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<span>Species:</span>
<select class="form-select" id="results" #species
(change)="onChangeSpecies(species.value)">
<ng-container *ngFor="let speciesName of speciesNames">
<option>{{speciesName}}</option>
</ng-container>
</select>
<mat-form-field>
<mat-label>Species</mat-label>
<mat-select id="results" [(value)]="speciesName">
<mat-option *ngFor="let name of speciesNames" [value]="name">{{name}}</mat-option>
</mat-select>
</mat-form-field>
<mat-divider></mat-divider>
<div>
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="species">
......@@ -21,7 +24,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let result">
<button [routerLink]="['/species', id, extractResultId(result)]" mat-raised-button color="primary"
<button [routerLink]="['/species', id, extractResultId(result)]" mat-icon-button color="primary"
aria-label="View analysis">
<mat-icon>visibility</mat-icon>
</button>
......
table {
width: 100%;
}
.form-select {
display: block;
width: 50%;
padding: .375rem 2.25rem .375rem .75rem;
-moz-padding-start: calc(0.75rem - 3px);
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right .75rem center;
background-size: 16px 12px;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.navigable-link {
cursor: pointer;
}
......@@ -3,13 +3,13 @@ import {ActivatedRoute, Router} from '@angular/router';
import {SpeciesAnalysis} from 'src/app/models/SpeciesAnalysis';
import {DataService} from 'src/app/services/data.service';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import {MatPaginatedDataSource} from '../../models/pagination/mat-paginated-data-source';
import {PaginatedDataProvider} from '../../models/pagination/paginated-data-provider';
import {ListingOptions} from '../../models/pagination/listing-options';
import {Observable, of} from 'rxjs';
import {PageData} from '../../models/pagination/page-data';
import {MatPaginator} from "@angular/material/paginator";
class FamilyPaginatedProvider implements PaginatedDataProvider<SpeciesAnalysis> {
private species?: string;
......@@ -82,6 +82,14 @@ export class FamilyComponent implements OnInit, AfterViewInit {
this._dataSource?.setControls(this.paginator, this.sort);
}
public set speciesName(speciesName: string) {
this.changeSpecies(speciesName);
}
public get speciesName(): string | undefined {
return this.dataProvider?.getCurrentSpeciesName();
}
public get dataSource(): MatPaginatedDataSource<SpeciesAnalysis> {
if (this._dataSource === undefined) {
throw new Error('dataProvider is undefined');
......@@ -105,10 +113,6 @@ export class FamilyComponent implements OnInit, AfterViewInit {
return name.substring(name.lastIndexOf('/') + 1);
}
public onChangeSpecies(speciesName: string): void {
this.changeSpecies(speciesName);
}
private changeSpecies(speciesName: string): void {
this.dataProvider?.changeSpecies(speciesName);
this.paginator?.firstPage();
......
<mat-card>
<mat-card-title>
{{id}}
</mat-card-title>
<mat-card-subtitle>
<a id="family-link" routerLink="/family/{{familyName}}">{{familyName}}</a>
</mat-card-subtitle>
<mat-card-content>
<span>Results:</span>
<select class="form-select" id="results" #result
(change)="onChangeResults(result.value)">
<ng-container *ngFor="let analysisName of speciesAnalysisNames">
<div *ngIf="analysisName === id; then thenBlock; else elseBlock"></div>
<ng-template #thenBlock>
<option selected>{{analysisName}}</option>
</ng-template>
<ng-template #elseBlock>
<option>{{analysisName}}</option>
</ng-template>
</ng-container>
</select>
<div>
<div *ngIf="speciesAnalysis?.predictedSkp1===null && speciesAnalysis?.predictedSkp1===null; then thenBlockSKP1 else elseBlockSKP1"></div>
<mat-card-header>
<mat-card-title>
{{id}}
</mat-card-title>
<mat-card-subtitle>
<ng-container
*ngIf="speciesAnalysis?.predictedSkp1 === null && speciesAnalysis?.putativeSkp1 === null; then thenBlockSKP1 else elseBlockSKP1"></ng-container>
<ng-template #thenBlockSKP1>
<br>
<mat-card-subtitle>
No SKP1 model
<a routerLink="/family/{{familyName}}">{{familyName}}</a> - No SKP1 model
</mat-card-subtitle>
</ng-template>
<ng-template #elseBlockSKP1>
<br>
<mat-card-subtitle>
<div *ngIf="speciesAnalysis?.predictedSkp1TreePath===null; then thenBlockPredictedSKP1 else elseBlockPredictedSKP1"></div>
<a routerLink="/family/{{familyName}}">{{familyName}}</a> -
<ng-container
*ngIf="speciesAnalysis?.predictedSkp1TreePath === null; then thenBlockPredictedSKP1 else elseBlockPredictedSKP1"></ng-container>
<ng-template #thenBlockPredictedSKP1>
SKP1 region count: {{speciesAnalysis?.predictedSkp1}} predicted /
</ng-template>
<ng-template #elseBlockPredictedSKP1>
SKP1 region count:
<a [href]="buildFileUrl(speciesAnalysis?.predictedSkp1TreePath!)" target="_blank">
{{speciesAnalysis?.predictedSkp1}} predicted </a> /
</ng-template>
<div *ngIf="speciesAnalysis?.putativeSkp1TreePath===null; then thenBlockPutativeSKP1 else elseBlockPutativeSKP1"></div>
<ng-template #thenBlockPutativeSKP1>
{{speciesAnalysis?.putativeSkp1}} putative
</ng-template>
<ng-template #elseBlockPutativeSKP1>
<a [href]="buildFileUrl(speciesAnalysis?.putativeSkp1TreePath!)" target="_blank">
{{speciesAnalysis?.putativeSkp1}} putative</a>
</ng-template>
<ng-template #elseBlockPredictedSKP1>
SKP1 region count:
<a [href]="buildFileUrl(speciesAnalysis?.predictedSkp1TreePath!)" target="_blank">
{{speciesAnalysis?.predictedSkp1}} predicted </a> /
</ng-template>
<ng-container
*ngIf="speciesAnalysis?.putativeSkp1TreePath === null; then thenBlockPutativeSKP1 else elseBlockPutativeSKP1"></ng-container>
<ng-template #thenBlockPutativeSKP1>
{{speciesAnalysis?.putativeSkp1}} putative
</ng-template>
<ng-template #elseBlockPutativeSKP1>
<a [href]="buildFileUrl(speciesAnalysis?.putativeSkp1TreePath!)" target="_blank">
{{speciesAnalysis?.putativeSkp1}} putative</a>
</ng-template>
</mat-card-subtitle>
</ng-template>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<mat-form-field>
<mat-label>Results:</mat-label>
<mat-select (selectionChange)="onChangeResults($event.value)" [value]="id">
<mat-option *ngFor="let analysisName of speciesAnalysisNames" [value]="analysisName">
{{analysisName}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-divider></mat-divider>
<div>
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="predicted">
<th mat-header-cell *matHeaderCellDef>Predicted</th>
......@@ -76,7 +67,8 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header>Region</th>
<td mat-cell *matCellDef="let analysis">
<div *ngIf="analysis.getRegionPdfPath(isChecked(analysis))!==null; then thenBlockRegion else elseBlockRegion"></div>
<div
*ngIf="analysis.getRegionPdfPath(isChecked(analysis))!==null; then thenBlockRegion else elseBlockRegion"></div>
<ng-template #thenBlockRegion>
<a [href]="buildFileUrl(analysis.getRegionPdfPath(isChecked(analysis)))" target="_blank">
{{analysis.regionName}}
......@@ -90,7 +82,8 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header>Model</th>
<td mat-cell *matCellDef="let analysis">
<div *ngIf="analysis.getModelFastaPath(isChecked(analysis))!==null; then thenBlockModel else elseBlockModel"></div>
<div
*ngIf="analysis.getModelFastaPath(isChecked(analysis))!==null; then thenBlockModel else elseBlockModel"></div>
<ng-template #thenBlockModel>
<a [href]="buildFileUrl(analysis.getModelFastaPath(isChecked(analysis)))" target="_blank">
{{analysis.modelName}}
......@@ -106,7 +99,7 @@
<ul>
<li *ngFor="let distance of analysis.getMinTreeDistance(isChecked(analysis))">
<a [href]="buildFileUrl(analysis.getPhylogenyTreePath(isChecked(analysis)))" target="_blank">
{{distance.region}}: {{distance.score}}
{{distance.region}}: {{distance.score}}
</a>
</li>
</ul>
......
......@@ -2,44 +2,12 @@ table {
width: 100%;
}
#family-link {
text-decoration: none;
color: inherit;
}
a {
color: #3f51b5;
text-decoration: none;
}
a:hover{
color:#2f3b80;
}
mark{
background-color: #f8f9fa!important;
border-radius: 3px;
font-size: medium;
}
.form-select {
display: block;
width: 50%;
padding: .375rem 2.25rem .375rem .75rem;
-moz-padding-start: calc(0.75rem - 3px);
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right .75rem center;
background-size: 16px 12px;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
a:hover {
color: #2f3b80;
}
import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, ParamMap, Router} from '@angular/router';
import {SpeciesAnalysis} from 'src/app/models/SpeciesAnalysis';
import {DataService} from 'src/app/services/data.service';
import {SLFDatabase} from '../../models/SLFDatabase';
import {FamilyAnalysis} from '../../models/FamilyAnalysis';
import {PaginatedDataProvider} from '../../models/pagination/paginated-data-provider';
import {ListingOptions} from '../../models/pagination/listing-options';
import {Observable, of} from 'rxjs';
import {PageData} from '../../models/pagination/page-data';
import {SpeciesRow} from '../../models/SpeciesRow';
import {MatPaginatedDataSource} from '../../models/pagination/mat-paginated-data-source';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import {MatSnackBar} from '@angular/material/snack-bar';
import {environment} from '../../../environments/environment';
import {MatPaginator} from "@angular/material/paginator";
class SpeciesPaginatedProvider implements PaginatedDataProvider<SpeciesRow> {
......@@ -77,16 +74,13 @@ class SpeciesPaginatedProvider implements PaginatedDataProvider<SpeciesRow> {
export class ResultComponent implements OnInit {
@ViewChild(MatPaginator) public paginator?: MatPaginator;
@ViewChild(MatSort) public sort?: MatSort;
public readonly id: string;
public id: string;
public readonly familyName: string;
private readonly speciesName: string;
private database?: SLFDatabase;
private familyAnalysis?: FamilyAnalysis;
public speciesAnalysis?: SpeciesAnalysis;
public speciesAnalysisNames: string[];
public rowData: SpeciesRow[];
private checkedAnalysis: Map<string, Map<string, boolean>>;
private _dataSource?: MatPaginatedDataSource<SpeciesRow>;
private dataProvider?: SpeciesPaginatedProvider;
......@@ -94,8 +88,6 @@ export class ResultComponent implements OnInit {
['predicted', 'region', 'model', 'min_tree_distance', 'fbox', 'isoelectric_point'];
constructor(
private readonly changeDetectorRef: ChangeDetectorRef,
private readonly snackBar: MatSnackBar,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly dataService: DataService
......@@ -110,26 +102,34 @@ export class ResultComponent implements OnInit {
this.speciesName = this.id.substring(0, this.id.indexOf('_' + this.familyName));
this.speciesAnalysisNames = [];
this.rowData = [];
this.checkedAnalysis = new Map<string, Map<string, boolean>>();
}
public ngOnInit(): void {
this.dataProvider = new SpeciesPaginatedProvider(this.familyName, this.id, this.dataService);
this._dataSource = new MatPaginatedDataSource<SpeciesRow>(this.dataProvider);
this.dataService.getFamily(this.familyName)
.subscribe(familyAnalysis => {
this.familyAnalysis = familyAnalysis;
console.log(familyAnalysis);
this.speciesAnalysis = familyAnalysis.speciesAnalysis[this.id];
console.log(this.speciesAnalysis);
this.speciesAnalysisNames = Object.keys(familyAnalysis.speciesAnalysis)
.filter(speciesName => speciesName.includes(this.speciesName));
});
this.changeId(this.id);
}
public ngAfterViewInit(): void {
private changeId(id: string): void {
this.id = id;
const paramMap: ParamMap = this.route.snapshot.paramMap;
if (this.id !== paramMap.get('id')) {
this.router.navigate(['species', this.familyName, this.id])
.then(() => this.updateDataSource());
} else {
this.updateDataSource();
}
}
private updateDataSource(): void {
this.dataProvider = new SpeciesPaginatedProvider(this.familyName, this.id, this.dataService);
this._dataSource = new MatPaginatedDataSource<SpeciesRow>(this.dataProvider);
this._dataSource?.setControls(this.paginator, this.sort);
}
......@@ -141,8 +141,8 @@ export class ResultComponent implements OnInit {
}
public onChangeResults(value: string): void {
this.router.navigate(['species', this.familyName, value])
.then(() => window.location.reload());
console.log("EVENT");
this.changeId(value);
}
public isChecked(analysis: SpeciesRow): boolean {
......
......@@ -4,11 +4,9 @@ export class SpeciesAnalysis {
constructor(
public regionAnalysis: NamedRegionAnalysis,
public name: string,
public predictedSkp1?: number,
public putativeSkp1?: number,
public predictedSkp1TreePath?: string,
public putativeSkp1TreePath?: string) {
public predictedSkp1: number | null,
public putativeSkp1: number | null,
public predictedSkp1TreePath: string | null,
public putativeSkp1TreePath: string | null) {
}
}
......@@ -20,12 +20,12 @@
*/
import {PaginatedDataSource} from './paginated-data-source';
import {PaginatedDataProvider} from './paginated-data-provider';
import {MatPaginator, PageEvent} from '@angular/material/paginator';
import {MatSort, Sort} from '@angular/material/sort';
import {Subscription} from 'rxjs/internal/Subscription';
import {ListingOptions} from './listing-options';
import {SortDirection} from './sort-direction.enum';
import {Observable} from 'rxjs/internal/Observable';
import {MatPaginator, PageEvent} from "@angular/material/paginator";
export class MatPaginatedDataSource<T> extends PaginatedDataSource<T> {
public static readonly DEFAULT_PAGE_SIZE = 10;
......
......@@ -65,10 +65,7 @@ export class DataService {
public hasFamily(name: string): Observable<boolean> {
return this.getDatabase()
.pipe(
tap(database => console.log(database)),
tap(database => console.log(name in database.families)),
map(database => name in database.families),
tap(exists => console.log(exists))
);
}
......@@ -98,18 +95,10 @@ export class DataService {
throw new Error('multipleFamilyAnalysis is already initialized');
}
/*this.http.get<SLFDatabase>(`${environment.apiUrl}/database`)
.subscribe(database => {
this.database.next(database);
});*/
this.http.get<SLFDatabase>(`${environment.apiUrl}/database`,
{headers: new HttpHeaders({'Content-Type': 'application/gzip'})}).subscribe(database => {
this.database.next(database);
console.log(database)
});
this.http.get<SLFDatabase>(`${environment.apiUrl}/database`,
{headers: new HttpHeaders({'Content-Type': 'application/gzip'})}).subscribe(database => {
this.database.next(database);
});
}
public listFamilySpecies(familyName: string): Observable<string[]> {
......