Update VPP_STABLE_VER files
[csit.git] / resources / tools / dash / app / pal / stats / layout.py
index 5c3758b..fa1da90 100644 (file)
@@ -25,30 +25,48 @@ from dash import callback_context, no_update
 from dash import Input, Output, State
 from dash.exceptions import PreventUpdate
 from yaml import load, FullLoader, YAMLError
 from dash import Input, Output, State
 from dash.exceptions import PreventUpdate
 from yaml import load, FullLoader, YAMLError
-from datetime import datetime, timedelta
+from datetime import datetime
 from copy import deepcopy
 
 from copy import deepcopy
 
+from ..utils.constants import Constants as C
+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 ..data.data import Data
-from ..data.url_processing import url_decode, url_encode
 from .graphs import graph_statistics, select_data
 
 
 class Layout:
 from .graphs import graph_statistics, select_data
 
 
 class Layout:
+    """The layout of the dash app and the callbacks.
     """
     """
-    """
-
-    DEFAULT_JOB = "csit-vpp-perf-mrr-daily-master-2n-icx"
-
-    URL_STYLE = {
-        "background-color": "#d2ebf5",
-        "border-color": "#bce1f1",
-        "color": "#135d7c"
-    }
 
     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, html_layout_file: str,
         graph_layout_file: str, data_spec_file: str, tooltip_file: str,
         time_period: int=None) -> None:
-        """
+        """Initialization:
+        - save the input parameters,
+        - read and pre-process the data,
+        - prepare data for the control panel,
+        - read HTML layout file,
+        - read tooltips from the tooltip file.
+
+        :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 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 html_layout_file: str
+        :type graph_layout_file: str
+        :type data_spec_file: str
+        :type tooltip_file: str
+        :type time_period: int
         """
 
         # Inputs
         """
 
         # Inputs
@@ -79,7 +97,7 @@ class Layout:
             self._time_period = data_time_period
 
         jobs = sorted(list(data_stats["job"].unique()))
             self._time_period = data_time_period
 
         jobs = sorted(list(data_stats["job"].unique()))
-        job_info = {
+        d_job_info = {
             "job": list(),
             "dut": list(),
             "ttype": list(),
             "job": list(),
             "dut": list(),
             "ttype": list(),
@@ -88,14 +106,14 @@ class Layout:
         }
         for job in jobs:
             lst_job = job.split("-")
         }
         for job in jobs:
             lst_job = job.split("-")
