from ..utils.trigger import Trigger
from ..utils.telemetry_data import TelemetryData
from ..utils.utils import show_tooltip, label, sync_checklists, gen_new_url, \
- generate_options, get_list_group_items
+ generate_options, get_list_group_items, graph_hdrh_latency
from ..utils.url_processing import url_decode
-from ..data.data import Data
-from .graphs import graph_trending, graph_hdrh_latency, select_trending_data, \
- graph_tm_trending
+from .graphs import graph_trending, select_trending_data, graph_tm_trending
# Control panel partameters and their default values.
"""The layout of the dash app and the callbacks.
"""
- def __init__(self, app: Flask, html_layout_file: str,
- graph_layout_file: str, data_spec_file: str, tooltip_file: str,
- time_period: str=None) -> None:
+ def __init__(self,
+ app: Flask,
+ data_trending: pd.DataFrame,
+ html_layout_file: str,
+ graph_layout_file: str,
+ tooltip_file: str
+ ) -> None:
"""Initialization:
- save the input parameters,
- read and pre-process the data,
- read tooltips from the tooltip file.
:param app: Flask application running the dash application.
+ :param data_trending: Pandas dataframe with trending data.
:param html_layout_file: Path and name of the file specifying the HTML
layout of the dash application.
:param graph_layout_file: Path and name of the file with layout of
plot.ly graphs.
- :param data_spec_file: Path and name of the file specifying the data to
- be read from parquets for this application.
:param tooltip_file: Path and name of the yaml file specifying the
tooltips.
- :param time_period: It defines the time period for data read from the
- parquets in days from now back to the past.
:type app: Flask
+ :type data_trending: pandas.DataFrame
:type html_layout_file: str
:type graph_layout_file: str
- :type data_spec_file: str
:type tooltip_file: str
- :type time_period: int
"""
# Inputs
self._app = app
+ self._data = data_trending
self._html_layout_file = html_layout_file
self._graph_layout_file = graph_layout_file
- self._data_spec_file = data_spec_file
self._tooltip_file = tooltip_file
- self._time_period = time_period
-
- # Read the data:
- data_mrr = Data(
- data_spec_file=self._data_spec_file,
- debug=True
- ).read_trending_mrr(days=self._time_period)
-
- data_ndrpdr = Data(
- data_spec_file=self._data_spec_file,
- debug=True
- ).read_trending_ndrpdr(days=self._time_period)
-
- self._data = pd.concat(
- [data_mrr, data_ndrpdr],
- ignore_index=True,
- copy=False
- )
# Get structure of tests:
tbs = dict()
- for _, row in self._data[["job", "test_id"]].drop_duplicates().\
- iterrows():
+ cols = ["job", "test_id", "test_type", "tg_type"]
+ for _, row in self._data[cols].drop_duplicates().iterrows():
lst_job = row["job"].split("-")
dut = lst_job[1]
- ttype = lst_job[3]
tbed = "-".join(lst_job[-2:])
lst_test = row["test_id"].split(".")
if dut == "dpdk":
area = "dpdk"
else:
- area = "-".join(lst_test[3:-2])
+ area = ".".join(lst_test[3:-2])
suite = lst_test[-2].replace("2n1l-", "").replace("1n1l-", "").\
replace("2n-", "")
test = lst_test[-1]
tbs[dut][infra][area][test]["frame-size"].append(
framesize.upper()
)
- if ttype == "mrr":
+ if row["test_type"] == "mrr":
if "MRR" not in tbs[dut][infra][area][test]["test-type"]:
tbs[dut][infra][area][test]["test-type"].append("MRR")
- elif ttype == "ndrpdr":
+ elif row["test_type"] == "ndrpdr":
if "NDR" not in tbs[dut][infra][area][test]["test-type"]:
tbs[dut][infra][area][test]["test-type"].extend(
("NDR", "PDR")
)
+ elif row["test_type"] == "hoststack":
+ if row["tg_type"] in ("iperf", "vpp"):
+ if "BPS" not in tbs[dut][infra][area][test]["test-type"]:
+ tbs[dut][infra][area][test]["test-type"].append("BPS")
+ elif row["tg_type"] == "ab":
+ if "CPS" not in tbs[dut][infra][area][test]["test-type"]:
+ tbs[dut][infra][area][test]["test-type"].extend(
+ ("CPS", "RPS")
+ )
self._spec_tbs = tbs
# Read from files:
id="div-main",
className="small",
children=[
- dcc.Store(id="store-selected-tests"),
- dcc.Store(id="store-control-panel"),
- dcc.Store(id="store-telemetry-data"),
- dcc.Store(id="store-telemetry-user"),
+ dcc.Store(id="store"),
dcc.Location(id="url", refresh=False),
dbc.Row(
id="row-navbar",
)
else:
return html.Div(
- id="div-main-error",
- children=[
- dbc.Alert(
- [
- "An Error Occured"
- ],
- color="danger"
- )
- ]
+ dbc.Alert("An Error Occured", color="danger"),
+ id="div-main-error"
)
def _add_navbar(self):
:rtype: dbc.NavbarSimple
"""
return dbc.NavbarSimple(
- id="navbarsimple-main",
- children=[
- dbc.NavItem(
- dbc.NavLink(
- C.TREND_TITLE,
- disabled=True,
- external_link=True,
- href="#"
- )
+ dbc.NavItem(
+ dbc.NavLink(
+ C.TREND_TITLE,
+ disabled=True,
+ external_link=True,
+ href="#"
)
- ],
+ ),
+ id="navbarsimple-main",
brand=C.BRAND,
brand_href="/",
brand_external_link=True,
:returns: Column with the control panel.
:rtype: dbc.Col
"""
- return dbc.Col([
- html.Div(
- children=self._add_ctrl_panel(),
- className="sticky-top"
- )
- ])
+ return dbc.Col(html.Div(self._add_ctrl_panel(), className="sticky-top"))
def _add_ctrl_panel(self) -> list:
"""Add control panel.
"""
return [
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-dut",
- "DUT"
- )
- ),
- dbc.Select(
- id={"type": "ctrl-dd", "index": "dut"},
- placeholder="Select a Device under Test...",
- options=sorted(
- [
- {"label": k, "value": k} \
- for k in self._spec_tbs.keys()
- ],
- key=lambda d: d["label"]
- )
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ show_tooltip(self._tooltips, "help-dut", "DUT")
+ ),
+ dbc.Select(
+ id={"type": "ctrl-dd", "index": "dut"},
+ placeholder="Select a Device under Test...",
+ options=sorted(
+ [
+ {"label": k, "value": k} \
+ for k in self._spec_tbs.keys()
+ ],
+ key=lambda d: d["label"]
)
- ],
- size="sm"
- )
- ]
+ )
+ ],
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-infra",
- "Infra"
- )
- ),
- dbc.Select(
- id={"type": "ctrl-dd", "index": "phy"},
- placeholder=\
- "Select a Physical Test Bed Topology..."
- )
- ],
- size="sm"
- )
- ]
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ show_tooltip(self._tooltips, "help-infra", "Infra")
+ ),
+ dbc.Select(
+ id={"type": "ctrl-dd", "index": "phy"},
+ placeholder="Select a Physical Test Bed Topology..."
+ )
+ ],
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-area",
- "Area"
- )
- ),
- dbc.Select(
- id={"type": "ctrl-dd", "index": "area"},
- placeholder="Select an Area..."
- )
- ],
- size="sm"
- )
- ]
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ show_tooltip(self._tooltips, "help-area", "Area")
+ ),
+ dbc.Select(
+ id={"type": "ctrl-dd", "index": "area"},
+ placeholder="Select an Area..."
+ )
+ ],
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-test",
- "Test"
- )
- ),
- dbc.Select(
- id={"type": "ctrl-dd", "index": "test"},
- placeholder="Select a Test..."
- )
- ],
- size="sm"
- )
- ]
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ show_tooltip(self._tooltips, "help-test", "Test")
+ ),
+ dbc.Select(
+ id={"type": "ctrl-dd", "index": "test"},
+ placeholder="Select a Test..."
+ )
+ ],
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-framesize",
- "Frame Size"
- )
- ),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "frmsize-all"
- },
- options=C.CL_ALL_DISABLED,
- inline=True,
- class_name="ms-2"
- )
- ],
- width=2
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-framesize",
+ "Frame Size"
+ )),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "frmsize-all"},
+ options=C.CL_ALL_DISABLED,
+ inline=True,
+ class_name="ms-2"
),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "frmsize"
- },
- inline=True
- )
- ]
+ width=2
+ ),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "frmsize"},
+ inline=True
)
- ],
- style={"align-items": "center"},
- size="sm"
- )
- ]
+ )
+ ],
+ style={"align-items": "center"},
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-cores",
- "Number of Cores"
- )
- ),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "core-all"
- },
- options=C.CL_ALL_DISABLED,
- inline=True,
- class_name="ms-2"
- )
- ],
- width=2
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-cores",
+ "Number of Cores"
+ )),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "core-all"},
+ options=C.CL_ALL_DISABLED,
+ inline=True,
+ class_name="ms-2"
),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "core"
- },
- inline=True
- )
- ]
+ width=2
+ ),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "core"},
+ inline=True
)
- ],
- style={"align-items": "center"},
- size="sm"
- )
- ]
+ )
+ ],
+ style={"align-items": "center"},
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-ttype",
- "Test Type"
- )
- ),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "tsttype-all"
- },
- options=C.CL_ALL_DISABLED,
- inline=True,
- class_name="ms-2"
- )
- ],
- width=2
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-ttype",
+ "Test Type"
+ )),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "tsttype-all"},
+ options=C.CL_ALL_DISABLED,
+ inline=True,
+ class_name="ms-2"
),
- dbc.Col(
- children=[
- dbc.Checklist(
- id={
- "type": "ctrl-cl",
- "index": "tsttype"
- },
- inline=True
- )
- ]
+ width=2
+ ),
+ dbc.Col(
+ dbc.Checklist(
+ id={"type": "ctrl-cl", "index": "tsttype"},
+ inline=True
)
- ],
- style={"align-items": "center"},
- size="sm"
- )
- ]
+ )
+ ],
+ style={"align-items": "center"},
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.InputGroup(
- [
- dbc.InputGroupText(
- children=show_tooltip(
- self._tooltips,
- "help-normalize",
- "Normalization"
- )
- ),
- dbc.Col(
- children=[
- dbc.Checklist(
- id="normalize",
- options=[{
- "value": "normalize",
- "label": (
- "Normalize to CPU frequency "
- "2GHz"
- )
- }],
- value=[],
- inline=True,
- class_name="ms-2"
- )
- ]
- )
- ],
- style={"align-items": "center"},
- size="sm"
- )
- ]
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(show_tooltip(
+ self._tooltips,
+ "help-normalize",
+ "Normalization"
+ )),
+ dbc.Col(dbc.Checklist(
+ id="normalize",
+ options=[{
+ "value": "normalize",
+ "label": "Normalize to CPU frequency 2GHz"
+ }],
+ value=[],
+ inline=True,
+ class_name="ms-2"
+ ))
+ ],
+ style={"align-items": "center"},
+ size="sm"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.Button(
- id={"type": "ctrl-btn", "index": "add-test"},
- children="Add Selected",
- color="info"
- )
- ]
+ dbc.Button(
+ id={"type": "ctrl-btn", "index": "add-test"},
+ children="Add Selected",
+ color="info"
+ ),
+ class_name="g-0 p-1"
),
dbc.Row(
+ dbc.ListGroup(
+ class_name="overflow-auto p-0",
+ id="lg-selected",
+ children=[],
+ style={"max-height": "20em"},
+ flush=True
+ ),
id="row-card-sel-tests",
class_name="g-0 p-1",
style=C.STYLE_DISABLED,
- children=[
- dbc.ListGroup(
- class_name="overflow-auto p-0",
- id="lg-selected",
- children=[],
- style={"max-height": "14em"},
- flush=True
- )
- ]
),
dbc.Row(
+ dbc.ButtonGroup([
+ dbc.Button(
+ "Remove Selected",
+ id={"type": "ctrl-btn", "index": "rm-test"},
+ class_name="w-100",
+ color="info",
+ disabled=False
+ ),
+ dbc.Button(
+ "Remove All",
+ id={"type": "ctrl-btn", "index": "rm-test-all"},
+ class_name="w-100",
+ color="info",
+ disabled=False
+ )
+ ]),
id="row-btns-sel-tests",
class_name="g-0 p-1",
style=C.STYLE_DISABLED,
- children=[
- dbc.ButtonGroup(
- children=[
- dbc.Button(
- id={"type": "ctrl-btn", "index": "rm-test"},
- children="Remove Selected",
- class_name="w-100",
- color="info",
- disabled=False
- ),
- dbc.Button(
- id={"type": "ctrl-btn", "index": "rm-test-all"},
- children="Remove All",
- class_name="w-100",
- color="info",
- disabled=False
- )
- ]
+ ),
+ dbc.Stack(
+ [
+ dbc.Button(
+ "Add Telemetry Panel",
+ id={"type": "telemetry-btn", "index": "open"},
+ color="info"
+ ),
+ dbc.Button("Show URL", id="plot-btn-url", color="info"),
+ dbc.Modal(
+ [
+ dbc.ModalHeader(dbc.ModalTitle("URL")),
+ dbc.ModalBody(id="mod-url")
+ ],
+ id="plot-mod-url",
+ size="xl",
+ is_open=False,
+ scrollable=True
)
- ]
+ ],
+ id="row-btns-add-tm",
+ class_name="g-0 p-1",
+ style=C.STYLE_DISABLED,
+ gap=2
)
]
id="plotting-area-telemetry",
class_name="g-0 p-0",
children=C.PLACEHOLDER
- ),
- dbc.Row(
- id="plotting-area-buttons",
- class_name="g-0 p-0",
- children=C.PLACEHOLDER
)
],
- width=9
+ width=9,
+ style=C.STYLE_DISABLED,
)
- def _get_plotting_area_buttons(self) -> dbc.Col:
- """Add buttons and modals to the plotting area.
-
- :returns: A column with buttons and modals for telemetry.
- :rtype: dbc.Col
- """
- return dbc.Col([
- html.Div(
- [
- dbc.Button(
- id={"type": "telemetry-btn", "index": "open"},
- children="Add Panel with Telemetry",
- class_name="me-1",
- color="info",
- style={
- "text-transform": "none",
- "padding": "0rem 1rem"
- }
- ),
- dbc.Modal(
- [
- dbc.ModalHeader(
- dbc.ModalTitle(
- "Select a Metric"
- ),
- close_button=False
- ),
- dbc.Spinner(
- dbc.ModalBody(
- id="plot-mod-telemetry-body-1",
- children=self._get_telemetry_step_1()
- ),
- delay_show=2*C.SPINNER_DELAY
- ),
- dbc.ModalFooter([
- dbc.Button(
- "Select",
- id={
- "type": "telemetry-btn",
- "index": "select"
- },
- disabled=True
- ),
- dbc.Button(
- "Cancel",
- id={
- "type": "telemetry-btn",
- "index": "cancel"
- },
- disabled=False
- )
- ])
- ],
- id="plot-mod-telemetry-1",
- size="lg",
- is_open=False,
- scrollable=False,
- backdrop="static",
- keyboard=False
- ),
- dbc.Modal(
- [
- dbc.ModalHeader(
- dbc.ModalTitle(
- "Select Labels"
- ),
- close_button=False
- ),
- dbc.Spinner(
- dbc.ModalBody(
- id="plot-mod-telemetry-body-2",
- children=self._get_telemetry_step_2()
- ),
- delay_show=2*C.SPINNER_DELAY
- ),
- dbc.ModalFooter([
- dbc.Button(
- "Back",
- id={
- "type": "telemetry-btn",
- "index": "back"
- },
- disabled=False
- ),
- dbc.Button(
- "Add Telemetry",
- id={
- "type": "telemetry-btn",
- "index": "add"
- },
- disabled=True
- ),
- dbc.Button(
- "Cancel",
- id={
- "type": "telemetry-btn",
- "index": "cancel"
- },
- disabled=False
- )
- ])
- ],
- id="plot-mod-telemetry-2",
- size="xl",
- is_open=False,
- scrollable=False,
- backdrop="static",
- keyboard=False
- )
- ],
- className="d-grid gap-0 d-md-flex justify-content-md-end"
- )
- ])
-
- def _get_plotting_area_trending(
- self,
- tests: list,
- normalize: bool,
- url: str
- ) -> dbc.Col:
+ @staticmethod
+ def _plotting_area_trending(graphs: list) -> dbc.Col:
"""Generate the plotting area with all its content.
- :param tests: A list of tests to be displayed in the trending graphs.
- :param normalize: If True, the data in graphs is normalized.
- :param url: An URL to be displayed in the modal window.
- :type tests: list
- :type normalize: bool
- :type url: str
+ :param graphs: A list of graphs to be displayed in the trending page.
+ :type graphs: list
:returns: A collumn with trending graphs (tput and latency) in tabs.
:rtype: dbc.Col
"""
- if not tests:
+ if not graphs:
return C.PLACEHOLDER
- figs = graph_trending(self._data, tests, self._graph_layout, normalize)
-
- if not figs[0]:
+ if not graphs[0]:
return C.PLACEHOLDER
tab_items = [
dbc.Tab(
children=dcc.Graph(
id={"type": "graph", "index": "tput"},
- figure=figs[0]
+ figure=graphs[0]
),
label="Throughput",
tab_id="tab-tput"
)
]
- if figs[1]:
+ if graphs[1]:
tab_items.append(
dbc.Tab(
children=dcc.Graph(
id={"type": "graph", "index": "lat"},
- figure=figs[1]
+ figure=graphs[1]
),
label="Latency",
tab_id="tab-lat"
)
trending = [
- dbc.Row(children=[
+ dbc.Row(
dbc.Tabs(
children=tab_items,
id="tabs",
active_tab="tab-tput",
- )
- ]),
+ ),
+ class_name="g-0 p-0"
+ ),
dbc.Row(
- [
- dbc.Col([html.Div(
- [
- dbc.Button(
- id="plot-btn-url",
- children="Show URL",
- class_name="me-1",
- color="info",
- style={
- "text-transform": "none",
- "padding": "0rem 1rem"
- }
- ),
- dbc.Modal(
- [
- dbc.ModalHeader(dbc.ModalTitle("URL")),
- dbc.ModalBody(url)
- ],
- id="plot-mod-url",
- size="xl",
- is_open=False,
- scrollable=True
- ),
- dbc.Button(
- id="plot-btn-download",
- children="Download Data",
- class_name="me-1",
- color="info",
- style={
- "text-transform": "none",
- "padding": "0rem 1rem"
- }
- ),
- dcc.Download(id="download-trending-data")
- ],
- className=\
- "d-grid gap-0 d-md-flex justify-content-md-end"
- )])
- ],
+ html.Div(
+ [
+ dbc.Button(
+ "Download Data",
+ id="plot-btn-download",
+ class_name="me-1",
+ color="info",
+ style={"padding": "0rem 1rem"}
+ ),
+ dcc.Download(id="download-trending-data")
+ ],
+ className="d-grid gap-0 d-md-flex justify-content-md-end"
+ ),
class_name="g-0 p-0"
)
]
return dbc.Col(
children=[
- dbc.Row(
- dbc.Accordion(
- children=[
- dbc.AccordionItem(
- title="Trending",
- children=trending
+ dbc.Accordion(
+ dbc.AccordionItem(trending, title="Trending"),
+ class_name="g-0 p-1",
+ start_collapsed=False,
+ always_open=True,
+ active_item=["item-0", ]
+ ),
+ dbc.Modal(
+ [
+ dbc.ModalHeader(
+ dbc.ModalTitle("Select a Metric"),
+ close_button=False
+ ),
+ dbc.Spinner(
+ dbc.ModalBody(Layout._get_telemetry_step_1()),
+ delay_show=2 * C.SPINNER_DELAY
+ ),
+ dbc.ModalFooter([
+ dbc.Button(
+ "Select",
+ id={"type": "telemetry-btn", "index": "select"},
+ color="success",
+ disabled=True
+ ),
+ dbc.Button(
+ "Cancel",
+ id={"type": "telemetry-btn", "index": "cancel"},
+ color="info",
+ disabled=False
+ ),
+ dbc.Button(
+ "Remove All",
+ id={"type": "telemetry-btn", "index": "rm-all"},
+ color="danger",
+ disabled=False
)
- ],
- class_name="g-0 p-1",
- start_collapsed=False,
- always_open=True,
- active_item=["item-0", ]
- ),
- class_name="g-0 p-0",
+ ])
+ ],
+ id={"type": "plot-mod-telemetry", "index": 0},
+ size="lg",
+ is_open=False,
+ scrollable=False,
+ backdrop="static",
+ keyboard=False
+ ),
+ dbc.Modal(
+ [
+ dbc.ModalHeader(
+ dbc.ModalTitle("Select Labels"),
+ close_button=False
+ ),
+ dbc.Spinner(
+ dbc.ModalBody(Layout._get_telemetry_step_2()),
+ delay_show=2 * C.SPINNER_DELAY
+ ),
+ dbc.ModalFooter([
+ dbc.Button(
+ "Back",
+ id={"type": "telemetry-btn", "index": "back"},
+ color="info",
+ disabled=False
+ ),
+ dbc.Button(
+ "Add Telemetry Panel",
+ id={"type": "telemetry-btn", "index": "add"},
+ color="success",
+ disabled=True
+ ),
+ dbc.Button(
+ "Cancel",
+ id={"type": "telemetry-btn", "index": "cancel"},
+ color="info",
+ disabled=False
+ )
+ ])
+ ],
+ id={"type": "plot-mod-telemetry", "index": 1},
+ size="xl",
+ is_open=False,
+ scrollable=False,
+ backdrop="static",
+ keyboard=False
)
]
)
- def _get_plotting_area_telemetry(self, graphs: list) -> dbc.Col:
+ @staticmethod
+ def _plotting_area_telemetry(graphs: list) -> dbc.Col:
"""Generate the plotting area with telemetry.
+
+ :param graphs: A list of graphs to be displayed in the telemetry page.
+ :type graphs: list
+ :returns: A collumn with telemetry trending graphs.
+ :rtype: dbc.Col
"""
if not graphs:
return C.PLACEHOLDER
-
- acc_items = list()
- for graph in graphs:
- acc_items.append(
+
+ def _plural(iterative):
+ return "s" if len(iterative) > 1 else str()
+
+ panels = list()
+ for idx, graph_set in enumerate(graphs):
+ acc_items = list()
+ for graph in graph_set[0]:
+ graph_name = ", ".join(graph[1])
+ acc_items.append(
+ dbc.AccordionItem(
+ dcc.Graph(
+ id={"type": "graph-telemetry", "index": graph_name},
+ figure=graph[0]
+ ),
+ title=(f"Test{_plural(graph[1])}: {graph_name}"),
+ class_name="g-0 p-0"
+ )
+ )
+ panels.append(
dbc.AccordionItem(
- title=f"Telemetry: {graph[1]}",
- children=dcc.Graph(
- id={"type": "graph-telemetry", "index": graph[1]},
- figure=graph[0]
+ [
+ dbc.Row(
+ dbc.Accordion(
+ children=acc_items,
+ class_name="g-0 p-0",
+ start_collapsed=True,
+ always_open=True,
+ flush=True
+ ),
+ class_name="g-0 p-0"
+ ),
+ dbc.Row(
+ html.Div(
+ [
+ dbc.Button(
+ "Remove",
+ id={
+ "type": "tm-btn-remove",
+ "index": idx
+ },
+ class_name="me-1",
+ color="danger",
+ style={"padding": "0rem 1rem"}
+ ),
+ dbc.Button(
+ "Download Data",
+ id={
+ "type": "tm-btn-download",
+ "index": idx
+ },
+ class_name="me-1",
+ color="info",
+ style={"padding": "0rem 1rem"}
+ )
+ ],
+ className=\
+ "d-grid gap-0 d-md-flex justify-content-md-end"
+ ),
+ class_name="g-0 p-0"
+ )
+ ],
+ class_name="g-0 p-0",
+ title=(
+ f"Metric{_plural(graph_set[1])}: ",
+ ", ".join(graph_set[1])
)
)
)
return dbc.Col(
- children=[
- dbc.Row(
- dbc.Accordion(
- children=acc_items,
- class_name="g-0 p-1",
- start_collapsed=False,
- always_open=True,
- active_item=[f"item-{i}" for i in range(len(acc_items))]
- ),
- class_name="g-0 p-0",
- )
- ]
+ dbc.Accordion(
+ panels,
+ class_name="g-0 p-1",
+ start_collapsed=True,
+ always_open=True
+ )
)
@staticmethod
class_name="g-0 p-1",
children=[
dbc.Input(
- id="telemetry-search-in",
+ id={"type": "telemetry-search-in", "index": 0},
placeholder="Start typing a metric name...",
type="text"
)
children=[
dbc.ListGroup(
class_name="overflow-auto p-0",
- id="telemetry-search-out",
+ id={"type": "telemetry-search-out", "index": 0},
children=[],
style={"max-height": "14em"},
flush=True
"""
return [
dbc.Row(
- id="telemetry-dd",
- class_name="g-0 p-1",
- children=["Add content here."]
+ "Add content here.",
+ id={"type": "tm-container", "index": 0},
+ class_name="g-0 p-1"
),
dbc.Row(
- class_name="g-0 p-1",
- children=[
- dbc.Textarea(
- id="telemetry-list-metrics",
- rows=20,
- size="sm",
- wrap="off",
- readonly=True
+ [
+ dbc.Col(
+ dbc.Checkbox(
+ id={"type": "cb-all-in-one", "index": 0},
+ label="All Metrics in one Graph"
+ ),
+ width=6
+ ),
+ dbc.Col(
+ dbc.Checkbox(
+ id={"type": "cb-ignore-host", "index": 0},
+ label="Ignore Host"
+ ),
+ width=6
)
- ]
+ ],
+ class_name="g-0 p-2"
+ ),
+ dbc.Row(
+ dbc.Textarea(
+ id={"type": "tm-list-metrics", "index": 0},
+ rows=20,
+ size="sm",
+ wrap="off",
+ readonly=True
+ ),
+ class_name="g-0 p-1"
)
]
"""
@app.callback(
- [
- Output("store-control-panel", "data"),
- Output("store-selected-tests", "data"),
- Output("plotting-area-trending", "children"),
- Output("plotting-area-buttons", "children"),
- Output("row-card-sel-tests", "style"),
- Output("row-btns-sel-tests", "style"),
- Output("lg-selected", "children"),
- Output({"type": "ctrl-dd", "index": "dut"}, "value"),
- Output({"type": "ctrl-dd", "index": "phy"}, "options"),
- Output({"type": "ctrl-dd", "index": "phy"}, "disabled"),
- Output({"type": "ctrl-dd", "index": "phy"}, "value"),
- Output({"type": "ctrl-dd", "index": "area"}, "options"),
- Output({"type": "ctrl-dd", "index": "area"}, "disabled"),
- Output({"type": "ctrl-dd", "index": "area"}, "value"),
- Output({"type": "ctrl-dd", "index": "test"}, "options"),
- Output({"type": "ctrl-dd", "index": "test"}, "disabled"),
- Output({"type": "ctrl-dd", "index": "test"}, "value"),
- Output({"type": "ctrl-cl", "index": "core"}, "options"),
- Output({"type": "ctrl-cl", "index": "core"}, "value"),
- Output({"type": "ctrl-cl", "index": "core-all"}, "value"),
- Output({"type": "ctrl-cl", "index": "core-all"}, "options"),
- Output({"type": "ctrl-cl", "index": "frmsize"}, "options"),
- Output({"type": "ctrl-cl", "index": "frmsize"}, "value"),
- Output({"type": "ctrl-cl", "index": "frmsize-all"}, "value"),
- Output({"type": "ctrl-cl", "index": "frmsize-all"}, "options"),
- Output({"type": "ctrl-cl", "index": "tsttype"}, "options"),
- Output({"type": "ctrl-cl", "index": "tsttype"}, "value"),
- Output({"type": "ctrl-cl", "index": "tsttype-all"}, "value"),
- Output({"type": "ctrl-cl", "index": "tsttype-all"}, "options"),
- Output({"type": "ctrl-btn", "index": "add-test"}, "disabled"),
- Output("normalize", "value")
- ],
- [
- State("store-control-panel", "data"),
- State("store-selected-tests", "data"),
- State({"type": "sel-cl", "index": ALL}, "value")
- ],
- [
- Input("url", "href"),
- Input("normalize", "value"),
- Input({"type": "ctrl-dd", "index": ALL}, "value"),
- Input({"type": "ctrl-cl", "index": ALL}, "value"),
- Input({"type": "ctrl-btn", "index": ALL}, "n_clicks")
- ],
+ Output("store", "data"),
+ Output("plotting-area-trending", "children"),
+ Output("plotting-area-telemetry", "children"),
+ Output("col-plotting-area", "style"),
+ Output("row-card-sel-tests", "style"),
+ Output("row-btns-sel-tests", "style"),
+ Output("row-btns-add-tm", "style"),
+ Output("lg-selected", "children"),
+ Output({"type": "telemetry-search-out", "index": ALL}, "children"),
+ Output({"type": "plot-mod-telemetry", "index": ALL}, "is_open"),
+ Output({"type": "telemetry-btn", "index": ALL}, "disabled"),
+ Output({"type": "tm-container", "index": ALL}, "children"),
+ Output({"type": "tm-list-metrics", "index": ALL}, "value"),
+ Output({"type": "ctrl-dd", "index": "dut"}, "value"),
+ Output({"type": "ctrl-dd", "index": "phy"}, "options"),
+ Output({"type": "ctrl-dd", "index": "phy"}, "disabled"),
+ Output({"type": "ctrl-dd", "index": "phy"}, "value"),
+ Output({"type": "ctrl-dd", "index": "area"}, "options"),
+ Output({"type": "ctrl-dd", "index": "area"}, "disabled"),
+ Output({"type": "ctrl-dd", "index": "area"}, "value"),
+ Output({"type": "ctrl-dd", "index": "test"}, "options"),
+ Output({"type": "ctrl-dd", "index": "test"}, "disabled"),
+ Output({"type": "ctrl-dd", "index": "test"}, "value"),
+ Output({"type": "ctrl-cl", "index": "core"}, "options"),
+ Output({"type": "ctrl-cl", "index": "core"}, "value"),
+ Output({"type": "ctrl-cl", "index": "core-all"}, "value"),
+ Output({"type": "ctrl-cl", "index": "core-all"}, "options"),
+ Output({"type": "ctrl-cl", "index": "frmsize"}, "options"),
+ Output({"type": "ctrl-cl", "index": "frmsize"}, "value"),
+ Output({"type": "ctrl-cl", "index": "frmsize-all"}, "value"),
+ Output({"type": "ctrl-cl", "index": "frmsize-all"}, "options"),
+ Output({"type": "ctrl-cl", "index": "tsttype"}, "options"),
+ Output({"type": "ctrl-cl", "index": "tsttype"}, "value"),
+ Output({"type": "ctrl-cl", "index": "tsttype-all"}, "value"),
+ Output({"type": "ctrl-cl", "index": "tsttype-all"}, "options"),
+ Output({"type": "ctrl-btn", "index": "add-test"}, "disabled"),
+ Output("normalize", "value"),
+
+ State("store", "data"),
+ State({"type": "sel-cl", "index": ALL}, "value"),
+ State({"type": "cb-all-in-one", "index": ALL}, "value"),
+ State({"type": "cb-ignore-host", "index": ALL}, "value"),
+ State({"type": "telemetry-search-out", "index": ALL}, "children"),
+ State({"type": "plot-mod-telemetry", "index": ALL}, "is_open"),
+ State({"type": "telemetry-btn", "index": ALL}, "disabled"),
+ State({"type": "tm-container", "index": ALL}, "children"),
+ State({"type": "tm-list-metrics", "index": ALL}, "value"),
+ State({"type": "tele-cl", "index": ALL}, "value"),
+
+ Input("url", "href"),
+ Input({"type": "tm-dd", "index": ALL}, "value"),
+
+ Input("normalize", "value"),
+ Input({"type": "telemetry-search-in", "index": ALL}, "value"),
+ Input({"type": "telemetry-btn", "index": ALL}, "n_clicks"),
+ Input({"type": "tm-btn-remove", "index": ALL}, "n_clicks"),
+ Input({"type": "ctrl-dd", "index": ALL}, "value"),
+ Input({"type": "ctrl-cl", "index": ALL}, "value"),
+ Input({"type": "ctrl-btn", "index": ALL}, "n_clicks"),
+
prevent_initial_call=True
)
def _update_application(
- control_panel: dict,
- store_sel: list,
+ store: dict,
lst_sel: list,
+ all_in_one: list,
+ ignore_host: list,
+ search_out: list,
+ is_open: list,
+ tm_btns_disabled: list,
+ tm_dd: list,
+ list_metrics: list,
+ cl_metrics: list,
href: str,
- normalize: list,
+ tm_dd_in: list,
*_
) -> tuple:
"""Update the application when the event is detected.
"""
- ctrl_panel = ControlPanel(CP_PARAMS, control_panel)
- on_draw = False
+ if store is None:
+ store = {
+ "control-panel": dict(),
+ "selected-tests": list(),
+ "trending-graphs": None,
+ "telemetry-data": dict(),
+ "selected-metrics": dict(),
+ "telemetry-panels": list(),
+ "telemetry-all-in-one": list(),
+ "telemetry-ignore-host": list(),
+ "telemetry-graphs": list(),
+ "url": str()
+ }
+
+ ctrl_panel = ControlPanel(
+ CP_PARAMS,
+ store.get("control-panel", dict())
+ )
+ store_sel = store["selected-tests"]
+ tm_data = store["telemetry-data"]
+ tm_user = store["selected-metrics"]
+ tm_panels = store["telemetry-panels"]
+ tm_all_in_one = store["telemetry-all-in-one"]
+ tm_ignore_host = store["telemetry-ignore-host"]
+
+ plotting_area_telemetry = no_update
+ on_draw = [False, False] # 0 --> trending, 1 --> telemetry
# Parse the url:
parsed_url = url_decode(href)
else:
url_params = None
- trigger = Trigger(callback_context.triggered)
+ if tm_user is None:
+ # Telemetry user data
+ # The data provided by user or result of user action
+ tm_user = {
+ # List of unique metrics:
+ "unique_metrics": list(),
+ # List of metrics selected by user:
+ "selected_metrics": list(),
+ # Labels from metrics selected by user (key: label name,
+ # value: list of all possible values):
+ "unique_labels": dict(),
+ # Labels selected by the user (subset of 'unique_labels'):
+ "selected_labels": dict(),
+ # All unique metrics with labels (output from the step 1)
+ # converted from pandas dataframe to dictionary.
+ "unique_metrics_with_labels": dict(),
+ # Metrics with labels selected by the user using dropdowns.
+ "selected_metrics_with_labels": dict()
+ }
+ tm = TelemetryData(store_sel) if store_sel else TelemetryData()
+ trigger = Trigger(callback_context.triggered)
if trigger.type == "url" and url_params:
+ telemetry = None
try:
store_sel = literal_eval(url_params["store_sel"][0])
normalize = literal_eval(url_params["norm"][0])
- except (KeyError, IndexError):
+ telemetry = literal_eval(url_params["telemetry"][0])
+ url_p = url_params.get("all-in-one", ["[[None]]"])
+ tm_all_in_one = literal_eval(url_p[0])
+ url_p = url_params.get("ignore-host", ["[[None]]"])
+ tm_ignore_host = literal_eval(url_p[0])
+ if not isinstance(telemetry, list):
+ telemetry = [telemetry, ]
+ except (KeyError, IndexError, AttributeError, ValueError):
pass
if store_sel:
last_test = store_sel[-1]
"cl-normalize-val": normalize,
"btn-add-dis": False
})
- on_draw = True
+ store["trending-graphs"] = None
+ store["telemetry-graphs"] = list()
+ on_draw[0] = True
+ if telemetry:
+ tm = TelemetryData(store_sel)
+ tm.from_dataframe(self._data)
+ tm_data = tm.to_json()
+ tm.from_json(tm_data)
+ tm_panels = telemetry
+ on_draw[1] = True
elif trigger.type == "normalize":
- ctrl_panel.set({"cl-normalize-val": normalize})
- on_draw = True
+ ctrl_panel.set({"cl-normalize-val": trigger.value})
+ store["trending-graphs"] = None
+ on_draw[0] = True
elif trigger.type == "ctrl-dd":
if trigger.idx == "dut":
try:
f"cl-{param}-val": val_sel,
f"cl-{param}-all-val": val_all,
})
- if all((ctrl_panel.get("cl-core-val"),
+ if all((ctrl_panel.get("cl-core-val"),
ctrl_panel.get("cl-frmsize-val"),
ctrl_panel.get("cl-tsttype-val"), )):
ctrl_panel.set({"btn-add-dis": False})
else:
ctrl_panel.set({"btn-add-dis": True})
elif trigger.type == "ctrl-btn":
- on_draw = True
+ tm_panels = list()
+ tm_all_in_one = list()
+ tm_ignore_host = list()
+ store["trending-graphs"] = None
+ store["telemetry-graphs"] = list()
+ # on_draw[0] = True
+ on_draw = [True, True]
if trigger.idx == "add-test":
dut = ctrl_panel.get("dd-dut-val")
phy = ctrl_panel.get("dd-phy-val")
store_sel = new_store_sel
elif trigger.idx == "rm-test-all":
store_sel = list()
-
- if on_draw:
- if store_sel:
- lg_selected = get_list_group_items(store_sel, "sel-cl")
- plotting_area_trending = self._get_plotting_area_trending(
- store_sel,
- bool(normalize),
- gen_new_url(
- parsed_url,
- {"store_sel": store_sel, "norm": normalize}
- )
- )
- plotting_area_buttons = self._get_plotting_area_buttons()
- row_card_sel_tests = C.STYLE_ENABLED
- row_btns_sel_tests = C.STYLE_ENABLED
- else:
- plotting_area_trending = C.PLACEHOLDER
- plotting_area_buttons = C.PLACEHOLDER
- row_card_sel_tests = C.STYLE_DISABLED
- row_btns_sel_tests = C.STYLE_DISABLED
- lg_selected = no_update
- store_sel = list()
- else:
- plotting_area_trending = no_update
- plotting_area_buttons = no_update
- row_card_sel_tests = no_update
- row_btns_sel_tests = no_update
- lg_selected = no_update
-
- ret_val = [
- ctrl_panel.panel,
- store_sel,
- plotting_area_trending,
- plotting_area_buttons,
- row_card_sel_tests,
- row_btns_sel_tests,
- lg_selected
- ]
- ret_val.extend(ctrl_panel.values)
- return ret_val
-
- @app.callback(
- Output("plot-mod-url", "is_open"),
- Input("plot-btn-url", "n_clicks"),
- State("plot-mod-url", "is_open")
- )
- def toggle_plot_mod_url(n, is_open):
- """Toggle the modal window with url.
- """
- if n:
- return not is_open
- return is_open
-
- @app.callback(
- Output("store-telemetry-data", "data"),
- Output("store-telemetry-user", "data"),
- Output("telemetry-search-in", "value"),
- Output("telemetry-search-out", "children"),
- Output("telemetry-list-metrics", "value"),
- Output("telemetry-dd", "children"),
- Output("plotting-area-telemetry", "children"),
- Output("plot-mod-telemetry-1", "is_open"),
- Output("plot-mod-telemetry-2", "is_open"),
- Output({"type": "telemetry-btn", "index": "select"}, "disabled"),
- Output({"type": "telemetry-btn", "index": "add"}, "disabled"),
- State("store-telemetry-data", "data"),
- State("store-telemetry-user", "data"),
- State("store-selected-tests", "data"),
- Input({"type": "tele-cl", "index": ALL}, "value"),
- Input("telemetry-search-in", "value"),
- Input({"type": "telemetry-btn", "index": ALL}, "n_clicks"),
- Input({"type": "tm-dd", "index": ALL}, "value"),
- prevent_initial_call=True
- )
- def _update_plot_mod_telemetry(
- tm_data: dict,
- tm_user: dict,
- store_sel: list,
- cl_metrics: list,
- search_in: str,
- n_clicks: list,
- tm_dd_in: list
- ) -> tuple:
- """Toggle the modal window with telemetry.
- """
-
- if not any(n_clicks):
- raise PreventUpdate
-
- if tm_user is None:
- # Telemetry user data
- # The data provided by user or result of user action
- tm_user = {
- # List of unique metrics:
- "unique_metrics": list(),
- # List of metrics selected by user:
- "selected_metrics": list(),
- # Labels from metrics selected by user (key: label name,
- # value: list of all possible values):
- "unique_labels": dict(),
- # Labels selected by the user (subset of 'unique_labels'):
- "selected_labels": dict(),
- # All unique metrics with labels (output from the step 1)
- # converted from pandas dataframe to dictionary.
- "unique_metrics_with_labels": dict(),
- # Metrics with labels selected by the user using dropdowns.
- "selected_metrics_with_labels": dict()
- }
-
- tm = TelemetryData(tests=store_sel)
- tm_json = no_update
- search_out = no_update
- list_metrics = no_update
- tm_dd = no_update
- plotting_area_telemetry = no_update
- is_open = (False, False)
- is_btn_disabled = (True, True)
-
- trigger = Trigger(callback_context.triggered)
- if trigger.type == "telemetry-btn":
+ elif trigger.type == "telemetry-btn":
if trigger.idx in ("open", "back"):
tm.from_dataframe(self._data)
- tm_json = tm.to_json()
+ tm_data = tm.to_json()
tm_user["unique_metrics"] = tm.unique_metrics
tm_user["selected_metrics"] = list()
tm_user["unique_labels"] = dict()
tm_user["selected_labels"] = dict()
- search_in = str()
- search_out = get_list_group_items(
- tm_user["unique_metrics"],
- "tele-cl",
- False
+ search_out = (
+ get_list_group_items(tm_user["unique_metrics"],
+ "tele-cl", False),
)
is_open = (True, False)
+ tm_btns_disabled[1], tm_btns_disabled[5] = False, True
elif trigger.idx == "select":
- tm.from_json(tm_data)
if any(cl_metrics):
+ tm.from_json(tm_data)
if not tm_user["selected_metrics"]:
tm_user["selected_metrics"] = \
tm_user["unique_metrics"]
tm.get_selected_labels(metrics)
tm_user["unique_metrics_with_labels"] = \
tm.unique_metrics_with_labels
- list_metrics = tm.str_metrics
- tm_dd = _get_dd_container(tm_user["unique_labels"])
- if list_metrics:
- is_btn_disabled = (True, False)
+ list_metrics[0] = tm.str_metrics
+ tm_dd[0] = _get_dd_container(tm_user["unique_labels"])
+ if list_metrics[0]:
+ tm_btns_disabled[1] = True
+ tm_btns_disabled[4] = False
is_open = (False, True)
else:
- tm_user = None
- is_open = (False, False)
+ is_open = (True, False)
elif trigger.idx == "add":
tm.from_json(tm_data)
- plotting_area_telemetry = self._get_plotting_area_telemetry(
- graph_tm_trending(
- tm.select_tm_trending_data(
- tm_user["selected_metrics_with_labels"]
- ),
- self._graph_layout)
- )
- tm_user = None
+ tm_panels.append(tm_user["selected_metrics_with_labels"])
+ tm_all_in_one.append(all_in_one)
+ tm_ignore_host.append(ignore_host)
is_open = (False, False)
+ tm_btns_disabled[1], tm_btns_disabled[5] = True, True
+ on_draw = [True, True]
elif trigger.idx == "cancel":
+ is_open = (False, False)
+ tm_btns_disabled[1], tm_btns_disabled[5] = True, True
+ elif trigger.idx == "rm-all":
+ tm_panels = list()
+ tm_all_in_one = list()
+ tm_ignore_host = list()
tm_user = None
is_open = (False, False)
+ tm_btns_disabled[1], tm_btns_disabled[5] = True, True
+ plotting_area_telemetry = C.PLACEHOLDER
elif trigger.type == "telemetry-search-in":
tm.from_metrics(tm_user["unique_metrics"])
tm_user["selected_metrics"] = \
- tm.search_unique_metrics(search_in)
- search_out = get_list_group_items(
+ tm.search_unique_metrics(trigger.value)
+ search_out = (get_list_group_items(
tm_user["selected_metrics"],
type="tele-cl",
colorize=False
- )
- is_open = (True, False)
- elif trigger.type == "tele-cl":
- if any(cl_metrics):
- is_btn_disabled = (False, True)
+ ), )
is_open = (True, False)
elif trigger.type == "tm-dd":
tm.from_metrics_with_labels(
selected[previous_itm] = itm
show_new = True
previous_itm = itm
-
- tm_dd = _get_dd_container(
+ tm_dd[0] = _get_dd_container(
tm_user["unique_labels"],
selected,
show_new
sel_metrics = tm.filter_selected_metrics_by_labels(selected)
tm_user["selected_metrics_with_labels"] = sel_metrics.to_dict()
if not sel_metrics.empty:
- list_metrics = tm.metrics_to_str(sel_metrics)
+ list_metrics[0] = tm.metrics_to_str(sel_metrics)
+ tm_btns_disabled[5] = False
else:
- list_metrics = str()
- if list_metrics:
- is_btn_disabled = (True, False)
- is_open = (False, True)
+ list_metrics[0] = str()
+ elif trigger.type == "tm-btn-remove":
+ del tm_panels[trigger.idx]
+ del tm_all_in_one[trigger.idx]
+ del tm_ignore_host[trigger.idx]
+ del store["telemetry-graphs"][trigger.idx]
+ tm.from_json(tm_data)
+ on_draw = [True, True]
+
+ new_url_params = {
+ "store_sel": store_sel,
+ "norm": ctrl_panel.get("cl-normalize-val")
+ }
+ if tm_panels:
+ new_url_params["telemetry"] = tm_panels
+ new_url_params["all-in-one"] = tm_all_in_one
+ new_url_params["ignore-host"] = tm_ignore_host
+
+ if on_draw[0]: # Trending
+ if store_sel:
+ lg_selected = get_list_group_items(store_sel, "sel-cl")
+ if store["trending-graphs"]:
+ graphs = store["trending-graphs"]
+ else:
+ graphs = graph_trending(
+ self._data,
+ store_sel,
+ self._graph_layout,
+ bool(ctrl_panel.get("cl-normalize-val"))
+ )
+ if graphs and graphs[0]:
+ store["trending-graphs"] = graphs
+ plotting_area_trending = \
+ Layout._plotting_area_trending(graphs)
+
+ # Telemetry
+ start_idx = len(store["telemetry-graphs"])
+ end_idx = len(tm_panels)
+ if not end_idx:
+ plotting_area_telemetry = C.PLACEHOLDER
+ elif on_draw[1] and (end_idx >= start_idx):
+ for idx in range(start_idx, end_idx):
+ store["telemetry-graphs"].append(graph_tm_trending(
+ tm.select_tm_trending_data(
+ tm_panels[idx],
+ ignore_host=bool(tm_ignore_host[idx][0])
+ ),
+ self._graph_layout,
+ bool(tm_all_in_one[idx][0])
+ ))
+ plotting_area_telemetry = \
+ Layout._plotting_area_telemetry(
+ store["telemetry-graphs"]
+ )
+ col_plotting_area = C.STYLE_ENABLED
+ row_card_sel_tests = C.STYLE_ENABLED
+ row_btns_sel_tests = C.STYLE_ENABLED
+ row_btns_add_tm = C.STYLE_ENABLED
+ else:
+ plotting_area_trending = no_update
+ plotting_area_telemetry = C.PLACEHOLDER
+ col_plotting_area = C.STYLE_DISABLED
+ row_card_sel_tests = C.STYLE_DISABLED
+ row_btns_sel_tests = C.STYLE_DISABLED
+ row_btns_add_tm = C.STYLE_DISABLED
+ lg_selected = no_update
+ store_sel = list()
+ tm_panels = list()
+ tm_all_in_one = list()
+ tm_ignore_host = list()
+ tm_user = None
+ else:
+ plotting_area_trending = no_update
+ col_plotting_area = no_update
+ row_card_sel_tests = no_update
+ row_btns_sel_tests = no_update
+ row_btns_add_tm = no_update
+ lg_selected = no_update
- # Return values:
+ store["url"] = gen_new_url(parsed_url, new_url_params)
+ store["control-panel"] = ctrl_panel.panel
+ store["selected-tests"] = store_sel
+ store["telemetry-data"] = tm_data
+ store["selected-metrics"] = tm_user
+ store["telemetry-panels"] = tm_panels
+ store["telemetry-all-in-one"] = tm_all_in_one
+ store["telemetry-ignore-host"] = tm_ignore_host
ret_val = [
- tm_json,
- tm_user,
- search_in,
+ store,
+ plotting_area_trending,
+ plotting_area_telemetry,
+ col_plotting_area,
+ row_card_sel_tests,
+ row_btns_sel_tests,
+ row_btns_add_tm,
+ lg_selected,
search_out,
- list_metrics,
+ is_open,
+ tm_btns_disabled,
tm_dd,
- plotting_area_telemetry
+ list_metrics
]
- ret_val.extend(is_open)
- ret_val.extend(is_btn_disabled)
+ ret_val.extend(ctrl_panel.values)
return ret_val
+ @app.callback(
+ Output("plot-mod-url", "is_open"),
+ Output("mod-url", "children"),
+ State("store", "data"),
+ State("plot-mod-url", "is_open"),
+ Input("plot-btn-url", "n_clicks")
+ )
+ def toggle_plot_mod_url(store, is_open, n_clicks):
+ """Toggle the modal window with url.
+ """
+ if not store:
+ raise PreventUpdate
+
+ if n_clicks:
+ return not is_open, store.get("url", str())
+ return is_open, store["url"]
+
def _get_dd_container(
all_labels: dict,
selected_labels: dict=dict(),
@app.callback(
Output("download-trending-data", "data"),
- State("store-selected-tests", "data"),
+ State("store", "data"),
Input("plot-btn-download", "n_clicks"),
+ Input({"type": "tm-btn-download", "index": ALL}, "n_clicks"),
prevent_initial_call=True
)
- def _download_trending_data(store_sel: list, _) -> dict:
+ def _download_data(store: list, *_) -> dict:
"""Download the data
:param store_sel: List of tests selected by user stored in the
:rtype: dict
"""
- if not store_sel:
+ if not store:
raise PreventUpdate
-
+ if not store["selected-tests"]:
+ raise PreventUpdate
+
df = pd.DataFrame()
- for itm in store_sel:
- sel_data = select_trending_data(self._data, itm)
- if sel_data is None:
- continue
- df = pd.concat([df, sel_data], ignore_index=True, copy=False)
+
+ trigger = Trigger(callback_context.triggered)
+ if not trigger.value:
+ raise PreventUpdate
+
+ if trigger.type == "plot-btn-download":
+ data = list()
+ for itm in store["selected-tests"]:
+ sel_data = select_trending_data(self._data, itm)
+ if sel_data is None:
+ continue
+ data.append(sel_data)
+ df = pd.concat(data, ignore_index=True, copy=False)
+ file_name = C.TREND_DOWNLOAD_FILE_NAME
+ elif trigger.type == "tm-btn-download":
+ tm = TelemetryData(store["selected-tests"])
+ tm.from_json(store["telemetry-data"])
+ df = tm.select_tm_trending_data(
+ store["telemetry-panels"][trigger.idx]
+ )
+ file_name = C.TELEMETRY_DOWNLOAD_FILE_NAME
+ else:
+ raise PreventUpdate
- return dcc.send_data_frame(df.to_csv, C.TREND_DOWNLOAD_FILE_NAME)
+ return dcc.send_data_frame(df.to_csv, file_name)