Add WIP UI and manager for alerts.

This commit is contained in:
Matthew Stratford 2021-09-11 23:44:15 +01:00
parent 502c7e3bed
commit ac5409587d
5 changed files with 174 additions and 1 deletions

65
baps_types/alert.py Normal file
View file

@ -0,0 +1,65 @@
from typing import Any, Dict
from datetime import datetime
CRITICAL = "Critical"
WARNING = "Warning"
class Alert:
start_time: int = 0
last_time: int = 0
end_time: int = -1
id: str
title: str
description: str
module: str
severity: str
@property
def ui_class(self) -> str:
if self.severity == CRITICAL:
return "danger"
if self.severity == WARNING:
return "warning"
return "info"
# return self._weight
# weight.setter
# def weight(self, value: int):
# self._weight = value
@property
def __dict__(self):
attrs = ["start_time", "last_time", "end_time", "id", "title", "description", "module", "severity"]
out = {}
for attr in attrs:
out[attr] = self.__getattribute__(attr)
return out
def __init__(self, new_data: Dict[str,Any]):
required_vars = [
"start_time", # Just in case an alert wants to show starting earlier than it is reported.
"id",
"title",
"description",
"module",
"severity"
]
for key in required_vars:
if key not in new_data.keys():
raise KeyError("Key {} is missing from data to create Alert.".format(key))
#if type(new_data[key]) != type(getattr(self,key)):
# raise TypeError("Key {} has type {}, was expecting {}.".format(key, type(new_data[key]), type(getattr(self,key))))
# Account for if the creator didn't want to set a custom time.
if key == "start_time" and new_data[key] == -1:
new_data[key] = datetime.now()
setattr(self,key,new_data[key])
self.last_time = self.start_time

29
helpers/alert_manager.py Normal file
View file

@ -0,0 +1,29 @@
from typing import List
from baps_types.alert import CRITICAL, Alert
class AlertManager():
_alerts: List[Alert]
def __init__(self):
self._alerts = [Alert(
{
"start_time": -1,
"id": "test",
"title": "Test Alert",
"description": "This is a test alert.",
"module": "Test",
"severity": CRITICAL
}
)]
@property
def alerts_current(self):
return self._alerts
@property
def alert_count_current(self):
return len(self._alerts)
@property
def alert_count_previous(self):
return len(self._alerts)

41
ui-templates/alerts.html Normal file
View file

@ -0,0 +1,41 @@
{% extends 'base.html' %}
{% block head %}
<meta http-equiv="refresh" content="2;url=/alerts" />
{% endblock %}
{% block content_inner %}
{% if data %}
<h2>Current Alerts: {{ data.alert_count_current }}</h2>
<div class="accordion" id="accordionExample">
{% for alert in data.alerts_current %}
<div class="card alert-{{ alert.ui_class }}">
<div class="card-header" id="headingOne">
<h2 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
{{ alert.title }}
</button>
<span class="badge badge-{{ alert.ui_class}}">{{ alert.severity }}</span>
</h2>
<span class="badge">Since {{ alert.start_time }}</span>
<span class="badge">Last Seen {{ alert.last_time }}</span>
{% if alert.end_time > -1 %}
<span class="badge">Ended {{ alert.end_time }}</span>
{% endif %}
</div>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
<strong>Module: </strong>{{ alert.module }}<br>
{{ alert.description }}
</div>
</div>
</div>
{% endfor %}
</div>
<hr>
<h2>Previous Alerts: {{ data.alert_count_previous }}</h2>
<div class="row">
</div>
{% endif %}
{% endblock %}

View file

