Skip to content

Commit

Permalink
Improved diagram performance (#456)
Browse files Browse the repository at this point in the history
* improved diagram performance

* extraneous log

* style is no longer always present

* refresh fix
  • Loading branch information
therealryan authored Jul 11, 2023
1 parent f93cf3b commit 58a71ce
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void filteredInteractions() {
" CHE",
"Edges:",
" AVA normal solid BEN",
" AVA thick solid CHE <INVISIBLE>" );
" AVA normal solid CHE <INVISIBLE>" );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -25,6 +26,7 @@
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

Expand Down Expand Up @@ -447,10 +449,12 @@ private static String summariseSVG( String svg ) {
.findFirst().orElse( prefix + "???" ) );
} );

if( nl.item( i ).getAttributes().getNamedItem( "style" ).getTextContent()
.contains( "stroke-width: 0" ) ) {
sb.append( " <INVISIBLE>" );
}
Optional.of( nl.item( i ) )
.map( Node::getAttributes )
.map( a -> a.getNamedItem( "style" ) )
.map( Node::getTextContent )
.filter( s -> s.contains( "stroke-width: 0" ) )
.ifPresent( s -> sb.append( " <INVISIBLE>" ) );
}

return sb.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class SystemDiagramComponent implements OnInit {
loadProgress: number = 0;
summary: string = "";
edges: Edge[] = [];
renderedEdgeCount: number = 0;
hovered: Entry | null = null;

@ViewChild('myTestDiv') containerElRef: ElementRef | null = null;
Expand Down Expand Up @@ -76,6 +77,8 @@ export class SystemDiagramComponent implements OnInit {
f!.root, this.edges, requests)
);

// force a re-render of the diagram
this.renderedEdgeCount = -1;
this.refilterEdges();
}

