Development
This commit is contained in:
parent
6d9aac0460
commit
59ac3c5973
20 changed files with 1466 additions and 1 deletions
135
docker/routlin-dash/app/pages/actions/view.py
Normal file
135
docker/routlin-dash/app/pages/actions/view.py
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
import json
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from flask import session
|
||||
from config_utils import (
|
||||
get_dashboard_pending, load_all_groups, get_done_timestamps,
|
||||
_apply_changes_immediately, _find_cmd_in_queues, WEB_APP_DISPLAY_NAME,
|
||||
)
|
||||
from factory import LEVEL_RANK, e, client_level, build_snap_val, snap_expand_row
|
||||
from view_common import _load_icon
|
||||
|
||||
|
||||
def collect_tokens(cfg):
|
||||
tokens = {}
|
||||
tokens['GENERAL_APPLY_ON_SAVE'] = 'true' if session.get('apply_changes_immediately', False) else 'false'
|
||||
|
||||
all_groups = load_all_groups()
|
||||
group_uuid_set = {g['uuid'] for g, _ in all_groups}
|
||||
pending_items = get_dashboard_pending()
|
||||
|
||||
if pending_items:
|
||||
pgroups = defaultdict(list)
|
||||
for uuid, ts, cmd, user in pending_items:
|
||||
pgroups[cmd].append((uuid, user))
|
||||
rows = ''
|
||||
for cmd, entries in pgroups.items():
|
||||
users = ', '.join(sorted({u for _, u in entries if u and u != 'unknown'}))
|
||||
snap_uuids = [uuid for uuid, _ in entries if uuid in group_uuid_set]
|
||||
if snap_uuids:
|
||||
req_tags = ''.join(
|
||||
f'<span class="tag" data-tooltip="{uuid}" data-uuid="{uuid}">'
|
||||
f'<span class="tl-full">{uuid[:8]}</span>'
|
||||
f'<span class="tl-short">{uuid[:8]}</span>'
|
||||
f'<span class="tl-min">{uuid[:8]}</span>'
|
||||
'</span>'
|
||||
for uuid in snap_uuids
|
||||
)
|
||||
req_cell = f'<td class="table-cell"><div class="tag-list">{req_tags}</div></td>'
|
||||
else:
|
||||
req_cell = '<td class="table-cell">-</td>'
|
||||
rows += (
|
||||
'<tr>'
|
||||
f'<td class="table-cell">{e(cmd)}</td>'
|
||||
f'<td class="table-cell">{e(users)}</td>'
|
||||
f'{req_cell}'
|
||||
'</tr>'
|
||||
)
|
||||
pending_html = (
|
||||
'<table class="data-table"><thead><tr>'
|
||||
'<th class="table-header">Command</th>'
|
||||
'<th class="table-header">User</th>'
|
||||
'<th class="table-header">Required By</th>'
|
||||
'</tr></thead>'
|
||||
f'<tbody>{rows}</tbody></table>'
|
||||
)
|
||||
else:
|
||||
pending_html = '<p class="text-muted">No pending actions.</p>'
|
||||
|
||||
tokens['PENDING_ACTIONS_HTML'] = pending_html
|
||||
tokens['NO_PENDING'] = 'true' if not pending_items else ''
|
||||
tokens['NO_DISMISSIBLE_PENDING'] = 'true' if not any(c != 'fix problems' for _, _, c, _ in pending_items) else ''
|
||||
tokens['APPLY_WARNING'] = (
|
||||
f'<span style="color:var(--warning)"><p>{_load_icon("arrow-left")} <strong>Applying actions will briefly disrupt connections as network services are restarted.</strong></p></span>'
|
||||
if pending_items else ''
|
||||
)
|
||||
|
||||
done_ts_map = get_done_timestamps()
|
||||
if all_groups:
|
||||
no_revert = set()
|
||||
for g, _ in all_groups:
|
||||
if g['reverts_group']:
|
||||
no_revert.add(g['uuid'])
|
||||
no_revert.add(g['reverts_group'])
|
||||
hist_rows = ''
|
||||
hist_onclick = (
|
||||
'onclick="if(event.target.type!==\'checkbox\')'
|
||||
'this.nextElementSibling.hidden=!this.nextElementSibling.hidden"'
|
||||
)
|
||||
for g, changes in all_groups:
|
||||
uuid = g['uuid']
|
||||
applied_ts = done_ts_map.get(uuid)
|
||||
dt_str = datetime.fromtimestamp(applied_ts).strftime('%Y-%m-%d %H:%M') if applied_ts else '-'
|
||||
all_before_null = all(c['before'] is None for c in changes)
|
||||
all_after_null = all(c['after'] is None for c in changes)
|
||||
if g['reverts_group']:
|
||||
verb = 'Reverted'
|
||||
elif all_before_null:
|
||||
verb = 'Added'
|
||||
elif all_after_null:
|
||||
verb = 'Deleted'
|
||||
else:
|
||||
verb = 'Edited'
|
||||
item = g.get('item_value') or ''
|
||||
summary = f'{verb} {g["parent_path"]}: {item}' if item else f'{verb} {g["parent_path"]}'
|
||||
snap_tag = (
|
||||
f'<div class="tag-list"><span class="tag" data-tooltip="{e(uuid)}" data-uuid="{e(uuid)}">'
|
||||
f'<span class="tl-full">{e(uuid[:8])}</span>'
|
||||
f'<span class="tl-short">{e(uuid[:8])}</span>'
|
||||
f'<span class="tl-min">{e(uuid[:8])}</span>'
|
||||
'</span></div>'
|
||||
)
|
||||
snap_user = e(g.get('user', ''))
|
||||
cb_attrs = 'disabled title="Cannot revert"' if uuid in no_revert else ''
|
||||
hist_rows += (
|
||||
f'<tr class="row-expandable" data-uuid="{e(uuid)}" {hist_onclick}>'
|
||||
f'<td class="table-cell"><input type="checkbox" name="selected_uuids" value="{e(uuid)}" {cb_attrs}/></td>'
|
||||
f'<td class="table-cell">{e(dt_str)}</td>'
|
||||
f'<td class="table-cell">{e(summary)}</td>'
|
||||
f'<td class="table-cell">{build_snap_val(changes)}</td>'
|
||||
f'<td class="table-cell">{snap_tag}</td>'
|
||||
f'<td class="table-cell">{snap_user}</td>'
|
||||
'</tr>'
|
||||
f'{snap_expand_row(changes, 6)}'
|
||||
)
|
||||
select_all = (
|
||||
'<input type="checkbox" '
|
||||
'onchange="document.querySelectorAll(\'[name=selected_uuids]:not(:disabled)\').forEach(c=>c.checked=this.checked)"/>'
|
||||
)
|
||||
history_html = (
|
||||
'<table class="data-table"><thead><tr>'
|
||||
f'<th class="table-header">{select_all}</th>'
|
||||
'<th class="table-header">Applied</th>'
|
||||
'<th class="table-header">Change</th>'
|
||||
'<th class="table-header">Fields</th>'
|
||||
'<th class="table-header">Change ID</th>'
|
||||
'<th class="table-header">User</th>'
|
||||
'</tr></thead>'
|
||||
f'<tbody>{hist_rows}</tbody></table>'
|
||||
)
|
||||
else:
|
||||
history_html = '<p class="text-muted">No change history.</p>'
|
||||
|
||||
tokens['CHANGE_HISTORY_HTML'] = history_html
|
||||
tokens['NO_HISTORY'] = 'true' if not all_groups else ''
|
||||
return tokens
|
||||
Loading…
Add table
Add a link
Reference in a new issue