File

projects/web-mev/src/app/features/analysis/components/analysis-list/analyses.component.ts

Description

Analyses Component Used to display the list of available operations as a tree structure (the Tools tab)

Implements

OnInit

Metadata

changeDetection ChangeDetectionStrategy.Default
selector mev-analyses
styleUrls ./analyses.component.scss
templateUrl ./analyses.component.html

Index

Properties
Methods
Outputs

Constructor

constructor(route: ActivatedRoute, apiService: AnalysesService)
Parameters :
Name Type Optional
route ActivatedRoute No
apiService AnalysesService No

Outputs

executedOperationId
Type : EventEmitter<any>

Methods

getPlottingOperationCategory
getPlottingOperationCategory()

Add a 'fake' operation for plotting. It is a frontend-only operation to provide view for the normalization methods The user can select a numerical matrix and custom feature set to view a boxplot showing the distribution of expressions

Returns : { name: string; children: {}; }
ngOnInit
ngOnInit()

Initialize the datasource for the Operation Tree

Returns : void
Public showExecutedOperationResult
showExecutedOperationResult(data: any)

Function is triggered when the user starts an analysis and emits a newly created executed operation id

Parameters :
Name Type Optional
data any No
Returns : void
Public showOperationDetails
showOperationDetails(operation)

Function is triggered when the user clicks on a specific operation in the Operation Tree

Parameters :
Name Optional
operation No
Returns : void

Properties

Private _transformer
Default value : () => {...}
dataSource
Default value : new MatTreeFlatDataSource(this.treeControl, this.treeFlattener)
hasChild
Default value : () => {...}
operationCategories
Type : any[]
operations
Type : Operation[]
selectedOperation
Type : Operation
treeControl
Default value : new FlatTreeControl<ExampleFlatNode>( node => node.level, node => node.expandable )
treeFlattener
Default value : new MatTreeFlattener( this._transformer, node => node.level, node => node.expandable, node => node.children )
workspace$
Type : Observable<Workspace>
workspaceId
Type : string
import {
  Component,
  OnInit,
  ChangeDetectionStrategy,
  Output,
  EventEmitter
} from '@angular/core';
import { AnalysesService } from '../../services/analysis.service';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { Workspace } from '@app/features/workspace-manager/models/workspace';
import { Operation } from '../../models/operation';
import {
  MatTreeFlatDataSource,
  MatTreeFlattener
} from '@angular/material/tree';
import { FlatTreeControl } from '@angular/cdk/tree';

/**
 * Operation category with nested structure.
 * Each node has a name and an optional list of children.
 */
interface OperationCategoryNode {
  name: string;
  children?: Operation[];
}

/** Flat node with expandable and level information */
interface ExampleFlatNode {
  expandable: boolean;
  name: string;
  level: number;
}

/**
 * Analyses Component
 * Used to display the list of available operations as a tree structure (the Tools tab)
 */