Expand Down Expand Up @@ -178,29 +181,105 @@ export class SystemDiagramComponent implements OnInit {
this.summary = ic + " interactions between " + ac + " actors";

if (this.containerElRef != null) {
// it looks like mermaid doesn't have great support for refreshing
// an existing diagram - we have to clear an attribute and manually
// delete the generated svg
this.containerElRef.nativeElement
.querySelector("pre")
.removeAttribute("data-processed");
this.containerElRef.nativeElement
.querySelector("pre")
.innerHTML = "";

if (this.edges.length > 0) {
let diagram = "graph LR\n" + this.edges
.map(e => " " + e.from + " " + e.edge + " " + e.to)
.join("\n");
// now we know we have something to draw, put that text into
// the dom and trigger mermaid
if (this.edges.length != this.renderedEdgeCount) {
// we 've got a new edge - we have to rerender the diagram completely

// it looks like mermaid doesn't have great support for refreshing
// an existing diagram - we have to clear an attribute and manually
// delete the generated svg
this.containerElRef.nativeElement
.querySelector("pre")
.removeAttribute("data-processed");
this.containerElRef.nativeElement
.querySelector("pre")
.innerHTML = diagram;
.innerHTML = "";

if (this.edges.length > 0) {
let diagram = "graph LR\n" + this.edges
.map(e => " " + e.from + " " + e.edge + " " + e.to)
.join("\n");
// now we know we have something to draw, put that text into
// the dom and trigger mermaid
this.containerElRef.nativeElement
.querySelector("pre")
.innerHTML = diagram;

mermaid.init();
this.renderedEdgeCount = this.edges.length;
}
}
else {
// edge count hasn't changed, so we can get away with editing styles
let paths: HTMLElement[] = (Array.from(this.containerElRef?.nativeElement
.querySelectorAll("path")) as HTMLElement[])
.filter(path => path.classList.contains("flowchart-link"));

mermaid.init();
this.edges.forEach(edge => {
paths
.filter(path => path.classList.contains("LS-" + edge.from)
&& path.classList.contains("LE-" + edge.to))
.forEach(path => {
if (edge.edge === this.dottedEdge) {
this.dottedEdgeStyle(path);
}
else if (edge.edge === this.thickEdge) {
this.thickEdgeStyle(path);
}
else if (edge.edge === this.invisibleEdge) {
this.invisibleEdgeStyle(path);
}
else {
this.lineEdgeStyle(path);
}
});
});
}
}
}

private lineEdgeStyle(e: HTMLElement): void {
this.replaceClass(e, "edge-thickness-", "normal");
this.replaceClass(e, "edge-pattern-", "solid");
this.setAttr(e, "style", "");
this.setAttr(e, "marker-end", "url(#flowchart-pointEnd)");
}

private thickEdgeStyle(e: HTMLElement): void {
this.replaceClass(e, "edge-thickness-", "thick");
this.replaceClass(e, "edge-pattern-", "solid");
this.setAttr(e, "style", "");
this.setAttr(e, "marker-end", "url(#flowchart-pointEnd)");
}

private dottedEdgeStyle(e: HTMLElement): void {
this.replaceClass(e, "edge-thickness-", "normal");
this.replaceClass(e, "edge-pattern-", "dotted");
this.setAttr(e, "style", "");
this.setAttr(e, "marker-end", "url(#flowchart-pointEnd)");
}

private invisibleEdgeStyle(e: HTMLElement): void {
this.replaceClass(e, "edge-thickness-", "normal");
this.replaceClass(e, "edge-pattern-", "solid");
this.setAttr(e, "style", "stroke-width: 0");
this.setAttr(e, "marker-end", "");
}

private replaceClass(e: HTMLElement, prefix: string, suffix: string) {
e.classList.forEach(c => {
if (c.startsWith(prefix)) {
e.classList.remove(c);
}
});
e.classList.add(prefix + suffix);
}

private setAttr(e: HTMLElement, name: string, value: string) {
if (value) {
e.setAttribute(name, value);
}
else {
e.removeAttribute(name);
}
}
}
71 changes: 2 additions & 69 deletions report/report-ng/projects/report/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,75 +8,8 @@
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script type="text/javascript">
data =
// START_JSON_DATA
{
"meta": {
"modelTitle": "Flow testing example system",
"testTitle": "Integration test",
"timestamp": 1688369394714
},
"entries": [{
"description": "empty",
"tags": ["PASS", "direct", "histogram"],
"detail": "9539207BDB23D6F30524F7EF1013AA41"
}, {
"description": "empty",
"tags": ["PASS", "direct", "histogram", "web"],
"detail": "DE4215272BF59E7495457029BEA52864"
}, {
"description": "hello",
"tags": ["PASS", "direct", "histogram", "subset", "web"],
"detail": "28E14F191FFDD2FC5D3DE6E233DE754F"
}, {
"description": "hello",
"tags": ["PASS", "direct", "histogram"],
"detail": "482730F5C81EA0249B98F6DA9D9780EA"
}, {
"description": "vowels",
"tags": ["PASS", "direct", "histogram", "subset"],
"detail": "D43EDB48A3B1196C0B73D0D33626C333"
}, {
"description": "yodel",
"tags": ["PASS", "direct", "histogram"],
"detail": "7E22263CB3957E4841C81B8933D5CB47"
}, {
"description": "enqueue",
"tags": ["PASS", "chain:provoked", "deferred", "enqueue", "histogram"],
"detail": "A8B79C3F37F3AD89996982A976D64E2D"
}, {
"description": "pre",
"tags": ["PASS", "chain:provoked", "deferred", "histogram", "query"],
"detail": "AEE996A366DE06478D69800343205EFE"
}, {
"description": "process",
"tags": ["PASS", "chain:provoked", "deferred", "histogram", "process"],
"detail": "6AD48A1226A7921950AAE77C926869FA"
}, {
"description": "post",
"tags": ["PASS", "chain:provoked", "deferred", "histogram", "query"],
"detail": "25A183B8702781E33E69363406D4CEC9"
}, {
"description": "results",
"tags": ["PASS", "chain:provoked", "deferred", "histogram", "retrieve"],
"detail": "35089CAEECE7FC6D2D141B3547F65D84"
}, {
"description": "enqueue",
"tags": ["PASS", "deferred", "enqueue", "histogram"],
"detail": "DE493EFD0A6870C6557C9310E795B97C"
}, {
"description": "results",
"tags": ["PASS", "deferred", "histogram", "retrieve"],
"detail": "2C77C8FC80B065593F294F386EA0385C"
}, {
"description": "hello",
"tags": ["PASS", "direct", "histogram", "timeout"],
"detail": "C137C97BF006B35EACD1FE7287E5BD7D"
}, {
"description": "hello",
"tags": ["PASS", "direct", "failure", "histogram"],
"detail": "71F6B8B040538DF548C766F5222D59E1"
}]
}
// START_JSON_DATA
"You'll want to replace this with an actual index or flow data structure"
// END_JSON_DATA
;
</script>
Expand Down

0 comments on commit 58a71ce

Please sign in to comment.