Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System diagram #443

Merged
merged 10 commits into from
Jul 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,78 @@ public JsApp( String name, Path resDir ) {
.orElseThrow(
() -> new IllegalStateException( "Failed to find index.html in " + resDir ) );
indexTemplate = new Template( originalIndexPath );
Files.delete( originalIndexPath );
}
catch( IOException ioe ) {
throw new UncheckedIOException( "Failed to extract index.html", ioe );
}

fixLazyChunkLoadingPath( resDir );
}

/**
* <p>
* I hate this with the heat of a thousand suns, but I <i>really</i> want the
* report file structure to be like:
* </p>
*
* <pre>
* /report
* ├ index.html
* ├ /detail
* │ ├ &lt;hash&gt;.html
* │ ├ &lt;hash&gt;.html
* │ ├ ...
* │ └ &lt;hash&gt;.html
* └ /res
* ├ main.&lt;hash&gt;.js
* ├ polyfills.&lt;hash&gt;.js
* ├ &lt;whatever>.&lt;hash&gt;.js
* ├ ...
* └ styles.&lt;hash&gt;.css
* </pre>
* <p>
* This makes the report entrypoint super-obvious. Angular seems to have other
* ideas though, and all the stuff that I want in <code>/res</code> is just
* splatted into the root directory.
* </p>
* <p>
* We're working around this in two ways:
* </p>
* <ul>
* <li>Updating index.html to add <code>/res</code> to resource reference paths.
* That's what is happening in {@link Template#insert(Object, Path)}</li>
* <li>This method, which is dealing with lazy-loaded javascript chunks by
* updating <code>runtime.js</code> to add <code>/res</code>.</li>
* </ul>
* <p>
* <b>N.B.:</b> This second fix will work OK for the index page, but it will
* fail for the for detail pages, as we can apply the first fix dynamically in
* the detail pages, but they all share the same <code>runtime.js</code> file,
* and we can only fix the relative path once. For the moment we only need the
* runtime.js fix for mermaid, which is only used in the index page, so this
* isn't a problem yet.
* </p>
*
* @param resDir
*/
private static void fixLazyChunkLoadingPath( Path resDir ) {
try( Stream<Path> files = Files.find( resDir, 1,
( path, attr ) -> path.getFileName().toString().startsWith( "runtime." ) ) ) {
Path runtime = files.findFirst()
.orElse( null );
if( runtime != null ) {
String content = new String( Files.readAllBytes( runtime ), UTF_8 );
String fixed = content.replaceAll( "(\\(\\d+===e\\?\"common\":e\\))", "\"res/\" + $1" );
if( fixed.equals( content ) ) {
throw new IllegalStateException( "Failed to fix chunk load path" );
}
Files.write( runtime, fixed.getBytes( UTF_8 ) );
}
}
catch( IOException ioe ) {
throw new UncheckedIOException( "Failed to update lazy chunk loading", ioe );
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,35 @@ void write() throws Exception {
+ "detail/4C5FFE22176C7ABC272D95A0E5D62262.html\n"
+ "detail/823B8031950E57346DCE6FFD4BE56F54.html\n"
+ "index.html\n"
+ "res/100.<hash>.js\n"
+ "res/104.<hash>.js\n"
+ "res/124.<hash>.js\n"
+ "res/136.<hash>.js\n"
+ "res/14.<hash>.js\n"
+ "res/170.<hash>.js\n"
+ "res/220.<hash>.js\n"
+ "res/297.<hash>.js\n"
+ "res/331.<hash>.js\n"
+ "res/373.<hash>.js\n"
+ "res/377.<hash>.js\n"
+ "res/3rdpartylicenses.txt\n"
+ "res/435.<hash>.js\n"
+ "res/458.<hash>.js\n"
+ "res/486.<hash>.js\n"
+ "res/487.<hash>.js\n"
+ "res/491.<hash>.js\n"
+ "res/531.<hash>.js\n"
+ "res/552.<hash>.js\n"
+ "res/673.<hash>.js\n"
+ "res/688.<hash>.js\n"
+ "res/703.<hash>.js\n"
+ "res/726.<hash>.js\n"
+ "res/759.<hash>.js\n"
+ "res/829.<hash>.js\n"
+ "res/835.<hash>.js\n"
+ "res/985.<hash>.js\n"
+ "res/common.<hash>.js\n"
+ "res/favicon.ico\n"
+ "res/index.html\n"
+ "res/main.<hash>.js\n"
+ "res/polyfills.<hash>.js\n"
+ "res/runtime.<hash>.js\n"
Expand Down
5 changes: 4 additions & 1 deletion report/report-ng/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
"@angular/platform-browser-dynamic": "^14.1.2",
"@angular/router": "^14.1.2",
"@babel/core": "^7.22.5",
"@types/d3": "^7.4.0",
"@types/diff-match-patch": "^1.0.32",
"@types/dompurify": "^3.0.2",
"diff-match-patch": "^1.0.5",
"mermaid": "^10.2.4",
"ngx-markdown": "^14.0.1",
"rxjs": "~7.8.1",
"tslib": "^2.6.0",
Expand All @@ -45,4 +48,4 @@
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~4.8.4"
}
}
}
4 changes: 3 additions & 1 deletion report/report-ng/projects/report/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ import { RouterModule, Routes } from '@angular/router';
import { TagSummaryComponent } from './tag-summary/tag-summary.component';
import { ResidueViewComponent } from './residue-view/residue-view.component';
import { MsgSearchInputComponent } from './msg-search-input/msg-search-input.component';
import { MatRipple, MatRippleModule } from '@angular/material/core';
import { MatRippleModule } from '@angular/material/core';
import { HighlightedTextComponent } from './highlighted-text/highlighted-text.component';
import { TextDiffComponent } from './text-diff/text-diff.component';
import { SystemDiagramComponent } from './system-diagram/system-diagram.component';