-            job_info["job"].append(job)
-            job_info["dut"].append(lst_job[1])
-            job_info["ttype"].append(lst_job[3])
-            job_info["cadence"].append(lst_job[4])
-            job_info["tbed"].append("-".join(lst_job[-2:]))
-        self.df_job_info = pd.DataFrame.from_dict(job_info)
+            d_job_info["job"].append(job)
+            d_job_info["dut"].append(lst_job[1])
+            d_job_info["ttype"].append(lst_job[3])
+            d_job_info["cadence"].append(lst_job[4])
+            d_job_info["tbed"].append("-".join(lst_job[-2:]))
+        self.job_info = pd.DataFrame.from_dict(d_job_info)
 
 
-        self._default = self._set_job_params(self.DEFAULT_JOB)
+        self._default = set_job_params(self.job_info, C.STATS_DEFAULT_JOB)
 
         tst_info = {
             "job": list(),
 
         tst_info = {
             "job": list(),
@@ -209,94 +227,24 @@ class Layout:
     def default(self) -> any:
         return self._default
 
     def default(self) -> any:
         return self._default
 
-    def _get_duts(self) -> list:
-        """
-        """
-        return sorted(list(self.df_job_info["dut"].unique()))
-
-    def _get_ttypes(self, dut: str) -> list:
-        """
-        """
-        return sorted(list(self.df_job_info.loc[(
-            self.df_job_info["dut"] == dut
-        )]["ttype"].unique()))
-
-    def _get_cadences(self, dut: str, ttype: str) -> list:
-        """
-        """
-        return sorted(list(self.df_job_info.loc[(
-            (self.df_job_info["dut"] == dut) &
-            (self.df_job_info["ttype"] == ttype)
-        )]["cadence"].unique()))
-
-    def _get_test_beds(self, dut: str, ttype: str, cadence: str) -> list:
-        """
-        """
-        return sorted(list(self.df_job_info.loc[(
-            (self.df_job_info["dut"] == dut) &
-            (self.df_job_info["ttype"] == ttype) &
-            (self.df_job_info["cadence"] == cadence)
-        )]["tbed"].unique()))
+    def add_content(self):
+        """Top level method which generated the web page.
 
 
-    def _get_job(self, dut, ttype, cadence, testbed):
-        """Get the name of a job defined by dut, ttype, cadence, testbed.
+        It generates:
+        - Store for user input data,
+        - Navigation bar,
+        - Main area with control panel and ploting area.
 
 
-        Input information comes from control panel.
-        """
-        return self.df_job_info.loc[(
-            (self.df_job_info["dut"] == dut) &
-            (self.df_job_info["ttype"] == ttype) &
-            (self.df_job_info["cadence"] == cadence) &
-            (self.df_job_info["tbed"] == testbed)
-        )]["job"].item()
-
-    def _set_job_params(self, job: str) -> dict:
-        """
-        """
-        lst_job = job.split("-")
-        return {
-            "job": job,
-            "dut": lst_job[1],
-            "ttype": lst_job[3],
-            "cadence": lst_job[4],
-            "tbed": "-".join(lst_job[-2:]),
-            "duts": self._generate_options(self._get_duts()),
-            "ttypes": self._generate_options(self._get_ttypes(lst_job[1])),
-            "cadences": self._generate_options(self._get_cadences(
-                lst_job[1], lst_job[3])),
-            "tbeds": self._generate_options(self._get_test_beds(
-                lst_job[1], lst_job[3], lst_job[4]))
-        }
+        If no HTML layout is provided, an error message is displayed instead.
 
 
-    def _show_tooltip(self, id: str, title: str,
-            clipboard_id: str=None) -> list:
-        """
+        :returns: The HTML div with the whole page.
+        :rtype: html.Div
         """
         """
-        return [
-            dcc.Clipboard(target_id=clipboard_id, title="Copy URL") \
-                if clipboard_id else str(),
-            f"{title} ",
-            dbc.Badge(
-                id=id,
-                children="?",
-                pill=True,
-                color="white",
-                text_color="info",
-                class_name="border ms-1",
-            ),
-            dbc.Tooltip(
-                children=self._tooltips.get(id, str()),
-                target=id,
-                placement="auto"
-            )
-        ]
 
 
-    def add_content(self):
-        """
-        """
         if self.html_layout:
             return html.Div(
                 id="div-main",
         if self.html_layout:
             return html.Div(
                 id="div-main",
+                className="small",
                 children=[
                     dcc.Store(id="control-panel"),
                     dcc.Location(id="url", refresh=False),
                 children=[
                     dcc.Store(id="control-panel"),
                     dcc.Location(id="url", refresh=False),
@@ -344,6 +292,9 @@ class Layout:
 
     def _add_navbar(self):
         """Add nav element with navigation panel. It is placed on the top.
 
     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",
         """
         return dbc.NavbarSimple(
             id="navbarsimple-main",
@@ -366,6 +317,9 @@ class Layout:
 
     def _add_ctrl_col(self) -> dbc.Col:
         """Add column with controls. It is placed on the left side.
 
     def _add_ctrl_col(self) -> dbc.Col:
         """Add column with controls. It is placed on the left side.
+
+        :returns: Column with the control panel.
+        :rtype: dbc.Col
         """
         return dbc.Col(
             id="col-controls",
         """
         return dbc.Col(
             id="col-controls",
@@ -376,6 +330,9 @@ class Layout:
 
     def _add_plotting_col(self) -> dbc.Col:
         """Add column with plots and tables. It is placed on the right side.
 
     def _add_plotting_col(self) -> dbc.Col:
         """Add column with plots and tables. It is placed on the right side.
+
+        :returns: Column with tables.
+        :rtype: dbc.Col
         """
         return dbc.Col(
             id="col-plotting-area",
         """
         return dbc.Col(
             id="col-plotting-area",
@@ -415,7 +372,7 @@ class Layout:
                                 dcc.Loading(children=[
                                     dbc.Button(
                                         id="btn-download-data",
                                 dcc.Loading(children=[
                                     dbc.Button(
                                         id="btn-download-data",
-                                        children=self._show_tooltip(
+                                        children=show_tooltip(self._tooltips,
                                             "help-download", "Download Data"),
                                         class_name="me-1",
                                         color="info"
                                             "help-download", "Download Data"),
                                         class_name="me-1",
                                         color="info"
@@ -431,15 +388,18 @@ class Layout:
                                     class_name="me-1",
                                     children=[
                                         dbc.InputGroupText(
                                     class_name="me-1",
                                     children=[
                                         dbc.InputGroupText(
-                                            style=self.URL_STYLE,
-                                            children=self._show_tooltip(
-                                                "help-url", "URL", "input-url")
+                                            style=C.URL_STYLE,
+                                            children=show_tooltip(
+                                                self._tooltips,
+                                                "help-url", "URL",
+                                                "input-url"
+                                            )
                                         ),
                                         dbc.Input(
                                             id="input-url",
                                             readonly=True,
                                             type="url",
                                         ),
                                         dbc.Input(
                                             id="input-url",
                                             readonly=True,
                                             type="url",
-                                            style=self.URL_STYLE,
+                                            style=C.URL_STYLE,
                                             value=""
                                         )
                                     ]
                                             value=""
                                         )
                                     ]
@@ -453,7 +413,10 @@ class Layout:
         )
 
     def _add_ctrl_panel(self) -> dbc.Row:
         )
 
     def _add_ctrl_panel(self) -> dbc.Row:
-        """
+        """Add control panel.
+
+        :returns: Control panel.
+        :rtype: dbc.Row
         """
         return dbc.Row(
             id="row-ctrl-panel",
         """
         return dbc.Row(
             id="row-ctrl-panel",
@@ -467,7 +430,7 @@ class Layout:
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
-                                    children=self._show_tooltip(
+                                    children=show_tooltip(self._tooltips,
                                         "help-dut", "Device under Test")
                                 ),
                                 dbc.Row(
                                         "help-dut", "Device under Test")
                                 ),
                                 dbc.Row(
@@ -485,7 +448,7 @@ class Layout:
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
-                                    children=self._show_tooltip(
+                                    children=show_tooltip(self._tooltips,
                                         "help-ttype", "Test Type"),
                                 ),
                                 dbc.RadioItems(
                                         "help-ttype", "Test Type"),
                                 ),
                                 dbc.RadioItems(
@@ -501,7 +464,7 @@ class Layout:
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
-                                    children=self._show_tooltip(
+                                    children=show_tooltip(self._tooltips,
                                         "help-cadence", "Cadence"),
                                 ),
                                 dbc.RadioItems(
                                         "help-cadence", "Cadence"),
                                 ),
                                 dbc.RadioItems(
@@ -517,7 +480,7 @@ class Layout:
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
                             children=[
                                 dbc.Label(
                                     class_name="p-0",
-                                    children=self._show_tooltip(
+                                    children=show_tooltip(self._tooltips,
                                         "help-tbed", "Test Bed"),
                                 ),
                                 dbc.Select(
                                         "help-tbed", "Test Bed"),
                                 ),
                                 dbc.Select(
@@ -537,30 +500,6 @@ class Layout:
                                     children=self.default["job"]
                                 )
                             ]
                                     children=self.default["job"]
                                 )
                             ]
-                        ),
-                        dbc.Row(
-                            class_name="g-0 p-2",
-                            children=[
-                                dbc.Label(
-                                    class_name="gy-1",
-                                    children=self._show_tooltip(
-                                        "help-time-period", "Time Period"),
-                                ),
-                                dcc.DatePickerRange(
-                                    id="dpr-period",
-                                    className="d-flex justify-content-center",
-                                    min_date_allowed=\
-                                        datetime.utcnow() - timedelta(
-                                            days=self.time_period),
-                                    max_date_allowed=datetime.utcnow(),
-                                    initial_visible_month=datetime.utcnow(),
-                                    start_date=\
-                                        datetime.utcnow() - timedelta(
-                                            days=self.time_period),
-                                    end_date=datetime.utcnow(),
-                                    display_format="D MMM YY"
-                                )
-                            ]
                         )
                     ]
                 ),
                         )
                     ]
                 ),
@@ -568,7 +507,20 @@ class Layout:
         )
 
     class ControlPanel:
         )
 
     class ControlPanel:
+        """A class representing the control panel.
+        """
+
         def __init__(self, panel: dict, default: dict) -> None:
         def __init__(self, panel: dict, default: dict) -> None:
+            """Initialisation of the control pannel by default values. If
+            particular values are provided (parameter "panel") they are set
+            afterwards.
+
+            :param panel: Custom values to be set to the control panel.
+            :param default: Default values to be set to the control panel.
+            :type panel: dict
+            :type defaults: dict
+            """
+
             self._defaults = {
                 "ri-ttypes-options": default["ttypes"],
                 "ri-cadences-options": default["cadences"],
             self._defaults = {
                 "ri-ttypes-options": default["ttypes"],
                 "ri-cadences-options": default["cadences"],
@@ -585,6 +537,13 @@ class Layout:
                     self._panel[key] = panel[key]
 
         def set(self, kwargs: dict) -> None:
                     self._panel[key] = panel[key]
 
         def set(self, kwargs: dict) -> None:
+            """Set the values of the Control panel.
+
+            :param kwargs: key - value pairs to be set.
+            :type kwargs: dict
+            :raises KeyError: If the key in kwargs is not present in the Control
+                panel.
+            """
             for key, val in kwargs.items():
                 if key in self._panel:
                     self._panel[key] = val
             for key, val in kwargs.items():
                 if key in self._panel:
                     self._panel[key] = val
@@ -600,20 +559,32 @@ class Layout:
             return self._panel
 
         def get(self, key: str) -> any:
             return self._panel
 
         def get(self, key: str) -> any:
+            """Returns the value of a key from the Control panel.
+
+            :param key: The key which value should be returned.
+            :type key: str
+            :returns: The value of the key.
+            :rtype: any
+            :raises KeyError: If the key in kwargs is not present in the Control
+                panel.
+            """
             return self._panel[key]
 
         def values(self) -> list:
             return self._panel[key]
 
         def values(self) -> list:
-            return list(self._panel.values())
+            """Returns the values from the Control panel as a list.
 
 
-    @staticmethod
-    def _generate_options(opts: list) -> list:
-        return [{"label": i, "value": i} for i in opts]
+            :returns: The values from the Control panel.
+            :rtype: list
+            """
+            return list(self._panel.values())
 
 
-    @staticmethod
-    def _get_date(s_date: str) -> datetime:
-        return datetime(int(s_date[0:4]), int(s_date[5:7]), int(s_date[8:10]))
 
     def callbacks(self, app):
 
     def callbacks(self, app):
+        """Callbacks for the whole application.
+
+        :param app: The application.
+        :type app: Flask
+        """
 
         @app.callback(
             Output("control-panel", "data"),  # Store
 
         @app.callback(
             Output("control-panel", "data"),  # Store
@@ -633,21 +604,31 @@ class Layout:
             Input("ri-ttypes", "value"),
             Input("ri-cadences", "value"),
             Input("dd-tbeds", "value"),
             Input("ri-ttypes", "value"),
             Input("ri-cadences", "value"),
             Input("dd-tbeds", "value"),
-            Input("dpr-period", "start_date"),
-            Input("dpr-period", "end_date"),
             Input("url", "href")
             Input("url", "href")
-            # prevent_initial_call=True
         )
         )
-        def _update_ctrl_panel(cp_data: dict, dut:str, ttype: str, cadence:str,
-                tbed: str, start: str, end: str, href: str) -> tuple:
-            """
+        def _update_ctrl_panel(cp_data: dict, dut: str, ttype: str, cadence:str,
+                tbed: str, href: str) -> tuple:
+            """Update the application when the event is detected.
+
+            :param cp_data: Current status of the control panel stored in
+                browser.
+            :param dut: Input - DUT name.
+            :param ttype: Input - Test type.
+            :param cadence: Input - The cadence of the job.
+            :param tbed: Input - The test bed.
+            :param href: Input - The URL provided by the browser.
+            :type cp_data: dict
+            :type dut: str
+            :type ttype: str
+            :type cadence: str
+            :type tbed: str
+            :type href: str
+            :returns: New values for web page elements.
+            :rtype: tuple
             """
 
             ctrl_panel = self.ControlPanel(cp_data, self.default)
 
             """
 
             ctrl_panel = self.ControlPanel(cp_data, self.default)
 
-            start = self._get_date(start)
-            end = self._get_date(end)
-
             # Parse the url:
             parsed_url = url_decode(href)
             if parsed_url:
             # Parse the url:
             parsed_url = url_decode(href)
             if parsed_url:
@@ -657,13 +638,13 @@ class Layout:
 
             trigger_id = callback_context.triggered[0]["prop_id"].split(".")[0]
             if trigger_id == "ri-duts":
 
             trigger_id = callback_context.triggered[0]["prop_id"].split(".")[0]
             if trigger_id == "ri-duts":
-                ttype_opts = self._generate_options(self._get_ttypes(dut))
+                ttype_opts = generate_options(get_ttypes(self.job_info, dut))
                 ttype_val = ttype_opts[0]["value"]
                 ttype_val = ttype_opts[0]["value"]
-                cad_opts = self._generate_options(
-                    self._get_cadences(dut, ttype_val))
+                cad_opts = generate_options(get_cadences(
+                    self.job_info, dut, ttype_val))
                 cad_val = cad_opts[0]["value"]
                 cad_val = cad_opts[0]["value"]
-                tbed_opts = self._generate_options(
-                    self._get_test_beds(dut, ttype_val, cad_val))
+                tbed_opts = generate_options(get_test_beds(
+                    self.job_info, dut, ttype_val, cad_val))
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
                     "ri-duts-value": dut,
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
                     "ri-duts-value": dut,
@@ -675,12 +656,12 @@ class Layout:
                     "dd-tbeds-value": tbed_val
                 })
             elif trigger_id == "ri-ttypes":
                     "dd-tbeds-value": tbed_val
                 })
             elif trigger_id == "ri-ttypes":
-                cad_opts = self._generate_options(
-                    self._get_cadences(ctrl_panel.get("ri-duts-value"), ttype))
+                cad_opts = generate_options(get_cadences(
+                    self.job_info, ctrl_panel.get("ri-duts-value"), ttype))
                 cad_val = cad_opts[0]["value"]
                 cad_val = cad_opts[0]["value"]
-                tbed_opts = self._generate_options(
-                    self._get_test_beds(ctrl_panel.get("ri-duts-value"),
-                    ttype, cad_val))
+                tbed_opts = generate_options(get_test_beds(
+                    self.job_info, ctrl_panel.get("ri-duts-value"), ttype,
+                    cad_val))
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
                     "ri-ttypes-value": ttype,
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
                     "ri-ttypes-value": ttype,
@@ -690,8 +671,8 @@ class Layout:
                     "dd-tbeds-value": tbed_val
                 })
             elif trigger_id == "ri-cadences":
                     "dd-tbeds-value": tbed_val
                 })
             elif trigger_id == "ri-cadences":
