Development

This commit is contained in:
Matthew Grotke 2026-05-26 00:07:35 -04:00
parent 1c1bddade3
commit 537de935e9
2 changed files with 19 additions and 10 deletions

View file

@ -270,7 +270,8 @@ def _timing_status_msg(entry_ts, action_label):
def _build_timing_msg(entry_ts, action_label='Configuration saved'):
if not _apply_changes_immediately():
return f'{action_label}. Visit Actions page to apply your changes.'
from markupsafe import Markup
return Markup(f'{action_label}. Visit <strong>Actions</strong> page to apply your changes.')
return _timing_status_msg(entry_ts, action_label)

View file

@ -1619,8 +1619,9 @@ def _load_datasource(spec):
def render_layout(view_id, content_html, tokens):
css = _load_css()
level = _client_level()
has_pending_alert = not _apply_changes_immediately() and bool(get_dashboard_pending())
titlebar_html = f'<div class="titlebar"><span class="titlebar-brand">{WEB_APP_DISPLAY_NAME}</span></div>'
navbar_html = _render_navbar(view_id, level, tokens)
navbar_html = _render_navbar(view_id, level, tokens, pending_alert=has_pending_alert)
footer_html = f'<footer class="footer">{WEB_APP_DISPLAY_NAME}</footer>'
page_hash = config_hash()
@ -1692,7 +1693,7 @@ def render_layout(view_id, content_html, tokens):
fix_suffix = (f'Fix will be applied {timing}.' if timing
else 'Fix pending. The processing service is not running.')
else:
fix_suffix = 'Fix pending. Visit Actions page ASAP to apply fix.'
fix_suffix = 'Fix pending. Visit <strong>Actions</strong> page ASAP to apply fix.'
for sev, items in grouped.items():
if not items:
continue
@ -1701,7 +1702,7 @@ def render_layout(view_id, content_html, tokens):
+ ''.join(f'<li>{d}</li>' for d in items)
+ '</ul>')
uuid_attr = f' data-health-uuid="{e(fix_uuid)}"' if _apply_changes_immediately() else ''
fix_html = (f'<div style="margin-top:0.5em"{uuid_attr}>{e(fix_suffix)}</div>'
fix_html = (f'<div style="margin-top:0.5em"{uuid_attr}>{fix_suffix}</div>'
if fix_suffix else '')
content = ('<div style="width:100%">'
'<div style="font-weight:600;margin-bottom:0.25em">Health check - problems found:</div>'
@ -1711,6 +1712,12 @@ def render_layout(view_id, content_html, tokens):
except Exception:
pass
pending_bar = ''
if has_pending_alert:
pending_bar = ('<div class="info-bar info-bar-warning">'
'You have actions pending. Please visit <strong>Actions</strong> page.'
'</div>\n')
return (f'<!DOCTYPE html>\n<html lang="en">\n<head>\n'
f' <meta charset="UTF-8"/>\n'
f' <meta name="viewport" content="width=device-width, initial-scale=1.0"/>\n'
@ -1719,14 +1726,14 @@ def render_layout(view_id, content_html, tokens):
f'</head>\n<body>\n'
f'{titlebar_html}\n'
f'{navbar_html}\n'
f'<main class="main-content">\n{problem_bars}{other_bars}{content_html}\n</main>\n'
f'<main class="main-content">\n{pending_bar}{problem_bars}{other_bars}{content_html}\n</main>\n'
f'{footer_html}\n'
f'<script>var CONFIG_HASH="{page_hash}";var LAN_IFACE="{lan_iface}";var VPN_VLAN_COUNT={vpn_count};var EXISTING_VLAN_IDS={existing_ids};var EXISTING_VLAN_NAMES={existing_names};var EXISTING_VLAN_INTERFACES={existing_interfaces};var APPLY_UUID={json.dumps(my_uuid)};</script>\n'
f'<script>{_inline_js()}</script>\n'
f'</body>\n</html>')
def _render_navbar(active_view, level, tokens):
def _render_navbar(active_view, level, tokens, pending_alert=False):
navbar_data = _load_json(f'{DATA_DIR}/navbar_content.json')
left, right = [], []
for item in navbar_data.get('items', []):
@ -1734,7 +1741,7 @@ def _render_navbar(active_view, level, tokens):
align = item.get('align', 'left')
if not _passes(req, level):
continue
frag = _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=req)
frag = _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=req, pending_alert=pending_alert)
(right if align == 'right' else left).append(frag)
return (f'<nav class="nav-bar">'
@ -1743,7 +1750,7 @@ def _render_navbar(active_view, level, tokens):
f'</nav>')
def _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=None):
def _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=None, pending_alert=False):
req = item.get('client_requirement', inherited_req)
t = item.get('type', '')
@ -1752,7 +1759,8 @@ def _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=
map_to = item.get('map_to', '')
action = item.get('action', '')
is_active = ' active' if map_to and map_to == active_view else ''
cls = f'dropdown-item{is_active}' if in_dropdown else f'nav-item{is_active}'
pending = ' nav-item-pending' if pending_alert and map_to == 'view_actions' else ''
cls = f'dropdown-item{is_active}' if in_dropdown else f'nav-item{is_active}{pending}'
if action:
return (f'<form method="post" action="/action/{e(action)}" class="form-inline">'
f'<button type="submit" class="{cls}">{label}</button></form>')
@ -1770,7 +1778,7 @@ def _render_nav_item(item, active_view, level, in_dropdown=False, inherited_req=
child_req = child.get('client_requirement', req)
if not _passes(child_req, level):
continue
children += _render_nav_item(child, active_view, level, in_dropdown=True, inherited_req=req)
children += _render_nav_item(child, active_view, level, in_dropdown=True, inherited_req=req, pending_alert=pending_alert)
if not children:
return ''
return (f'<div class="nav-menu">'