diff --git a/docker/routlin-dash/app/config_utils.py b/docker/routlin-dash/app/config_utils.py
index cb64e17..2e83d3c 100644
--- a/docker/routlin-dash/app/config_utils.py
+++ b/docker/routlin-dash/app/config_utils.py
@@ -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 Actions page to apply your changes.')
return _timing_status_msg(entry_ts, action_label)
diff --git a/docker/routlin-dash/app/view_page.py b/docker/routlin-dash/app/view_page.py
index 28ba639..b0b6da4 100644
--- a/docker/routlin-dash/app/view_page.py
+++ b/docker/routlin-dash/app/view_page.py
@@ -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'
'
'
Health check - problems found:
'
@@ -1711,6 +1712,12 @@ def render_layout(view_id, content_html, tokens):
except Exception:
pass
+ pending_bar = ''
+ if has_pending_alert:
+ pending_bar = ('
'
+ 'You have actions pending. Please visit Actions page.'
+ '
\n')
+
return (f'\n\n\n'
f'
\n'
f'
\n'
@@ -1719,14 +1726,14 @@ def render_layout(view_id, content_html, tokens):
f'\n\n'
f'{titlebar_html}\n'
f'{navbar_html}\n'
- f'
\n{problem_bars}{other_bars}{content_html}\n\n'
+ f'
\n{pending_bar}{problem_bars}{other_bars}{content_html}\n\n'
f'{footer_html}\n'
f'\n'
f'\n'
f'\n')
-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'
')
-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'
')
@@ -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'