-# Copyright (c) 2023 Cisco and/or its affiliates.
+# Copyright (c) 2024 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
"""
+import logging
import pandas as pd
import dash_bootstrap_components as dbc
from dash import Input, Output, State
from dash.exceptions import PreventUpdate
from ast import literal_eval
+from yaml import load, FullLoader, YAMLError
from ..utils.constants import Constants as C
from ..utils.control_panel import ControlPanel
from ..utils.trigger import Trigger
-from ..utils.utils import label, gen_new_url, generate_options
+from ..utils.utils import label, gen_new_url, generate_options, navbar_report, \
+ show_tooltip
from ..utils.url_processing import url_decode
from .tables import coverage_tables, select_coverage_data
self,
app: Flask,
data_coverage: pd.DataFrame,
- html_layout_file: str
+ html_layout_file: str,
+ tooltip_file: str
) -> None:
"""Initialization:
- save the input parameters,
:param app: Flask application running the dash application.
:param html_layout_file: Path and name of the file specifying the HTML
layout of the dash application.
+ :param tooltip_file: Path and name of the yaml file specifying the
+ tooltips.
:type app: Flask
:type html_layout_file: str
+ :type tooltip_file: str
"""
# Inputs
self._app = app
- self._html_layout_file = html_layout_file
self._data = data_coverage
+ self._html_layout_file = html_layout_file
+ self._tooltip_file = tooltip_file
# Get structure of tests:
tbs = dict()
tbs[rls][dut] = dict()
if tbs[rls][dut].get(d_ver, None) is None:
tbs[rls][dut][d_ver] = dict()
- if tbs[rls][dut][d_ver].get(infra, None) is None:
- tbs[rls][dut][d_ver][infra] = list()
- if area not in tbs[rls][dut][d_ver][infra]:
- tbs[rls][dut][d_ver][infra].append(area)
+ if tbs[rls][dut][d_ver].get(area, None) is None:
+ tbs[rls][dut][d_ver][area] = list()
+ if infra not in tbs[rls][dut][d_ver][area]:
+ tbs[rls][dut][d_ver][area].append(infra)
self._spec_tbs = tbs
f"Not possible to open the file {self._html_layout_file}\n{err}"
)
+ try:
+ with open(self._tooltip_file, "r") as file_read:
+ self._tooltips = load(file_read, Loader=FullLoader)
+ except IOError as err:
+ logging.warning(
+ f"Not possible to open the file {self._tooltip_file}\n{err}"
+ )
+ except YAMLError as err:
+ logging.warning(
+ f"An error occurred while parsing the specification file "
+ f"{self._tooltip_file}\n{err}"
+ )
+
# Callbacks:
if self._app is not None and hasattr(self, "callbacks"):
self.callbacks(self._app)
dbc.Row(
id="row-navbar",
class_name="g-0",
- children=[
- self._add_navbar()
- ]
+ children=[navbar_report((False, False, True, False)), ]
),
dbc.Row(
id="row-main",
self._add_ctrl_col(),
self._add_plotting_col()
]
+ ),
+ dbc.Offcanvas(
+ class_name="w-75",
+ id="offcanvas-documentation",
+ title="Documentation",
+ placement="end",
+ is_open=False,
+ children=html.Iframe(
+ src=C.URL_DOC_REL_NOTES,
+ width="100%",
+ height="100%"
+ )
)
]
)
]
)
- def _add_navbar(self):
- """Add nav element with navigation panel. It is placed on the top.
-
- :returns: Navigation bar.
- :rtype: dbc.NavbarSimple
- """
- return dbc.NavbarSimple(
- id="navbarsimple-main",
- children=[
- dbc.NavItem(
- dbc.NavLink(
- C.COVERAGE_TITLE,
- disabled=True,
- external_link=True,
- href="#"
- )
- )
- ],
- brand=C.BRAND,
- brand_href="/",
- brand_external_link=True,
- class_name="p-2",
- fluid=True
- )
-
def _add_ctrl_col(self) -> dbc.Col:
"""Add column with controls. It is placed on the left side.
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("CSIT Release"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-release",
+ "CSIT Release"
+ )),
dbc.Select(
id={"type": "ctrl-dd", "index": "rls"},
placeholder="Select a Release...",
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("DUT"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-dut",
+ "DUT"
+ )),
dbc.Select(
id={"type": "ctrl-dd", "index": "dut"},
placeholder="Select a Device under Test..."
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("DUT Version"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-dut-ver",
+ "DUT Version"
+ )),
dbc.Select(
id={"type": "ctrl-dd", "index": "dutver"},
placeholder=\
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("Infra"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-area",
+ "Area"
+ )),
dbc.Select(
- id={"type": "ctrl-dd", "index": "phy"},
- placeholder=\
- "Select a Physical Test Bed Topology..."
+ id={"type": "ctrl-dd", "index": "area"},
+ placeholder="Select an Area..."
)
],
size="sm"
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("Area"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-infra",
+ "Infra"
+ )),
dbc.Select(
- id={"type": "ctrl-dd", "index": "area"},
- placeholder="Select an Area..."
+ id={"type": "ctrl-dd", "index": "phy"},
+ placeholder=\
+ "Select a Physical Test Bed Topology..."
)
],
size="sm"
children=[
dbc.InputGroup(
[
- dbc.InputGroupText("Latency"),
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-show-latency",
+ "Latency"
+ )),
dbc.Checklist(
id="show-latency",
options=[{
[selected["dut"]].keys()
),
"dutver-dis": False,
+ "area-val": selected["area"],
+ "area-opt": [
+ {"label": label(v), "value": v} \
+ for v in sorted(self._spec_tbs[selected["rls"]]\
+ [selected["dut"]]\
+ [selected["dutver"]].keys())
+ ],
+ "area-dis": False,
"phy-val": selected["phy"],
"phy-opt": generate_options(
self._spec_tbs[selected["rls"]][selected["dut"]]\
- [selected["dutver"]].keys()
+ [selected["dutver"]][selected["area"]]
),
"phy-dis": False,
- "area-val": selected["area"],
- "area-opt": [
- {"label": label(v), "value": v} for v in sorted(
- self._spec_tbs[selected["rls"]]\
- [selected["dut"]][selected["dutver"]]\
- [selected["phy"]]
- )
- ],
- "area-dis": False,
"show-latency": show_latency
})
on_draw = True
try:
rls = ctrl_panel.get("rls-val")
dut = ctrl_panel.get("dut-val")
- dutver = self._spec_tbs[rls][dut][trigger.value]
- options = generate_options(dutver.keys())
+ ver = self._spec_tbs[rls][dut][trigger.value]
+ options = [
+ {"label": label(v), "value": v} for v in sorted(ver)
+ ]
disabled = False
except KeyError:
options = list()
disabled = True
ctrl_panel.set({
"dutver-val": trigger.value,
- "phy-val": str(),
- "phy-opt": options,
- "phy-dis": disabled,
"area-val": str(),
- "area-opt": list(),
- "area-dis": True
+ "area-opt": options,
+ "area-dis": disabled,
+ "phy-val": str(),
+ "phy-opt": list(),
+ "phy-dis": True
})
- elif trigger.idx == "phy":
+ elif trigger.idx == "area":
try:
rls = ctrl_panel.get("rls-val")
dut = ctrl_panel.get("dut-val")
- dutver = ctrl_panel.get("dutver-val")
- phy = self._spec_tbs[rls][dut][dutver][trigger.value]
- options = [
- {"label": label(v), "value": v} for v in sorted(phy)
- ]
+ ver = ctrl_panel.get("dutver-val")
+ options = generate_options(
+ self._spec_tbs[rls][dut][ver][trigger.value])
disabled = False
except KeyError:
options = list()
disabled = True
ctrl_panel.set({
- "phy-val": trigger.value,
- "area-val": str(),
- "area-opt": options,
- "area-dis": disabled
+ "area-val": trigger.value,
+ "phy-val": str(),
+ "phy-opt": options,
+ "phy-dis": disabled
})
- elif trigger.idx == "area":
- ctrl_panel.set({"area-val": trigger.value})
+ elif trigger.idx == "phy":
+ ctrl_panel.set({"phy-val": trigger.value})
selected = {
"rls": ctrl_panel.get("rls-val"),
"dut": ctrl_panel.get("dut-val"),
)
return dcc.send_data_frame(df.to_csv, C.COVERAGE_DOWNLOAD_FILE_NAME)
+
+ @app.callback(
+ Output("offcanvas-documentation", "is_open"),
+ Input("btn-documentation", "n_clicks"),
+ State("offcanvas-documentation", "is_open")
+ )
+ def toggle_offcanvas_documentation(n_clicks, is_open):
+ if n_clicks:
+ return not is_open
+ return is_open