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

FSM state diagram #306

Merged
merged 11 commits into from
Jan 23, 2025
1 change: 1 addition & 0 deletions controller/templates/controller/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
href="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/themes/light.css" />
<script type="module"
src="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/shoelace-autoloader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/mermaid.min.js"></script>
{% endblock extra_js %}
{% block content %}
<div class="container-fluid no-padding no-margin">
Expand Down
44 changes: 40 additions & 4 deletions controller/templates/controller/partials/state_machine.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
{% load render_table from django_tables2 %}
<div _="on load if #argsDialog is not null remove #argsDialog"></div>
<form>
{% csrf_token %}
{% render_table table %}
</form>
<div class="row">
<div class="col-md-auto">
<form>
{% csrf_token %}
{% render_table table %}
</form>
</div>
<div class="col-md-auto">
<pre class="mermaid">
flowchart TD
jamesturner246 marked this conversation as resolved.
Show resolved Hide resolved

%% FSM states (nodes).
classDef default fill:#b5b3ae,stroke:black,stroke-width:2px

%% FSM transitions (edges).
linkStyle default background-color:#b5b3ae,stroke-width:2px

{{ flowchart }}
</pre>
</div>
</div>
<script>
// Initialize mermaid diagrams.
mermaid.initialize({
jamesturner246 marked this conversation as resolved.
Show resolved Hide resolved
theme: "base",
// Make flowchart text uppercase.
themeCSS: ".label { text-transform: uppercase; }",
themeVariables: {
primaryTextColor: "white",
edgeLabelBackground: "transparent", // HACK: custom edge label colour
},
});
// Refresh mermaid diagrams after htmx swap.
document.body.addEventListener("htmx:afterSwap", (event) => {
const target = event.detail.target;
if (target && target.querySelector(".mermaid")) {
mermaid.run({nodes: target.querySelectorAll(".mermaid")});
}
});
jamesturner246 marked this conversation as resolved.
Show resolved Hide resolved
</script>
17 changes: 15 additions & 2 deletions controller/views/partials.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,24 @@ def state_machine(request: HttpRequest) -> HttpResponse:
else:
raise ValueError(f"Invalid form: {form.errors}")

table = tables.FSMTable.from_dict(fsm.get_fsm_architecture(), ci.get_fsm_state())
states = fsm.get_fsm_architecture()
current_state = ci.get_fsm_state()

table = tables.FSMTable.from_dict(states, current_state)

link = 0
flowchart = ""
for state, events in states.items():
for event, target in events.items():
flowchart += f"{state}({state}) -->|{event}| {target}({target})\n"
if state == current_state:
flowchart += f"style {state} fill:#93c54b\n"
flowchart += f"linkStyle {link} background-color:#93c54b\n"
link += 1
jamesturner246 marked this conversation as resolved.
Show resolved Hide resolved

return render(
request=request,
context=dict(table=table),
context=dict(table=table, flowchart=flowchart),
template_name="controller/partials/state_machine.html",
)

Expand Down
Loading