const routes: Routes = [
{ path: "diff", component: ModelDiffComponent },
Expand Down Expand Up @@ -100,6 +101,7 @@ const routes: Routes = [
MsgSearchInputComponent,
HighlightedTextComponent,
TextDiffComponent,
SystemDiagramComponent,
],
imports: [
BrowserAnimationsModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { EntryHoverService } from './entry-hover.service';

describe('EntryHoverService', () => {
let service: EntryHoverService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(EntryHoverService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
23 changes: 23 additions & 0 deletions report/report-ng/projects/report/src/app/entry-hover.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { Entry } from './types';

/**
* Mechanism for watching which index entries are hovered over
*/
@Injectable({
providedIn: 'root'
})
export class EntryHoverService {

listeners: ((entry: Entry | null) => void)[] = [];

constructor() { }

onHover(callback: (entry: Entry | null) => void): void {
this.listeners.push(callback);
}

hovered(entry: Entry | null): void {
this.listeners.forEach(cb => cb(entry));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, HostListener } from '@angular/core';
import { Entry } from '../types';
import { IconEmbedService } from '../icon-embed.service';
import { EntryHoverService } from '../entry-hover.service';

@Component({
selector: 'app-flow-nav-item',
Expand All @@ -20,7 +21,10 @@ export class FlowNavItemComponent implements OnInit {

lineClass: string = "";

constructor(private icons: IconEmbedService,) {
constructor(
icons: IconEmbedService,
private hover: EntryHoverService,
) {
icons.register("check_circle_outline", "error_outline", "help_outline", "new_releases");
}

Expand Down Expand Up @@ -48,6 +52,14 @@ export class FlowNavItemComponent implements OnInit {
}
}

@HostListener('mouseenter') onMouseEnter() {
this.hover.hovered(this.entry);
}

@HostListener('mouseleave') onMouseLeave() {
this.hover.hovered(null);
}

tags(): string[] {
return this.entry.tags.filter(t => {
return this.showResult || (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ export class IndexRouteComponent implements OnInit {
this.indexData.set(this.index);
}

// looking for the route definitions? They're in app.module.ts
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

<app-tag-summary [entries]="filteredFlows"></app-tag-summary>

<app-system-diagram></app-system-diagram>

<app-flow-nav-list [entries]="filteredFlows" *ngIf="!error">
</app-flow-nav-list>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<mat-icon svgIcon="menu"></mat-icon>
</button>
<mat-menu #menu="matMenu">
<a mat-menu-item *ngFor="let item of displayItems()" routerLink="{{item.href}}">
<a mat-menu-item *ngFor="let item of displayItems()" routerLink="/{{item.href}}">
<mat-icon svgIcon="{{item.icon}}"></mat-icon>
{{item.text}}
</a>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#container {
text-align: center;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<mat-expansion-panel *ngIf="loadProgress != 0">
<mat-expansion-panel-header>
<mat-panel-title>Interactions</mat-panel-title>
<mat-panel-description>{{summary}}</mat-panel-description>
</mat-expansion-panel-header>
<div #myTestDiv id="container">
<mat-progress-bar *ngIf="loadProgress != 100" [value]="loadProgress"></mat-progress-bar>
<pre class="mermaid"></pre>
</div>
</mat-expansion-panel>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { SystemDiagramComponent } from './system-diagram.component';
import { ModelDiffDataService } from '../model-diff-data.service';
import { RouterTestingModule } from '@angular/router/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatExpansionModule } from '@angular/material/expansion';

describe('SystemDiagramComponent', () => {
let component: SystemDiagramComponent;
let fixture: ComponentFixture<SystemDiagramComponent>;
let mockMdds;

beforeEach(async () => {
mockMdds = jasmine.createSpyObj([
'path', 'index', 'onFlow', 'flowLoadProgress', 'flowFor']);
await TestBed.configureTestingModule({
declarations: [SystemDiagramComponent],
providers: [
{ provide: ModelDiffDataService, useValue: mockMdds },
],
imports: [
RouterTestingModule,
BrowserAnimationsModule,
MatExpansionModule,
]
})
.compileComponents();

fixture = TestBed.createComponent(SystemDiagramComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading