flows: add diagrams (#415)

* flows: initial diagram implementation

* web: install flowchart.js, add flow diagram page

* web: adjust diagram colours for dark mode

* flows: add permission checks for diagram

* flows: fix formatting

* web: fix formatting for web

* flows: add fix when last stage has policy

* flows: add test for diagram

* web: flows/diagram: add support for light mode

* flows: make Flows's Diagram API return json, add more tests and fix swagger response
This commit is contained in:
Jens L
2020-12-26 17:05:11 +01:00
committed by GitHub
parent 33f5169f36
commit a9336f069c
9 changed files with 321 additions and 25 deletions

21
web/package-lock.json generated
View File

@ -1335,6 +1335,11 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"eve-raphael": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/eve-raphael/-/eve-raphael-0.5.0.tgz",
"integrity": "sha1-F8dUt5K+7z+maE15z1pHxjxM2jA="
},
"expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@ -1562,6 +1567,14 @@
"integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==",
"dev": true
},
"flowchart.js": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/flowchart.js/-/flowchart.js-1.15.0.tgz",
"integrity": "sha512-IyCVUFfHPLPgKLynw3NCkZ7CvKJdc/bAu0aHm+2AxKhtSBCiUC1kcTX1KautC3HOp1A2JS1IOcYxDTmcMkx5nQ==",
"requires": {
"raphael": "2.3.0"
}
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -2580,6 +2593,14 @@
"safe-buffer": "^5.1.0"
}
},
"raphael": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/raphael/-/raphael-2.3.0.tgz",
"integrity": "sha512-w2yIenZAQnp257XUWGni4bLMVxpUpcIl7qgxEgDIXtmSypYtlNxfXWpOBxs7LBTps5sDwhRnrToJrMUrivqNTQ==",
"requires": {
"eve-raphael": "0.5.0"
}
},
"regenerator-runtime": {
"version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",

View File

@ -16,6 +16,7 @@
"chart.js": "^2.9.4",
"codemirror": "^5.59.0",
"construct-style-sheets-polyfill": "^2.4.3",
"flowchart.js": "^1.15.0",
"lit-element": "^2.4.0",
"lit-html": "^1.3.0",
"rollup": "^2.35.1",

View File

@ -30,6 +30,10 @@ export class Flow {
return DefaultClient.fetch<Flow>(["flows", "instances", slug]);
}
static diagram(slug: string): Promise<{ diagram: string }> {
return DefaultClient.fetch<{ diagram: string }>(["flows", "instances", slug, "diagram"]);
}
static list(filter?: QueryArguments): Promise<PBResponse<Flow>> {
return DefaultClient.fetch<PBResponse<Flow>>(["flows", "instances"], filter);
}

View File

@ -0,0 +1,62 @@
import { customElement, html, LitElement, property, TemplateResult } from "lit-element";
import FlowChart from "flowchart.js";
import { Flow } from "../../api/Flows";
import { loading } from "../../utils";
export const FONT_COLOUR_DARK_MODE = "#fafafa";
export const FONT_COLOUR_LIGHT_MODE = "#151515";
export const FILL_DARK_MODE = "#18191a";
export const FILL_LIGHT_MODE = "#f0f0f0";
@customElement("ak-flow-diagram")
export class FlowDiagram extends LitElement {
@property()
set flowSlug(value: string) {
Flow.diagram(value).then((data) => {
this.diagram = FlowChart.parse(data.diagram);
});
}
@property({attribute: false})
diagram?: FlowChart.Instance;
@property()
fontColour: string = FONT_COLOUR_DARK_MODE;
@property()
fill: string = FILL_DARK_MODE;
createRenderRoot(): Element | ShadowRoot {
return this;
}
constructor() {
super();
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", (ev) => {
if (ev.matches) {
this.fontColour = FONT_COLOUR_LIGHT_MODE;
this.fill = FILL_LIGHT_MODE;
} else {
this.fontColour = FONT_COLOUR_DARK_MODE;
this.fill = FILL_DARK_MODE;
}
});
}
render(): TemplateResult {
if (this.diagram) {
this.diagram.drawSVG(this, {
"font-color": this.fontColour,
"line-color": "#bebebe",
"element-color": "#bebebe",
"fill": this.fill,
"yes-text": "Policy passes",
"no-text": "Policy denies",
});
return html``;
}
return loading(this.diagram, html``);
}
}

View File

@ -9,6 +9,7 @@ import "../../elements/buttons/ModalButton";
import "../../elements/buttons/SpinnerButton";
import "../../elements/policies/BoundPoliciesList";
import "./BoundStagesList";
import "./FlowDiagram";
@customElement("ak-flow-view")
export class FlowViewPage extends LitElement {
@ -49,6 +50,12 @@ export class FlowViewPage extends LitElement {
</div>
</section>
<ak-tabs>
<div slot="page-1" data-tab-title="${gettext("Flow Diagram")}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<ak-flow-diagram flowSlug=${this.flow.slug}>
</ak-flow-diagram>
</div>
</div>
<div slot="page-2" data-tab-title="${gettext("Stage Bindings")}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<ak-bound-stages-list .target=${this.flow.pk}>