diff --git a/capella_model_explorer/demo.py b/capella_model_explorer/demo.py index 65928d2..d1c1461 100644 --- a/capella_model_explorer/demo.py +++ b/capella_model_explorer/demo.py @@ -1,35 +1,97 @@ +# Copyright DB InfraGO AG and contributors +# SPDX-License-Identifier: Apache-2.0 + +import pathlib + import capellambse import pandas as pd import streamlit as st from jinja2.environment import Environment +WORKSPACE = pathlib.Path("~/models").expanduser() + env = Environment() +if "all_models" not in st.session_state: + st.session_state["all_models"] = { + i.name: i for i in WORKSPACE.rglob("*.aird") + } + +with st.sidebar: + model_name = st.selectbox( + "Select the Capella model", + st.session_state["all_models"].keys(), + index=None, + ) -@st.cache_resource -def load_model() -> capellambse.MelodyModel: - return capellambse.MelodyModel( - path="automated-train", - entrypoint="/automated-train.aird", +if not model_name: + st.stop() + +if ( + "model_name" not in st.session_state + or st.session_state["model_name"] != model_name +): + all_models = st.session_state["all_models"] + st.session_state.clear() + st.session_state["all_models"] = all_models + st.session_state["model"] = capellambse.MelodyModel( + st.session_state["all_models"][model_name] ) + st.session_state["model_name"] = model_name +model = st.session_state["model"] +with st.sidebar: + st.write(f"Loaded model {model.name!r}") + +sys_caps = model.sa.all_capabilities +sys_caps_idx = {cap.name: cap for cap in sys_caps} + +sys_fncs = model.sa.all_functions[1:] +sys_fncs_idx = {fnc.name: fnc for fnc in sys_fncs} +if "current_viewpoint" not in st.session_state: + st.session_state["current_viewpoint"] = {} +if "current_object" not in st.session_state: + st.session_state["current_object"] = {} + + +def jump_to(vp: str, name: str) -> None: + st.session_state["current_viewpoint"] = {"index": viewpoints.index(vp)} + if vp == "Capabilities": + st.session_state["current_object"] = { + "index": sys_caps.index(sys_caps_idx[name]) + } + elif vp == "Functions": + st.session_state["current_object"] = { + "index": sys_fncs.index(sys_fncs_idx[name]) + } -model = load_model() with st.sidebar: st.write("# Sidebar!") + viewpoints = ["Capabilities", "Functions", "Interfaces"] viewpoint = st.radio( - "Viewpoint:", ["Capabilities", "Functions", "Interfaces"] + "Viewpoint:", + viewpoints, + **st.session_state["current_viewpoint"], ) + st.session_state["current_viewpoint"] = {} if viewpoint == "Capabilities": with st.sidebar: - sys_caps = model.sa.all_capabilities - sys_caps_idx = {cap.name: cap for cap in sys_caps} + if not sys_caps_idx: + st.write( + 'The model has no Capabilities.', + unsafe_allow_html=True, + ) + st.stop() selected_name = st.selectbox( - "Select System Capability", options=sys_caps_idx.keys() + "Select System Capability", + options=sys_caps_idx.keys(), + **st.session_state["current_object"], ) + st.session_state["current_object"] = {} + cap = sys_caps_idx[selected_name] st.write(f"# {cap.name}") @@ -45,21 +107,35 @@ def load_model() -> capellambse.MelodyModel: ) st.image(cap.context_diagram.as_svg) - st.write(""" - ## Functional Requirements + st.write("## Data Flow Diagram") + st.image(cap.data_flow_view.as_svg) + + st.write( + """\ + ## Functional Requirements + + This section provides a summary of what functions are required from the + System and the actors to enable the system Capability. + """ + ) - This section provides a summary of what functions are required from the System and the actors to enable the system Capability. - """) - cap_real_entities = { entity.owner for entity in cap.involved_functions if entity.owner } for entity in cap_real_entities: - st.write(f"### {entity.name} \nTo enable the system Capability **{cap.name}** the **{entity.name}** shall:") + st.write( + f"### {entity.name}\n" + f"To enable the system Capability **{cap.name}**" + f" the **{entity.name}** shall:" + ) for fnc in cap.involved_functions: if fnc.owner == entity: - st.button(fnc.name) + st.button( + fnc.name, + on_click=jump_to, + args=("Functions", fnc.name), + ) table = pd.DataFrame( [ @@ -79,39 +155,69 @@ def load_model() -> capellambse.MelodyModel: # table.style.set_properties(**{"white-space": "pre-wrap"}), # hide_index=True, # ) + st.divider() + st.write(cap.__html__(), unsafe_allow_html=True) elif viewpoint == "Functions": - table_template = """ - To realize this capability the System and involved actors are required to perform the following functions:
-Involved Entity | Required function | -
---|---|
{{owner}} | -- {% for fnc in fncs %} - - {{fnc.name}} - {% endfor %} - | -