Commit ce64f837 authored by Vladislav Rykov's avatar Vladislav Rykov
Browse files

alerts, new alert views created, improved front-end alerts, other modifications

parent ae3700a3
...@@ -34,19 +34,6 @@ ...@@ -34,19 +34,6 @@
{% block content %} {% endblock %} {% block content %} {% endblock %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible show fade" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
<footer class="py-5"> <footer class="py-5">
<div class="container"> <div class="container">
<div class="row align-items-center justify-content-xl-between"> <div class="row align-items-center justify-content-xl-between">
......
...@@ -169,6 +169,21 @@ ...@@ -169,6 +169,21 @@
<!-- Header --> <!-- Header -->
<div class="header bg-gradient-primary pb-8 pt-5 pt-md-8"> <div class="header bg-gradient-primary pb-8 pt-5 pt-md-8">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="col-md-6" style="position: absolute; top:25%; right:30px;">
<div class="alert alert-{{ category }} alert-dismissible show fade" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ message }}
</div>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="container-fluid"> <div class="container-fluid">
<div class="header-body"> <div class="header-body">
<!-- Card stats --> <!-- Card stats -->
......
{% extends 'logged_layout.html' %}
{% block title %} HPC&amp;A IoT - Alerts {% endblock %}
{% block header %}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
{% endblock %}
{% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/applications">Applications</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/application/{{ app[1] }}">{{ app[0] }}</a>
{% endblock %}
{% block body %}
<!-- Page content -->
<div class="container-fluid mt--7">
<!-- Table -->
<div class="row">
<div class="col">
<div class="card shadow">
<div class="card-header bg-transparent">
<h3 class="mb-0">Alerts</h3>
</div>
<div class="card-body">
{% if alert_list %}
<table class="table">
<thead>
<th> Name </th>
<th> Condition </th>
<th> Email </th>
<th> </th>
</thead>
<tbody>
{% for a in alert_list %}
<tr>
<th> {{ a[3] }} </th>
<th> {{ a[4] }} </th>
<th> {{ a[6] }} </th>
<th> <a href="javascript:void(0)" onclick="return remove_alert('{{ a[0] }}', '{{ a[2] }}');"> <span class="fa fa-remove"</span> </a> </th>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<center><p> There are no alerts for the given application.</p> </center>
{% endif %}
<br>
<div class="col-lg-4">
<a href="/application/{{ app[1] }}/new-alert"><button class="btn btn-primary" type="submit">New Alert</button></a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
function remove_alert(id, devid) {
$.ajax({
url:"/application/{{ app[1] }}/remove-alert?id="+id+"&devid="+devid,
type:"get",
success: function() {
location.reload();
}
});
}
</script>
{% endblock %}
{% extends 'logged_layout.html' %}
{% block title %} HPC&amp;A IoT - New Alert {% endblock %}
{% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/applications">Applications</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/application/{{ app[1] }}">{{ app[0] }}</a>
{% endblock %}
{% block body %}
<!-- Page content -->
<div class="container-fluid mt--7">
<!-- Table -->
<div class="row">
<div class="col">
<div class="card shadow">
<div class="card-header bg-transparent">
<h3 class="mb-0">Applications</h3>
</div>
<div class="card-body">
<form action="/application/{{ app[1] }}/new-alert" method="post">
<div class="form-group">
<label>Name:</label><br>
<input type="text" maxlength="30" class="form-control" id="alertname" name="alertname" required><br>
</div>
<h3> Condition: </h3>
<h4> IF </h4>
<select class="form-control" id="devid" name="devid" onchange="return ondev();" required>
<option default value="-">Select Device</option>
{% for d in devs %}
<option value="{{ d[1] }}">{{ d[0] }}</option>
{% endfor %}
</select>
<br>
<select class="form-control" id="varname" name="varname" onchange="return validate_form();" required>
<option value="-">Select variable</option>
</select>
<br>
<select class='form-control notifelem' name='operation' id='operation' required>
<option default>></option>
<option>>=</option>
<option><</option>
<option><=</option>
<option>=</option>
</select>
<br>
<input type='text' class='form-control notifelem' name='avalue' id='avalue' placeholder='Value' title='use n (e.g. 5) for integer notation, n.n (e.g. 5.0) for float, and true or false for boolean' required>
<p> Use n (e.g. 5) for integer notation, n.n (e.g. 5.0) for float, and true or false for boolean </p>
<br>
<h4> THEN </h4>
<h5> Send email to: </h5>
<input class="form-control" type="email" id="alertemail" name="alertemail" placeholder="Type email..." required>
<br>
<div class="form-group">
<button type="submit" id="submit" class="btn btn-primary">Create Alert</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
$("#submit").prop("disabled", true);
function validate_form() {
var dev_sel = document.getElementById("devid");
var sel_op = dev_sel.options[dev_sel.selectedIndex].value;
var var_sel = document.getElementById("varname");
var sel_var = var_sel.options[var_sel.selectedIndex].value;
if (sel_op == "-" || sel_var == "-") {
$("#submit").prop("disabled", true);
console.log("not validated: "+sel_op+" "+sel_var);
} else {
$("#submit").prop("disabled", false);
console.log("validated: "+sel_op+" "+sel_var);
}
}
function ondev() {
var dev_sel = document.getElementById("devid");
var sel_op = dev_sel.options[dev_sel.selectedIndex].value;
if (sel_op != "-") {
fetch(window.origin+"/application/{{ app[1] }}/device/"+sel_op+"/variables").then(res => res.text()).then(data => $("#varname").html(data));
}
validate_form();
}
</script>
{% endblock %}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% block title %} HPC&amp;A IoT - New Application {% endblock %} {% block title %} HPC&amp;A IoT - New Application {% endblock %}
{% block location %} <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="./applications">Applications</a> {% endblock %} {% block location %} <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/applications">Applications</a> {% endblock %}
{% block body %} {% block body %}
<!-- Page content --> <!-- Page content -->
......
...@@ -267,6 +267,7 @@ def application_device_configuration(appkey, devid): ...@@ -267,6 +267,7 @@ def application_device_configuration(appkey, devid):
base64_args = misc.pend_base64_encode(request.form['arg'], request.form['confid']) base64_args = misc.pend_base64_encode(request.form['arg'], request.form['confid'])
pend.create(appkey, devid, base64_args) pend.create(appkey, devid, base64_args)
flash('Message enqueued', 'success')
return '', 201 return '', 201
else: else:
return redirect(url_for('login')) return redirect(url_for('login'))
...@@ -465,6 +466,20 @@ def dev_conf_rm(appkey, devid): ...@@ -465,6 +466,20 @@ def dev_conf_rm(appkey, devid):
return redirect(url_for('login')) return redirect(url_for('login'))
@app.route('/application/<appkey>/device/<devid>/variables')
def application_device_variables(appkey, devid):
if 'name' in session:
last = data.get_last_n(appkey, devid, 1)
if last[0]:
select = '<select class="form-control" id="varname" name="varname" onchange="validate_form();" required>'
select += '<option value="-">Select Variable</option>'
for k in last[1][0][2]:
select += '<option>'+k+'</option>'
select += '</select>'
return select
else:
return redirect(url_for('login'))
@app.route('/delete-dev') @app.route('/delete-dev')
def delete_dev(): def delete_dev():
if 'name' in session and 'devid' in session: if 'name' in session and 'devid' in session:
...@@ -691,7 +706,7 @@ def dev_data(var, dest, page): ...@@ -691,7 +706,7 @@ def dev_data(var, dest, page):
@app.route('/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>') @app.route('/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>')
def new_dev_data(appkey, devid, var, dest, page): def application_device_data(appkey, devid, var, dest, page):
if dest == 'graph': if dest == 'graph':
last = data.get_last_hours(appkey, devid, MAX_PG_ENTRIES_GRAPH_HOURS, int(page)) last = data.get_last_hours(appkey, devid, MAX_PG_ENTRIES_GRAPH_HOURS, int(page))
arr = '[["Time", "{}"],'.format(var) arr = '[["Time", "{}"],'.format(var)
...@@ -710,6 +725,67 @@ def new_dev_data(appkey, devid, var, dest, page): ...@@ -710,6 +725,67 @@ def new_dev_data(appkey, devid, var, dest, page):
return t return t
@app.route('/application/<appkey>/alerts')
def application_alerts(appkey):
if 'name' in session:
ap = ad.get(appkey)
alerts = nfs.get_alerts_list(appkey)
print(alerts)
return render_template('new/public/alerts.html', alert_list=alerts[1], app=ap[1])
else:
return redirect(url_for('login'))
@app.route('/application/<appkey>/new-alert', methods=['GET', 'POST'])
def application_new_alert(appkey):
if 'name' in session:
if request.method == 'GET':
ap = ad.get(appkey)
devs = dd.get_list(appkey)
return render_template('new/public/new-alert.html', devs=devs[1], app=ap[1])
elif request.method == 'POST':
# create new notification
nid = misc.rand_str(app.config['NID_LENGTH']).decode('utf-8')
dev = dd.get(appkey, request.form['devid'])
try:
desc = dev[1][0]+'.'+request.form['varname']+' '+request.form['operation']+' '+request.form['avalue']
res = nfs.create(nid, appkey, request.form['devid'], request.form['alertname'], desc, 'alert', request.form['alertemail'])
if res[0]:
# create new function and trigger
tr.create_function(appkey, request.form['devid'], nid, [request.form['varname'],request.form['operation'],request.form['avalue']])
tr.create(appkey, request.form['devid'], nid)
flash('Alert created', 'success')
return redirect(url_for('application_alerts', appkey=appkey))
else:
flash('Error creating new alert: {}'.format(res[1]), 'danger')
return redirect(request.url)
except Exception as e:
flash('Error creating new alert: {}. Make sure you have filled all form fields.'.format(e), 'danger')
return redirect(request.url)
else:
return redirect(url_for('login'))
@app.route('/application/<appkey>/remove-alert')
def application_alert_remove(appkey):
if 'name' in session:
nq.delete(appkey, request.args.get('devid'), request.args.get('id'))
tr.delete(appkey, request.args.get('devid'), request.args.get('id'))
tr.delete_function(appkey, request.args.get('devid'), request.args.get('id'))
res = nfs.delete(appkey, request.args.get('devid'), request.args.get('id'))
if res[0]:
flash('Alert removed', 'success')
return '', 200
else:
flash('Alert cannot be removed : {}'.format(res[1]), 'danger')
return '', 500
else:
return redirect(url_for('login'))
@app.route('/alerts') @app.route('/alerts')
def alerts(): def alerts():
if 'name' in session: if 'name' in session:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment