Add incidents to the page

Raoul Snyman 2021-09-17 11:56:22 -07:00
parent 6b29e2a373
commit 7a826cc4bc
No known key found for this signature in database
GPG Key ID: F55BCED79626AE9C
8 changed files with 1461 additions and 15 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
__pycache__
*.py[co]
*.sqlite

View File

@ -10,7 +10,7 @@ from statusforce.models import Service, Incident
app = Flask(__name__)
app.secret_key = b'GSADFGST#$%^$%&^2345234534576476'
app.config['FLASK_ADMIN_SWATCH'] = 'materia'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///statusforce.sqlite'
# Set up database
db.init_app(app)
@ -29,7 +29,7 @@ def index():
Show the status page
"""
services = Service.query.all()
incidents = Incident.query.limit(10).all()
incidents = Incident.query.order_by(Incident.created.desc()).limit(10).all()
service_statuses = [service.status for service in services]
overall_status = 'operational' if all(status == 'operational' for status in service_statuses) else \
'offline' if all(status == 'offline' for status in service_statuses) else 'unclear'

View File

@ -12,5 +12,6 @@ DateTime = db.DateTime
Enum = db.Enum
Integer = db.Integer
String = db.String
Text = db.Text
relationship = db.relationship
backref = db.backref

View File

@ -2,20 +2,28 @@ from datetime import datetime
from sqlalchemy.sql.expression import func
from statusforce.db import Model, Column, ForeignKey, Boolean, DateTime, Enum, Integer, String, relationship, backref
from statusforce.db import Model, Column, ForeignKey, Boolean, DateTime, Enum, Integer, String, Text, \
relationship, backref
class Service(Model):
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=False)
status = Column(Enum('operational', 'unclear', 'offline'), default='operational')
incidents = relationship('Incident', backref=backref('services', lazy=True))
incidents = relationship('Incident', backref=backref('service', lazy=True))
def __str__(self):
return self.name
class Incident(Model):
id = Column(Integer, primary_key=True, autoincrement=True)
service_id = Column(Integer, ForeignKey('service.id'))
title = Column(String, nullable=False)
description = Column(Text)
is_resolved = Column(Boolean, default=False)
created = Column(DateTime, nullable=False, default=datetime.utcnow)
updated = Column(DateTime, onupdate=func.current_timestamp())
def __str__(self):
return '{} ({})'.format(self.title, self.service.name)

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>System Status</title>
<link href="{{url_for('static', filename='css/bootstrap.min.css')}}" rel="stylesheet">
<link href="{{url_for('static', filename='css/bootstrap-icons.css')}}" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
@ -21,7 +22,7 @@
</style>
</head>
<body class="bg-light">
<div class="container">
<div class="container px-5">
<main>
<div class="py-5 text-center">
<img class="d-block mx-auto mb-4" src="{{url_for('static', filename='img/ltf-logo.svg')}}" alt="" width="72" height="57">
@ -30,42 +31,87 @@
</div>
{% if overall_status == 'operational' %}
<div class="p-3 mb-5 bg-success text-white" style="border-radius: 3px;">
All systems are operational
<i class="bi-check-circle-fill" style="margin-right: 0.5rem;"></i> All systems are operational
</div>
{% elif overall_status == 'unclear' %}
<div class="p-3 mb-5 bg-warning text-white" style="border-radius: 3px;">
Some systems are experiencing problems
<div class="p-3 mb-5 bg-warning" style="border-radius: 3px;">
<i class="bi-question-circle-fill" style="margin-right: 0.5rem;"></i> Some systems are experiencing problems
</div>
{% elif overall_status == 'offline' %}
<div class="p-3 mb-5 bg-danger text-white" style="border-radius: 3px;">
<strong>There is a major disruption of services</strong>
<i class="bi-exclamation-circle-fill" style="margin-right: 0.5rem;"></i> <strong>There is a major disruption of services</strong>
</div>
{% endif %}
{% if services | length > 0 %}
<h2 class="mt-5 mb-3">Services</h2>
<ul class="list-group">
{% for service in services %}
{% if service.status == 'operational' %}
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
{% elif service.status == 'unclear' %}
<li class="list-group-item d-flex justify-content-between align-items-center p-3 bg-warning" style="--bg-opacity: 0.2">
<li class="list-group-item d-flex justify-content-between align-items-center p-3 bg-warning" style="--bs-bg-opacity: 0.2">
{% elif service.status == 'offline' %}
<li class="list-group-item d-flex justify-content-between align-items-center p-3 bg-danger text-white" style="--bg-opacity: 0.2">
<li class="list-group-item d-flex justify-content-between align-items-center p-3 bg-danger" style="--bs-bg-opacity: 0.2">
{% endif %}
{{service.name}}
{% if service.status == 'operational' %}
<span class="p-2 bg-success border border-light rounded-circle">
<span class="p-2 bg-success rounded-circle">
{% elif service.status == 'unclear' %}
<span class="p-2 bg-warning border border-light rounded-circle">
<span class="p-2 bg-warning rounded-circle">
{% elif service.status == 'offline' %}
<span class="p-2 bg-danger border border-light rounded-circle">
<span class="p-2 bg-danger rounded-circle">
{% endif %}
<span class="visually-hidden">{{service.status}}</span>
</span>
</li>
{% endfor %}
</ul>
{% endif %}
{% if incidents | length > 0 %}
<h2 class="mt-5 mb-3">Incidents</h2>
{% endif %}
{% for incident in incidents %}
<div class="row">
<div class="col-auto text-center flex-column d-none d-sm-flex">
<div class="row h-50">
{% if loop.first %}
<div class="col">&nbsp;</div>
<div class="col">&nbsp;</div>
{% else %}
<div class="col border-end border-2">&nbsp;</div>
<div class="col border-start border-2">&nbsp;</div>
{% endif %}
</div>
<!-- h5 class="m-2"><span class="rounded-circle bg-white border px-3 py-1"></span></h5 -->
{% if incident.is_resolved %}
<h5 class="m-2"><span class="bi-check-circle-fill text-success" style="font-size: 200%"></span></h5>
{% else %}
<h5 class="m-2"><span class="bi-exclamation-circle-fill text-danger" style="font-size: 200%"></span></h5>
{% endif %}
<div class="row h-50">
{% if loop.last %}
<div class="col">&nbsp;</div>
<div class="col">&nbsp;</div>
{% else %}
<div class="col border-end border-2">&nbsp;</div>
<div class="col border-start border-2">&nbsp;</div>
{% endif %}
</div>
</div>
<div class="col py-2">
<div class="card">
<div class="card-body">
<div class="float-end">{{incident.created.strftime('%a %D %B, %Y')}}</div>
<h4 class="card-title text-muted">{{incident.title}} - {{incident.service.name}}</h4>
<p class="card-text text-muted">{{incident.description}}</p>
</div>
</div>
</div>
</div>
{% endfor %}
</main>
<footer class="my-5 pt-5 text-muted text-center text-small">
<p class="mb-1">&copy; 2021 Liberty Tech Force</p>
<p class="mb-1">&copy; 2021 <a href="https://libertytechforce.com">Liberty Tech Force</a> | Powered by <a href="https://git.libertytechforce.com/libertytechforce/statusforce">StatusForce</a></p>
</footer>
</div>
<!-- script src="js/bootstrap.bundle.min.js"></script -->