-                tbed_opts = self._generate_options(
-                    self._get_test_beds(ctrl_panel.get("ri-duts-value"),
+                tbed_opts = generate_options(get_test_beds(
+                    self.job_info, ctrl_panel.get("ri-duts-value"),
                     ctrl_panel.get("ri-ttypes-value"), cadence))
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
                     ctrl_panel.get("ri-ttypes-value"), cadence))
                 tbed_val = tbed_opts[0]["value"]
                 ctrl_panel.set({
@@ -703,29 +684,17 @@ class Layout:
                 ctrl_panel.set({
                     "dd-tbeds-value": tbed
                 })
                 ctrl_panel.set({
                     "dd-tbeds-value": tbed
                 })
-            elif trigger_id == "dpr-period":
-                pass
             elif trigger_id == "url":
             elif trigger_id == "url":
-                # TODO: Add verification
                 if url_params:
                     new_job = url_params.get("job", list())[0]
                 if url_params:
                     new_job = url_params.get("job", list())[0]
-                    new_start = url_params.get("start", list())[0]
-                    new_end = url_params.get("end", list())[0]
-                    if new_job and new_start and new_end:
-                        start = self._get_date(new_start)
-                        end = self._get_date(new_end)
-                        job_params = self._set_job_params(new_job)
+                    if new_job:
+                        job_params = set_job_params(self.job_info, new_job)
                         ctrl_panel = self.ControlPanel(None, job_params)
                 else:
                     ctrl_panel = self.ControlPanel(cp_data, self.default)
                         ctrl_panel = self.ControlPanel(None, job_params)
                 else:
                     ctrl_panel = self.ControlPanel(cp_data, self.default)
-                    job = self._get_job(
-                        ctrl_panel.get("ri-duts-value"),
-                        ctrl_panel.get("ri-ttypes-value"),
-                        ctrl_panel.get("ri-cadences-value"),
-                        ctrl_panel.get("dd-tbeds-value")
-                    )
 
 
-            job = self._get_job(
+            job = get_job(
+                self.job_info,
                 ctrl_panel.get("ri-duts-value"),
                 ctrl_panel.get("ri-ttypes-value"),
                 ctrl_panel.get("ri-cadences-value"),
                 ctrl_panel.get("ri-duts-value"),
                 ctrl_panel.get("ri-ttypes-value"),
                 ctrl_panel.get("ri-cadences-value"),
@@ -733,28 +702,14 @@ class Layout:
             )
 
             ctrl_panel.set({"al-job-children": job})
             )
 
             ctrl_panel.set({"al-job-children": job})
-            fig_passed, fig_duration = graph_statistics(self.data, job,
-                self.layout, start, end)
-
-            if parsed_url:
-                new_url = url_encode({
-                    "scheme": parsed_url["scheme"],
-                    "netloc": parsed_url["netloc"],
-                    "path": parsed_url["path"],
-                    "params": {
-                        "job": job,
-                        "start": start,
-                        "end": end
-                    }
-                })
-            else:
-                new_url = str()
+            fig_passed, fig_duration = \
+                graph_statistics(self.data, job, self.layout)
 
             ret_val = [
                 ctrl_panel.panel,
                 fig_passed,
                 fig_duration,
 
             ret_val = [
                 ctrl_panel.panel,
                 fig_passed,
                 fig_duration,
-                new_url
+                gen_new_url(parsed_url, {"job": job})
             ]
             ret_val.extend(ctrl_panel.values())
             return ret_val
             ]
             ret_val.extend(ctrl_panel.values())
             return ret_val
@@ -762,32 +717,39 @@ class Layout:
         @app.callback(
             Output("download-data", "data"),
             State("control-panel", "data"),  # Store
         @app.callback(
             Output("download-data", "data"),
             State("control-panel", "data"),  # Store
-            State("dpr-period", "start_date"),
-            State("dpr-period", "end_date"),
             Input("btn-download-data", "n_clicks"),
             prevent_initial_call=True
         )
             Input("btn-download-data", "n_clicks"),
             prevent_initial_call=True
         )
-        def _download_data(cp_data: dict, start: str, end: str, n_clicks: int):
-            """
+        def _download_data(cp_data: dict, n_clicks: int):
+            """Download the data
+
+            :param cp_data: Current status of the control panel stored in
+                browser.
+            :param n_clicks: Number of clicks on the button "Download".
+            :type cp_data: dict
+            :type n_clicks: int
+            :returns: dict of data frame content (base64 encoded) and meta data
+                used by the Download component.
+            :rtype: dict
             """
             if not (n_clicks):
                 raise PreventUpdate
 
             ctrl_panel = self.ControlPanel(cp_data, self.default)
 
             """
             if not (n_clicks):
                 raise PreventUpdate
 
             ctrl_panel = self.ControlPanel(cp_data, self.default)
 
-            job = self._get_job(
+            job = get_job(
+                self.job_info,
                 ctrl_panel.get("ri-duts-value"),
                 ctrl_panel.get("ri-ttypes-value"),
                 ctrl_panel.get("ri-cadences-value"),
                 ctrl_panel.get("dd-tbeds-value")
             )
 
                 ctrl_panel.get("ri-duts-value"),
                 ctrl_panel.get("ri-ttypes-value"),
                 ctrl_panel.get("ri-cadences-value"),
                 ctrl_panel.get("dd-tbeds-value")
             )
 
-            start = datetime(int(start[0:4]), int(start[5:7]), int(start[8:10]))
-            end = datetime(int(end[0:4]), int(end[5:7]), int(end[8:10]))
-            data = select_data(self.data, job, start, end)
+            data = select_data(self.data, job)
             data = data.drop(columns=["job", ])
 
             data = data.drop(columns=["job", ])
 
-            return dcc.send_data_frame(data.T.to_csv, f"{job}-stats.csv")
+            return dcc.send_data_frame(
+                data.T.to_csv, f"{job}-{C.STATS_DOWNLOAD_FILE_NAME}")
 
         @app.callback(
             Output("row-metadata", "children"),
 
         @app.callback(
             Output("row-metadata", "children"),
@@ -798,7 +760,19 @@ class Layout:
         )
         def _show_metadata_from_graphs(
                 passed_data: dict, duration_data: dict) -> tuple:
         )
         def _show_metadata_from_graphs(
                 passed_data: dict, duration_data: dict) -> tuple:
-            """
+            """Generates the data for the offcanvas displayed when a particular
+            point in a graph is clicked on.
+
+            :param passed_data: The data from the clicked point in the graph
+                displaying the pass/fail data.
+            :param duration_data: The data from the clicked point in the graph
+                displaying the duration data.
+            :type passed_data: dict
+            :type duration data: dict
+            :returns: The data to be displayed on the offcanvas (job statistics
+                and the list of failed tests) and the information to show the
+                offcanvas.
+            :rtype: tuple(list, bool)
             """
 
             if not (passed_data or duration_data):
             """
 
             if not (passed_data or duration_data):