-# Copyright (c) 2022 Cisco and/or its affiliates.
+# Copyright (c) 2023 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:
from dash import Input, Output, State
from dash.exceptions import PreventUpdate
from yaml import load, FullLoader, YAMLError
-from datetime import datetime
from ..utils.constants import Constants as C
from ..utils.control_panel import ControlPanel
from ..utils.utils import show_tooltip, gen_new_url, get_ttypes, get_cadences, \
get_test_beds, get_job, generate_options, set_job_params
from ..utils.url_processing import url_decode
-from ..data.data import Data
from .graphs import graph_statistics, select_data
"""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: int=None) -> None:
+ def __init__(
+ self,
+ app: Flask,
+ data_stats: pd.DataFrame,
+ 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_stats: Pandas dataframe with staistical data.
+ :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_stats: pandas.DataFrame
+ :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._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_stats, data_mrr, data_ndrpdr = Data(
- data_spec_file=self._data_spec_file,
- debug=True
- ).read_stats(days=self._time_period)
-
- df_tst_info = pd.concat([data_mrr, data_ndrpdr], ignore_index=True)
# Pre-process the data:
data_stats = data_stats[~data_stats.job.str.contains("-verify-")]
data_stats = data_stats[~data_stats.job.str.contains("-iterative-")]
data_stats = data_stats[["job", "build", "start_time", "duration"]]
- data_time_period = \
- (datetime.utcnow() - data_stats["start_time"].min()).days
- if self._time_period > data_time_period:
- self._time_period = data_time_period
-
jobs = sorted(list(data_stats["job"].unique()))
d_job_info = {
"job": list(),
"lst_failed": list()
}
for job in jobs:
- df_job = df_tst_info.loc[(df_tst_info["job"] == job)]
+ df_job = data_trending.loc[(data_trending["job"] == job)]
builds = df_job["build"].unique()
for build in builds:
df_build = df_job.loc[(df_job["build"] == build)]
"ri-ttypes-value": self._default["ttype"],
"ri-cadences-value": self._default["cadence"],
"dd-tbeds-value": self._default["tbed"],
- "al-job-children": self._default["job"]
+ "al-job-children": html.A(
+ self._default["job"],
+ href=f"{C.URL_JENKINS}{self._default['job']}",
+ target="_blank"
+ )
}
# Callbacks:
self._add_navbar()
]
),
- dcc.Loading(
+ dbc.Spinner(
dbc.Offcanvas(
class_name="w-50",
id="offcanvas-metadata",
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_TRENDING,
+ width="100%",
+ height="100%"
+ )
)
]
)
return dbc.NavbarSimple(
id="navbarsimple-main",
children=[
- dbc.NavItem(
- dbc.NavLink(
- C.STATS_TITLE,
- disabled=True,
- external_link=True,
- href="#"
- )
- )
+ dbc.NavItem(dbc.NavLink(
+ C.TREND_TITLE,
+ external_link=True,
+ href="/trending"
+ )),
+ dbc.NavItem(dbc.NavLink(
+ C.NEWS_TITLE,
+ external_link=True,
+ href="/news"
+ )),
+ dbc.NavItem(dbc.NavLink(
+ C.STATS_TITLE,
+ active=True,
+ external_link=True,
+ href="/stats"
+ )),
+ dbc.NavItem(dbc.NavLink(
+ "Documentation",
+ id="btn-documentation",
+ ))
],
brand=C.BRAND,
brand_href="/",
return dbc.Col(
id="col-plotting-area",
children=[
- dcc.Loading(
+ dbc.Spinner(
children=[
dbc.Row(
id="plotting-area",
dbc.Row(
class_name="g-0 p-1",
children=[
- dbc.Label(
- children=show_tooltip(
- self._tooltips,
- "help-dut",
- "Device under Test"
- )
- ),
- dbc.RadioItems(
- id="ri-duts",
- inline=True,
- value=self._default["dut"],
- options=self._default["duts"],
- input_class_name="border-info bg-info"
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ children=show_tooltip(
+ self._tooltips,
+ "help-dut",
+ "DUT"
+ )
+ ),
+ dbc.RadioItems(
+ id="ri-duts",
+ inline=True,
+ value=self._default["dut"],
+ options=self._default["duts"],
+ class_name="form-control"
+ )
+ ],
+ size="sm"
)
]
),
dbc.Row(
class_name="g-0 p-1",
children=[
- dbc.Label(
- children=show_tooltip(
- self._tooltips,
- "help-ttype",
- "Test Type"
- )
- ),
- dbc.RadioItems(
- id="ri-ttypes",
- inline=True,
- value=self._default["ttype"],
- options=self._default["ttypes"],
- input_class_name="border-info bg-info"
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ children=show_tooltip(
+ self._tooltips,
+ "help-ttype",
+ "Test Type"
+ )
+ ),
+ dbc.RadioItems(
+ id="ri-ttypes",
+ inline=True,
+ value=self._default["ttype"],
+ options=self._default["ttypes"],
+ class_name="form-control"
+ )
+ ],
+ size="sm"
)
]
),
dbc.Row(
class_name="g-0 p-1",
children=[
- dbc.Label(
- children=show_tooltip(
- self._tooltips,
- "help-cadence",
- "Cadence"
- )
- ),
- dbc.RadioItems(
- id="ri-cadences",
- inline=True,
- value=self._default["cadence"],
- options=self._default["cadences"],
- input_class_name="border-info bg-info"
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ children=show_tooltip(
+ self._tooltips,
+ "help-cadence",
+ "Cadence"
+ )
+ ),
+ dbc.RadioItems(
+ id="ri-cadences",
+ inline=True,
+ value=self._default["cadence"],
+ options=self._default["cadences"],
+ class_name="form-control"
+ )
+ ],
+ size="sm"
)
]
),
dbc.Row(
class_name="g-0 p-1",
children=[
- dbc.Label(
- children=show_tooltip(
- self._tooltips,
- "help-tbed",
- "Test Bed"
- )
- ),
- dbc.Select(
- id="dd-tbeds",
- placeholder="Select a test bed...",
- value=self._default["tbed"],
- options=self._default["tbeds"]
+ dbc.InputGroup(
+ [
+ dbc.InputGroupText(
+ children=show_tooltip(
+ self._tooltips,
+ "help-tbed",
+ "Test Bed"
+ )
+ ),
+ dbc.Select(
+ id="dd-tbeds",
+ placeholder="Select a test bed...",
+ value=self._default["tbed"],
+ options=self._default["tbeds"]
+ )
+ ],
+ size="sm"
)
]
),
[
dbc.Button(
id="plot-btn-url",
- children="URL",
+ children="Show URL",
class_name="me-1",
color="info",
style={
"ri-ttypes-value": job_params["ttype"],
"ri-cadences-value": job_params["cadence"],
"dd-tbeds-value": job_params["tbed"],
- "al-job-children": job_params["job"]
+ "al-job-children": html.A(
+ self._default["job"],
+ href=(
+ f"{C.URL_JENKINS}"
+ f"{self._default['job']}"
+ ),
+ target="_blank"
+ )
},
None
)
ctrl_panel.get("dd-tbeds-value")
)
- ctrl_panel.set({"al-job-children": job})
+ ctrl_panel.set(
+ {
+ "al-job-children": html.A(
+ self._default["job"],
+ href=f"{C.URL_JENKINS}{self._default['job']}",
+ target="_blank"
+ )
+ }
+ )
plotting_area = self._get_plotting_area(
job,
gen_new_url(parsed_url, {"job": job})
fail_tests = None
# Create the content of the offcanvas:
+ list_group_items = list()
+ for itm in lst_graph_data:
+ lst_itm = itm.split(": ")
+ if lst_itm[0] == "csit-ref":
+ list_group_item = dbc.ListGroupItem([
+ dbc.Badge(lst_itm[0]),
+ html.A(
+ lst_itm[1],
+ href=f"{C.URL_JENKINS}{lst_itm[1]}",
+ target="_blank"
+ )
+ ])
+ else:
+ list_group_item = dbc.ListGroupItem([
+ dbc.Badge(lst_itm[0]),
+ lst_itm[1]
+ ])
+ list_group_items.append(list_group_item)
metadata = [
dbc.Card(
class_name="gy-2 p-0",
children=[
- dbc.CardHeader(children=[
+ dbc.CardHeader([
dcc.Clipboard(
target_id="metadata",
title="Copy",
title
]),
dbc.CardBody(
+ dbc.ListGroup(list_group_items, flush=True),
id="metadata",
- class_name="p-0",
- children=[dbc.ListGroup(
- children=[
- dbc.ListGroupItem(
- [
- dbc.Badge(
- x.split(":")[0]
- ),
- x.split(": ")[1]
- ]
- ) for x in lst_graph_data
- ],
- flush=True),
- ]
+ class_name="p-0"
)
]
)
open_canvas = True
return metadata, open_canvas
+
+ @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