diff --git a/src/app.py b/src/app.py index a577425..ef36874 100644 --- a/src/app.py +++ b/src/app.py @@ -15,7 +15,11 @@ external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css', dbc.themes.BOOTSTRAP, dbc.icons.BOOTSTRAP] -app = Dash(__name__, external_stylesheets=external_stylesheets, suppress_callback_exceptions=True, use_pages=True) +app = Dash(__name__, external_stylesheets=external_stylesheets, + external_scripts=[ + {'src': 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.0/html2canvas.min.js'} + ], + suppress_callback_exceptions=True, use_pages=True) # server = app.server @@ -113,10 +117,10 @@ def ready(): color="#00245a", class_name="justify-content-between nav-conatiner", ), - dash.page_container + dash.page_container ] ) -]) +], id="component-to-save") @app.callback( @@ -162,5 +166,25 @@ def toggle_navbar_collapse(n, is_open): return is_open +app.clientside_callback( + """ + function(n_clicks){ + if(n_clicks > 0){ + html2canvas(document.getElementById("component-to-save"), {useCORS: true}).then(function (canvas) { + var anchorTag = document.createElement("a"); + document.body.appendChild(anchorTag); + anchorTag.download = "download.png"; + anchorTag.href = canvas.toDataURL(); + anchorTag.target = '_blank'; + anchorTag.click(); + }); + } + } + """, + Output('download-image', 'n_clicks'), + Input('download-image', 'n_clicks') +) + + if __name__ == '__main__': app.run_server(debug=False, port=8050, host='0.0.0.0') diff --git a/src/assets/style.css b/src/assets/style.css index 0f6b125..f6dee00 100644 --- a/src/assets/style.css +++ b/src/assets/style.css @@ -13,7 +13,7 @@ body{ margin-bottom: 1rem; } -.status-table .cell-markdown>p { +.table-container .cell-markdown>p { display: flex; height: 100%; justify-content: center; @@ -28,6 +28,10 @@ body{ padding: 0 40px; } +.navbar { + min-height: 5.5rem; +} + .major-alarms.nav-link { line-height: 2.8em; font-size: 2em; @@ -159,6 +163,10 @@ body{ margin: 2%; } +.cls-selected-site h1 { + font-size: 2.5rem !important; +} + .cls-site-map { height: 750px; padding: 20px; @@ -166,7 +174,7 @@ body{ border-radius: 1rem } -.status-table th { +.table-container th { border-left: 0px !important; border-right: 0px !important; border-top-color: white !important; @@ -175,14 +183,20 @@ body{ color: rgb(45, 44, 44); } -.status-table { +.table-container { border: 1px solid #dfdfdf; } -.status-table .previous-next-container { +.table-container .previous-next-container { padding-top: 1% !important; } +.dowload-page-button { + color: rgb(45, 44, 44); + background-color: #ebf1fd; + border-color: #cbd4e7; +} + @media (max-width: 1080px) { .sidebysite-cont { width: 100% !important; diff --git a/src/pages/explore_paths.py b/src/pages/explore_paths.py index a208ee0..1069ce3 100644 --- a/src/pages/explore_paths.py +++ b/src/pages/explore_paths.py @@ -221,7 +221,8 @@ def generate_tables(frame, pivotFrames, event, alarmsInst): page_size=20, style_cell={ 'padding': '2px', - 'whiteSpace': 'pre-line' + 'whiteSpace': 'pre-line', + "font-size": "1.4rem", }, style_header={ 'backgroundColor': 'white', @@ -229,7 +230,7 @@ def generate_tables(frame, pivotFrames, event, alarmsInst): }, style_data={ 'height': 'auto', - 'lineHeight': '15px', + 'lineHeight': '1.5rem', 'overflowX': 'auto' }, style_table={ diff --git a/src/pages/home.py b/src/pages/home.py index e49134a..766897f 100644 --- a/src/pages/home.py +++ b/src/pages/home.py @@ -155,7 +155,7 @@ def give_status(site): }, style_data_conditional=[], id='status-tbl') - ], className='status-table') + ], className='table-container') else: element = html.Div(html.H3('No alarms for this site in the past day'), style={'textAlign': 'center'}) @@ -192,7 +192,7 @@ def total_number_of_alarms(sitesDf): html_elements = [dbc.Col([ dbc.Row( dbc.Col( - html.H1('Status of all sites in the past 24 hours', className='status-number') + html.H1('Status of all sites in the past 24 hours') , align="center") , align="center", justify='center', className='h-100'), ], className='status-box boxwithshadow', md=3, xs=12)] @@ -215,7 +215,6 @@ def total_number_of_alarms(sitesDf): ) html_elements.append(dbc.Col([ - # dbc.Row(html.H3('Overall status', className='status-title b flex'), justify="start"), dbc.Row(children=total_status, justify="center", align="center", className='h-100')], className='status-box boxwithshadow col-md-auto', md=3, xs=12)) diff --git a/src/pages/loss_delay.py b/src/pages/loss_delay.py index b022ad2..2427afd 100644 --- a/src/pages/loss_delay.py +++ b/src/pages/loss_delay.py @@ -88,7 +88,7 @@ def layout(q=None, **other_unknown_query_strings): kibanaIframe.append(dbc.Row([ dbc.Row(html.H3(f"Issues from {alrmContent['site']}")), dbc.Row(html.Iframe(src=url, style={"height": "600px"})) - ], className="boxwithshadow pair-details g-0 mb-1")) + ], className="boxwithshadow pair-details g-0 mb-1 p-3")) if len(alrmContent["src_sites"]) > 0: original_names = metaDf[metaDf['netsite'].isin(alrmContent["src_sites"])]['netsite_original'].unique() @@ -99,7 +99,7 @@ def layout(q=None, **other_unknown_query_strings): kibanaIframe.append(dbc.Row([ dbc.Row(html.H3(f"Issues to {alrmContent['site']}")), dbc.Row(html.Iframe(src=url, style={"height": "600px"})) - ], className="boxwithshadow pair-details g-0 mb-1")) + ], className="boxwithshadow pair-details g-0 mb-1 p-3")) else: kibanaIframe = dbc.Row([html.Iframe(src=url, style={"height": "1000px"})], className="boxwithshadow pair-details g-0") @@ -129,7 +129,7 @@ def layout(q=None, **other_unknown_query_strings): ], className="boxwithshadow alarm-header pair-details g-0", justify="between", align="center") ], style={"padding": "0.5% 1.5%"}, className='g-0'), dbc.Row( - kibanaIframe, style={"padding": "0.5% 1.5%"}, className='g-0') + kibanaIframe, style={"padding": "0.5% 1.5%"}, className='g-0 p-3') ], className='mb-5') diff --git a/src/pages/paths_site.py b/src/pages/paths_site.py index d3727ed..71cf59e 100644 --- a/src/pages/paths_site.py +++ b/src/pages/paths_site.py @@ -204,7 +204,7 @@ def layout(q=None, **other_unknown_query_strings): ], className="pair-details"), ], - ), lg=10, md=12 + ), lg=10, md=12, className="p-3" ), ], justify="between", align="center", className="boxwithshadow alarm-header pair-details") ], style={"padding": "0.5% 1.5%"}, className='g-0 mb-1'), diff --git a/src/pages/site.py b/src/pages/site.py index 6431ac4..8bb9197 100644 --- a/src/pages/site.py +++ b/src/pages/site.py @@ -126,8 +126,8 @@ def generate_tables(site, dateFrom, dateTo, frames, pivotFrames, alarms4Site, al dbc.CardBody([ html.Div(category_list) ], className="text-dark p-1"), - ], className="mb-4 site-alarms-tables" - ), className="boxwithshadow mb-1 g-0 align-items-start")) + ], className="mb-4 site-alarms-tables boxwithshadow" + ), className="mb-1 g-0 align-items-start")) else: @@ -319,9 +319,14 @@ def layout(q=None, **other_unknown_query_strings): return html.Div( dbc.Row([ dbc.Row([ - dbc.Col(id='selected-site', className='cls-selected-site', children=html.H1(f'Site {q}'), align="start"), - dbc.Col(html.H2(f'Alarms reported in the past 24 hours (Current time: {dateTo} UTC)'), className='cls-selected-site') - ], align="start", className='boxwithshadow mb-1 g-0'), + dbc.Col( + children=html.H1(f'{q}'), + id='selected-site', className='cls-selected-site', align="center"), + dbc.Col([ + html.H2(f'Alarms reported in the past 24 hours', className='pb-1'), + dbc.Button('Download as image', id='download-image', className='btn btn-secondary load-pairs-button dowload-page-button'), + ], className='cls-selected-site w-100') + ], align="center", justify="center", className='boxwithshadow mb-1 g-0'), html.Div(id='datatables', children=generate_tables(q, dateFrom, dateTo, frames, pivotFrames, alarmCnt, alarmsInst), @@ -338,8 +343,8 @@ def layout(q=None, **other_unknown_query_strings): className="site-plots site-inner-cont p-05") ) ], className="text-dark p-1") - ]), - className="mb-4 site-alarms-tables boxwithshadow page-cont mb-1 g-0" + ], className="boxwithshadow"), + className="mb-4 site-alarms-tables page-cont mb-1 g-0" ), html.Br(),