File

src/app/pages/model-checker/model-checker.page.ts

Description

Page for ModelChecking. Contains an input for a formula, feedback-selection and the GraphEditorComponent.

Implements

OnDestroy

Metadata

Index

Properties
Methods

Constructor

Public constructor(store: Store<State>, router: Router, route: ActivatedRoute, snackBarService: SnackBarService, backendService: BackendService, dialog: MatDialog)
Parameters :
Name Type Optional
store Store<State> No
router Router No
route ActivatedRoute No
snackBarService SnackBarService No
backendService BackendService No
dialog MatDialog No

Methods

Public checkModel
checkModel(graph: FOLGraph, feedback: Feedback)
Parameters :
Name Type Optional
graph FOLGraph No
feedback Feedback No
Returns : void
Public ngOnDestroy
ngOnDestroy()
Returns : void
Public onSaveRequested
onSaveRequested(domainGraph: FOLGraph)
Parameters :
Name Type Optional
domainGraph FOLGraph No
Returns : void
Public requestGraphExport
requestGraphExport()
Returns : void
Public showFormulaSyntaxDialog
showFormulaSyntaxDialog()
Returns : void

Properties

Private Optional activeResultDialog
Type : MatDialogRef<ResultTreeDialog>
Public Readonly formula
Default value : new UntypedFormControl('', Validators.required)
Public Readonly graph
Type : Observable<D3Graph>
Default value : this.route.queryParams.pipe( map((params) => [params[GRAPH_SOURCE], params[GRAPH_KEY]]), filter(([source, key]) => source !== undefined && key !== undefined), mergeMap(([source, key]) => this.store.select(source).pipe( map((graphs: GraphCollection) => graphs[key]), filter((graph) => { const found = graph !== undefined; if (!found) { this.snackBarService.openSnackBar({ key: 'misc.graph-not-found' }); } return found; }), mergeMap((graph) => D3Graph.fromDomainGraph(graph).catch((error) => { this.snackBarService.openSnackBar(error); return new D3Graph(); }), ), ), ), )

The graph that is passed to the GraphComponent. Tries to retrieve the cached or stored graph by the query parameters.

Public Readonly graphExportRequests
Default value : new EventEmitter<void>()
import { Component, EventEmitter, OnDestroy } from '@angular/core';
import { UntypedFormControl, Validators } from '@angular/forms';
import { MatLegacyDialog as MatDialog, MatLegacyDialogRef as MatDialogRef } from '@angular/material/legacy-dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { filter, map, mergeMap } from 'rxjs/operators';

import { FormulaSyntaxDialog } from 'src/app/dialogs/formula-syntax/formula-syntax.dialog';
import { HttpProgressDialog } from 'src/app/dialogs/http-progress/http-progress.dialog';
import { ResultTreeDialog } from 'src/app/dialogs/result-tree/result-tree.dialog';
import { Feedback } from 'src/app/model/api/model-checker-request';
import { ModelCheckerResponse } from 'src/app/model/api/model-checker-response';
import D3Graph from 'src/app/model/d3/d3.graph';
import { FOLGraph } from 'src/app/model/domain/fol.graph';
import { GRAPH_KEY, GRAPH_SOURCE, GraphCollection, graphCollectionQueryParams } from 'src/app/model/domain/graph.collection';
import { BackendService } from 'src/app/services/backend.service';
import { SnackBarService } from 'src/app/services/snack-bar.service';
import { storeGraph } from 'src/app/store/actions';
import { State } from 'src/app/store/state';

/**
 * Page for ModelChecking.
 * Contains an input for a formula, feedback-selection and the GraphEditorComponent.
 */
@Component({
  selector: 'apollo-model-checker',
  templateUrl: './model-checker.page.html',
  styleUrls: ['./model-checker.page.scss'],
})
export class ModelCheckerPage implements OnDestroy {
  public readonly formula = new UntypedFormControl('', Validators.required);

  public readonly graphExportRequests = new EventEmitter<void>();

