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:
21
web/package-lock.json
generated
21
web/package-lock.json
generated
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
62
web/src/pages/flows/FlowDiagram.ts
Normal file
62
web/src/pages/flows/FlowDiagram.ts
Normal 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``);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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}>
|
||||
|
||||
Reference in New Issue
Block a user