@ -1,4 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head %}
<meta http-equiv="refresh" content="2;url=/" />
{% endblock %}
{% block content %} {% block content %}
<div class="card-body p-0"> <div class="card-body p-0">
@ -16,6 +19,23 @@
<a href="/presenter/" class="btn btn-primary btn-user btn-block"> <a href="/presenter/" class="btn btn-primary btn-user btn-block">
Open BAPS Presenter Open BAPS Presenter
</a> </a>
<hr>
{% if data.alert_count > 0 %}
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">Something's up! <a href="/alerts" class="btn btn-sm btn-danger float-right"><span class="badge badge-light mr-1">{{data.alert_count}}</span>View Alerts</a></h4>
<p>BAPSicle is having some issues. Please review the alerts page.
{% else %}
<div class="alert alert-success" role="alert">
<h4 class="alert-heading">We're all good!</h4>
<p>BAPSicle seems to be running well. If this doesn't seem to be the case, try restarting or taking a closer look at the logs.</p>
{% endif %}
<hr>
<a href="/logs" class="btn btn-success">Logs</a>
<a href="/restart" class="btn btn-info">Restart</a>
<a href="/shutdown" class="btn btn-danger">Shutdown</a>
</div>
<hr> <hr>
<p>Version: {{data.server_version}} - Build: {{data.server_build}} - Branch: {{data.server_branch}}</p> <p>Version: {{data.server_version}} - Build: {{data.server_build}} - Branch: {{data.server_branch}}</p>
<p>Server Name: {{data.server_name}}</p> <p>Server Name: {{data.server_name}}</p>

View file

@ -27,6 +27,7 @@ from helpers.state_manager import StateManager
from helpers.the_terminator import Terminator from helpers.the_terminator import Terminator
from helpers.normalisation import get_normalised_filename_if_available from helpers.normalisation import get_normalised_filename_if_available
from helpers.myradio_api import MyRadioAPI from helpers.myradio_api import MyRadioAPI
from helpers.alert_manager import AlertManager
env = Environment( env = Environment(
loader=FileSystemLoader("%s/ui-templates/" % os.path.dirname(__file__)), loader=FileSystemLoader("%s/ui-templates/" % os.path.dirname(__file__)),
@ -97,6 +98,7 @@ def render_template(file, data, status=200):
logger: LoggingManager logger: LoggingManager
server_state: StateManager server_state: StateManager
api: MyRadioAPI api: MyRadioAPI
alerts: AlertManager
player_to_q: List[Queue] = [] player_to_q: List[Queue] = []
player_from_q: List[Queue] = [] player_from_q: List[Queue] = []
@ -116,6 +118,7 @@ def ui_index(request):
data = { data = {
"ui_page": "index", "ui_page": "index",
"ui_title": "", "ui_title": "",
"alert_count": alerts.alert_count_current,
"server_version": config["server_version"], "server_version": config["server_version"],
"server_build": config["server_build"], "server_build": config["server_build"],
"server_name": config["server_name"], "server_name": config["server_name"],
@ -135,6 +138,20 @@ def ui_status(request):
"ui_page": "status", "ui_title": "Status"} "ui_page": "status", "ui_title": "Status"}
return render_template("status.html", data=data) return render_template("status.html", data=data)
@app.route("/alerts")
def ui_alerts(request):
channel_states = []
for i in range(server_state.get()["num_channels"]):
channel_states.append(status(i))
data = {
"alerts_current": alerts.alerts_current,
"alerts_count_current": alerts.alert_count_current,
"ui_page": "alerts",
"ui_title": "Alerts"
}
return render_template("alerts.html", data=data)
@app.route("/config/player") @app.route("/config/player")
def ui_config_player(request): def ui_config_player(request):
@ -479,13 +496,14 @@ def restart(request):
# Don't use reloader, it causes Nested Processes! # Don't use reloader, it causes Nested Processes!
def WebServer(player_to: List[Queue], player_from: List[Queue], state: StateManager): def WebServer(player_to: List[Queue], player_from: List[Queue], state: StateManager):
global player_to_q, player_from_q, server_state, api, app global player_to_q, player_from_q, server_state, api, app, alerts
player_to_q = player_to player_to_q = player_to
player_from_q = player_from player_from_q = player_from
server_state = state server_state = state
logger = LoggingManager("WebServer") logger = LoggingManager("WebServer")
api = MyRadioAPI(logger, state) api = MyRadioAPI(logger, state)
alerts = AlertManager()
process_title = "Web Server" process_title = "Web Server"
setproctitle(process_title) setproctitle(process_title)