  /**
   * The graph that is passed to the GraphComponent.
   * Tries to retrieve the cached or stored graph by the query parameters.
   */
  public readonly graph: Observable<D3Graph> = this.route.queryParams.pipe(
    map((params) => [params[GRAPH_SOURCE], params[GRAPH_KEY]]),
    filter(([source, key]) => source !== undefined && key !== undefined),
    mergeMap(([source, key]) =>
      this.store.select(source).pipe(
        map((graphs: GraphCollection) => graphs[key]),
        filter((graph) => {
          const found = graph !== undefined;
          if (!found) {
            this.snackBarService.openSnackBar({ key: 'misc.graph-not-found' });
          }
          return found;
        }),
        mergeMap((graph) =>
          D3Graph.fromDomainGraph(graph).catch((error) => {
            this.snackBarService.openSnackBar(error);
            return new D3Graph();
          }),
        ),
      ),
    ),
  );

  private activeResultDialog?: MatDialogRef<ResultTreeDialog>;

  public constructor(
    private readonly store: Store<State>,
    private readonly router: Router,
    private readonly route: ActivatedRoute,
    private readonly snackBarService: SnackBarService,
    private readonly backendService: BackendService,
    private readonly dialog: MatDialog,
  ) {}

  public ngOnDestroy(): void {
    this.activeResultDialog?.close();
  }

  public onSaveRequested(domainGraph: FOLGraph): void {
    this.store.dispatch(storeGraph(domainGraph));
    this.router.navigate(['model-checker'], { queryParams: graphCollectionQueryParams('graphStore', domainGraph.name) });
  }

  public requestGraphExport(): void {
    if (this.formula.invalid) {
      return;
    }
    this.activeResultDialog?.close();
    this.graphExportRequests.emit();
  }

  public checkModel(graph: FOLGraph, feedback: Feedback): void {
    const request = this.backendService.checkModel(graph, this.formula.value, feedback);
    const requestDialog = this.dialog.open<HttpProgressDialog<ModelCheckerResponse>>(HttpProgressDialog, {
      width: '90%',
      data: request,
      autoFocus: false,
    });
    requestDialog.afterOpened().subscribe(() => {
      this.activeResultDialog?.close();
      this.activeResultDialog = undefined;
    });
    requestDialog
      .afterClosed()
      .pipe(filter((response) => response !== undefined))
      .subscribe((response: ModelCheckerResponse) => {
        this.activeResultDialog = this.dialog.open(ResultTreeDialog, {
          width: response.rootTrace.children ? '70%' : undefined,
          height: response.rootTrace.children ? '90%' : undefined,
          data: response,
          autoFocus: false,
          hasBackdrop: false,
        });
      });
  }

  public showFormulaSyntaxDialog(): void {
    this.dialog.open(FormulaSyntaxDialog, {
      minWidth: '50%',
      panelClass: 'unpadded-dialog',
    });
  }
}
<div class="model-checker-container">
  <div class="formula-section">
    <mat-form-field>
      <mat-label>{{ 'fol.formula' | translate }}</mat-label>
      <input matInput [formControl]="formula" placeholder="{{ 'fol.formula' | translate}}" autocomplete="off" (keyup.enter)="requestGraphExport()" />
      <button mat-icon-button matSuffix color="primary" (click)="showFormulaSyntaxDialog()">
        <mat-icon>help_outlined</mat-icon>
      </button>
    </mat-form-field>
    <button mat-raised-button class="check-button" (click)="requestGraphExport()" [disabled]="formula.invalid" color="primary">{{ 'actions.check' | translate}}</button>
    <apollo-feedback-selection #feedbackSelection></apollo-feedback-selection>
  </div>
  <div class="graph-section">
    <apollo-graph-editor
      [graph]="graph"
      [graphExportRequests]="graphExportRequests"
      (saveRequested)="onSaveRequested($event)"
      (graphExported)="checkModel($event, feedbackSelection.selectedFeedback)"
    ></apollo-graph-editor>
  </div>
</div>

./model-checker.page.scss

:host {
  display: block;
  height: 100%;
}

.model-checker-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.formula-section {
  display: flex;
  align-items: center;
  flex-wrap: wrap;

  mat-form-field {
    flex: 1;
    margin-right: 1rem;
  }

  .check-button {
    margin-right: 1rem;
  }
}

.graph-section {
  flex-grow: 1;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""