@Component({
  selector: 'mev-analyses',
  templateUrl: './analyses.component.html',
  styleUrls: ['./analyses.component.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class AnalysesComponent implements OnInit {
  workspaceId: string;
  workspace$: Observable<Workspace>;
  operations: Operation[];
  operationCategories: any[];
  selectedOperation: Operation;

  @Output() executedOperationId: EventEmitter<any> = new EventEmitter<any>();

  treeControl = new FlatTreeControl<ExampleFlatNode>(
    node => node.level,
    node => node.expandable
  );

  private _transformer = (node: OperationCategoryNode, level: number) => {
    return {
      expandable: !!node.children && node.children.length > 0,
      level: level,
      ...node
    };
  };

  treeFlattener = new MatTreeFlattener(
    this._transformer,
    node => node.level,
    node => node.expandable,
    node => node.children
  );

  dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

  hasChild = (_: number, node: ExampleFlatNode) => node.expandable;

  constructor(
    private route: ActivatedRoute,
    private apiService: AnalysesService
  ) {}

  /**
   * Initialize the datasource for the Operation Tree
   */
  ngOnInit(): void {
    this.workspaceId = this.route.snapshot.paramMap.get('workspaceId');
    this.workspace$ = this.apiService.getWorkspaceDetail(this.workspaceId);

    this.apiService.getOperations().subscribe(operations => {
      this.operations = operations;
    });

    this.apiService.getOperationCategories().subscribe(operationCategories => {
      this.selectedOperation = operationCategories[0].children[0]; // show the parameters for the 1st operation by default
      operationCategories.push(this.getPlottingOperationCategory());
      this.dataSource.data = operationCategories;
      this.treeControl.expand(this.treeControl.dataNodes[0]); // expand the 1st operation category by default
    });
  }

  /**
   * Add a 'fake' operation for plotting. It is a frontend-only operation to provide
   * view for the normalization methods
   * The user can select a numerical matrix and custom feature set to view a boxplot showing the
   * distribution of expressions
   */
  getPlottingOperationCategory() {
    const op = {
      name: 'Plotting',
      children: [
        {
          id: 'Plotting',
          name: 'Plot expressions',
          description: 'Output view for the normalization methods',
          mode: 'client',
          inputs: {
            input_matrix: {
              description:
                'The input matrix. For example, a gene expression matrix for a cohort of samples.',
              name: 'Input matrix:',
              required: true,
              spec: {
                attribute_type: 'DataResource',
                many: false,
                resource_types: ['MTX', 'I_MTX', 'EXP_MTX', 'RNASEQ_COUNT_MTX']
              }
            },
            features: {
              description: 'The genes/features to use in plotting',
              name: 'Plot genes/features by:',
              required: false,
              spec: {
                attribute_type: 'FeatureSet'
              }
            }
          }
        }
      ]
    };
    return op;
  }

  /**
   * Function is triggered when the user clicks on a specific operation in the Operation Tree
   */
  public showOperationDetails(operation) {
    this.selectedOperation = operation;
  }

  /**
   * Function is triggered when the user starts an analysis and emits a newly created executed operation id
   */
  public showExecutedOperationResult(data: any) {
    this.executedOperationId.emit(data);
  }
}
<div class="analyses-container">
  <section class="analyses-section">
    <div class="tab-content">
      The analysis pane on the left side displays the list of available
      data analysis tools. Expand and collapse the list of tools clicking on a category.
      Click on a item to set input parameters and run an analysis.
      <div class="vertical-tab-container">
        <mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
          <!-- tree node template for leaf nodes -->
          <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding [ngClass]="{ 'active-node': node.id === selectedOperation.id }">
            <!-- use a disabled button to provide padding for tree leaf -->
            <button mat-icon-button disabled></button>
            <button (click)="showOperationDetails(node)">
              {{node.name}}
            </button>
          </mat-tree-node>
          <!-- tree node template for expandable nodes -->
          <mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
            <button matTreeNodeToggle [attr.aria-label]="'Toggle ' + node.name">
              <mat-icon class="mat-icon-rtl-mirror">
                {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
              </mat-icon>
              {{node.name}}
            </button>
            
          </mat-tree-node>
        </mat-tree>

        <mat-divider [vertical]="true"></mat-divider>

        <div class="operation-container">
          <mev-operation *ngIf="selectedOperation" [operation]="selectedOperation" [workspaceId]="workspaceId"
            [workspace$]="workspace$" (executedOperationId)="showExecutedOperationResult($event)"></mev-operation>
        </div>
      </div>
    </div>
  </section>
</div>

./analyses.component.scss

.analyses-section {
  margin: 20px;
  font-size: 14px !important;
}

.vertical-tab-container {
  margin: 30px 0;
  display: flex;
}

mat-tree {
  background-color: #ddebf2 !important;
  width: 300px;

  button {
    display: flex;
    align-items: center;
    border: 0;
    background: none;
    white-space: normal;
    padding-right: 15px;
    padding-left: 15px;
    text-align: left;

    &:hover {
      color: grey;
    }
  }

  .active-node {
    font-weight: bold;
    background-color: #eee !important;
  }
}

.operation-container {
  padding: 10px 20px;
  width: 100%;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""