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

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}>