1 # Copyright (c) 2022 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Plotly Dash HTML layout override.
21 from dash import Input, Output, callback
22 from dash.exceptions import PreventUpdate
23 from yaml import load, FullLoader, YAMLError
30 def __init__(self, app, html_layout_file, spec_file):
36 self._html_layout_file = html_layout_file
37 self._spec_file = spec_file
40 self._html_layout = ""
41 self._spec_test = None
44 with open(self._html_layout_file, "r") as layout_file:
45 self._html_layout = layout_file.read()
46 except IOError as err:
47 logging.error(f"Not possible to open the file {layout_file}\n{err}")
50 with open(self._spec_file, "r") as file_read:
51 self._spec_test = load(file_read, Loader=FullLoader)
52 except IOError as err:
53 logging.error(f"Not possible to open the file {spec_file}\n{err}")
54 except YAMLError as err:
56 f"An error occurred while parsing the specification file "
62 if self._app is not None and hasattr(self, 'callbacks'):
63 self.callbacks(self._app)
65 # User choice (one test):
66 self._test_selection = {
76 def html_layout(self):
77 return self._html_layout
81 return self._spec_test
83 def _reset_test_selection(self):
84 self._test_selection = {
93 def add_content(self):
96 if self._html_layout and self._spec_test:
100 self._add_ctrl_div(),
101 self._add_plotting_div()
107 children="An Error Occured."
110 def _add_ctrl_div(self):
111 """Add div with controls. It is placed on the left side.
117 id="div-controls-tabs",
119 self._add_ctrl_select(),
120 self._add_ctrl_shown()
125 "display": "inline-block",
131 def _add_plotting_div(self):
132 """Add div with plots and tables. It is placed on the right side.
135 id="div-plotting-area",
137 # Only a visible note.
142 "vertical-align": "middle",
143 "text-align": "center"
148 "vertical-align": "middle",
149 "display": "inline-block",
155 def _add_ctrl_shown(self):
160 children="List of selected tests"
163 def _add_ctrl_select(self):
167 id="div-ctrl-select",
171 children="Physical Test Bed Topology, NIC and Driver"
175 placeholder="Select a Physical Test Bed Topology...",
179 {"label": k, "value": k} for k in self._spec_test.keys()
188 placeholder="Select an Area...",
199 placeholder="Select a Test...",
205 # Change to radio buttons:
208 children="Number of Cores"
212 placeholder="Select a Number of Cores...",
219 children="Frame Size"
222 id="dd-ctrl-framesize",
223 placeholder="Select a Frame Size...",
233 id="dd-ctrl-testtype",
234 placeholder="Select a Test Type...",
252 def callbacks(self, app):
255 Output("dd-ctrl-area", "options"),
256 Output("dd-ctrl-area", "disabled"),
257 Input("dd-ctrl-phy", "value"),
259 def _update_dd_area(phy):
268 {"label": self._spec_test[phy][v]["label"], "value": v}
269 for v in [v for v in self._spec_test[phy].keys()]
274 return options, False
277 Output("dd-ctrl-test", "options"),
278 Output("dd-ctrl-test", "disabled"),
279 Input("dd-ctrl-phy", "value"),
280 Input("dd-ctrl-area", "value"),
282 def _update_dd_test(phy, area):
286 if not all((phy, area, )):
291 {"label": v, "value": v}
292 for v in self._spec_test[phy][area]["test"]
297 return options, False
300 Output("btn-ctrl-add", "disabled"),
301 Input("dd-ctrl-phy", "value"),
302 Input("dd-ctrl-area", "value"),
303 Input("dd-ctrl-test", "value"),
305 def _update_btn_add(phy, area, test):
309 if all((phy, area, test, )):
310 self._test_selection["phy"] = phy
311 self._test_selection["area"] = area
312 self._test_selection["test"] = test
318 Output("div-ctrl-info", "children"),
319 Output("dd-ctrl-phy", "value"),
320 Output("dd-ctrl-area", "value"),
321 Output("dd-ctrl-test", "value"),
322 Output("btn-ctrl-add", "n_clicks"),
323 Input("btn-ctrl-add", "n_clicks")
325 def _print_user_selection(n_clicks):
329 logging.info(f"\n\n{n_clicks}\n\n")
335 f"{self._test_selection['phy']} # "
336 f"{self._test_selection['area']} # "
337 f"{self._test_selection['test']} # "
341 self._reset_test_selection()