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

admin:user new application view added

parent 5b661487
......@@ -43,13 +43,11 @@
{% endif %}
</div>
<!--
<div class="row" style="margin-top: 30px;">
<div class="col-lg-4">
<a href="../new-application"><button type="submit" class="btn btn-primary btn-block">New application</button></a>
<a href="./new-application"><button type="submit" class="btn btn-primary btn-block">New application</button></a>
</div>
</div>
-->
</div>
</div>
......
{% extends 'logged_layout.html' %}
{% block title %} User Device - HPC&amp;A IoT {% endblock %}
{% block header %}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
{% endblock %}
{% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/administration">Administration</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="/administration/users">Users</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="/administration/users/{{ user }}">{{ user }}</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="/administration/users/{{ user }}/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="/administration/users/{{ user }}/application/{{ app[1] }}">{{ app[0] }}</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="/administration/users/{{ user }}/application/{{ app[1] }}/device/{{ dev[1] }}">{{ dev[0] }}</a>
{% endblock %}
{% block stats %}
<!-- Header -->
<div class="row">
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Name</h5>
<span class="h2 font-weight-bold mb-0">{{ dev[0] }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Device ID</h5>
<span class="h2 font-weight-bold mb-0">{{ dev[1] }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Last time up</h5>
<span class="h2 font-weight-bold mb-0">{{ ltup }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
{% 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">Details</h3>
</div>
<div class="card-body">
<div class="col-lg-12 col-md-6" style="margin-bottom : 30px;">
<div class="card" style="margin-bottom : 15px;">
<div class="card-body">
<h5 class="card-title">Description</h5>
<p class="card-text">{{ dev[2] }}</p>
</div>
</div>
</div>
{% if data %}
<div>
<ul class="nav nav-pills" id="pills-tab" role="tablist">
{% for k in data[0][2] %}
<li class="nav-item col-lg-3 col-md-6" role="presentation">
<a class="nav-link" id="tab_{{ k }}" data-toggle="pill" href="#{{ k }}" role="tab" aria-controls="{{ k }}" aria-selected="true" onclick="display_data('{{ k }}')">{{ k }}</a>
</li>
{% endfor %}
</ul>
<div class="tab-content" id="pills-tabContent">
{% for k in data[0][2] %}
<div class="tab-pane fade card" id="{{ k }}" style="margin-top: 30px;" role="tabpanel" aria-labelledby="tab_{{ k }}">
<div class="card-body">
<h3 class="mb-0 card-header">Last 24 hours data</h3>
<center>
<div id="curve_chart_{{ k }}"></div>
</center>
<p> Total: <strong> {{ total }} </strong> messages. </p>
<table class="table" id="table_{{ k }}">
<thead>
<th> Timestamp </th>
<th> {{ k }} </th>
</thead>
<tbody id="table_{{ k }}_body">
</tbody>
</table>
<center><a href="javascript:void(0);" onclick="return table_load_more('{{ k }}');">Load more</a></center>
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
<div class="col-lg-12">
<p> Device has not sent any data yet. </p>
</div>
{% endif %}
<div class="row" style="margin-top: 30px;">
<div class="col-lg-4">
<a href="./{{ dev[1] }}/configure"><button type="submit" class="btn btn-primary btn-block">Configure</button></a>
</div>
<div class="col-lg-4">
<a href="./{{ dev[1] }}/download-csv"<button type="submit" class="btn btn-primary btn-block">Download CSV</button></a>
</div>
<div class="col-lg-4">
<a href="./{{ dev[1] }}/settings"<button type="submit" class="btn btn-primary btn-block">Settings</button></a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
{% if data %}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(show_first_page);
function init_scroll() {
var ts = {
{% for k in data[0][2] %}
{{ k }} : 1,
{% endfor %}
};
return ts;
}
var tscroll = init_scroll();
function drawChart(dname, ddata) {
var data = google.visualization.arrayToDataTable(ddata);
var options = {
title: '{{ dev[0] }} > '+dname,
curveType: 'function',
hAxis: {
format: 'dd/MM hh:mm'
},
vAxis: {
format: 'decimal',
scaleType: 'linear',
textPosition: 'out'
},
legend: { position: 'none' },
height: 600,
/* width: 900, */
// interpolateNulls: true,
chartArea: { left: '5%', width: '90%', height: '80%' }
};
var container = document.getElementById('curve_chart_'+dname);
var chart = new google.visualization.LineChart(container);
chart.draw(data, options);
}
function display_data(dname) {
// Declare all variables
var i, tabcontent, tablinks;
tscroll = init_scroll();
fetch('/administration/users/{{ user }}/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/graph/1').then(res => res.text()).then(data => drawChart(dname, eval(data)));
fetch('/administration/users/{{ user }}/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => $('#table_'+dname+'_body').html(data));
}
function show_first_page() {
document.getElementById("tab_{{ data[0][2] | first }}").click();
}
function table_load_more(dname) {
tscroll[dname] += 1;
fetch('/administration/users/{{ user }}/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => $('#table_'+dname+'_body').append(data));
fetch('/administration/users/{{ user }}/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => console.log(data));
}
</script>
{% endif %}
{% endblock %}
{% extends 'logged_layout.html' %}
{% block title %} New Application - HPC&amp;A IoT {% endblock %}
{% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/administration">Administration</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="/administration/users">Users</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="/administration/users/{{ user }}">{{ user }}</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="/administration/users/{{ user }}/applications">Applications</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">New Application</h3>
</div>
<div class="card-body">
<form action="new-application" method="post">
<div class="form-group">
<label>Name:</label><br>
<input type="text" maxlength="30" class="form-control" id="appname" name="appname" required><br>
</div>
<div class="form-group">
<label>Description:</label><br>
<textarea id="appdesc" maxlength="200" class="form-control" name="appdesc" rows="5"></textarea>
</div>
<br>
<div class="custom-control custom-control-alternative custom-checkbox">
<input class="custom-control-input" id="secure" type="checkbox" name="secure">
<label class="custom-control-label" for="secure">
<span class="text-muted">Secure</span>
</label>
</div>
<br>
<p> Note, if you use secure option, make sure your device uses aes128 ctr with the corresponding key.</p>
<br>
<div class="form-group">
<button type="submit" class="btn btn-primary">Create Application</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
......@@ -187,7 +187,7 @@ def application_delete(appkey):
def application_device(appkey, devid):
if 'name' in session:
ap = ad.get(appkey)
if session['role'] == 'admin' or session['name'] == ap[1][2]:
if session['name'] == ap[1][2]:
dev = dd.get(appkey, devid)
session['devid'] = int(dev[1][1])
......
......@@ -21,6 +21,8 @@ import app.helpers.misc as misc
MAX_PG = 5
MAX_PG_ENTRIES_USERS = 10
MAX_PG_ENTRIES_DATA = 10
MAX_PG_ENTRIES_GRAPH_HOURS = 24
@app.route('/administration', methods=['GET', 'POST'])
@restricted(access_level='admin')
......@@ -74,6 +76,38 @@ def administration_users_user_applications(name):
return render_template('new/admin/user-applications.html', apps=apps, user=name)
@app.route('/administration/users/<name>/new-application', methods=['GET', 'POST'])
def administration_users_user_application_create(name):
if request.method == 'GET':
return render_template('new/admin/user-new-application.html', user=name)
elif request.method == 'POST':
if request.form['appname'] == '':
flash('Application name cannot be empty.', 'danger')
return render_template(request.url)
elif request.method == 'POST':
appkey = misc.rand_str(app.config['APPKEY_LENGTH']).decode('utf-8')
secure_key = misc.gen_skey_b64(16)
secure = False
if request.form.getlist('secure') and request.form.getlist('secure')[0] == 'on':
secure = True
res = ad.create(request.form['appname'], appkey, name, request.form['appdesc'], secure, secure_key)
if not res[0]:
flash('Error: {}'.format(res[1]), 'danger')
return render_template(request.url)
res = dd.create_table(appkey)
if not res[0]:
ad.delete(appkey)
flash('Error: {}'.format(res[1]), 'danger')
return render_template(request.url)
return redirect(url_for('administration_users_user_applications', name=name))
@app.route('/administration/users/<name>/application/<appkey>')
@restricted(access_level='admin')
def administration_users_user_application(name, appkey):
......@@ -84,6 +118,47 @@ def administration_users_user_application(name, appkey):
return render_template('new/admin/user-application.html', app=ap, devs=devs, user=name)
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>')
@restricted(access_level='admin')
def administration_users_user_application_device(name, appkey, devid):
ap = ad.get(appkey)
dev = dd.get(appkey, devid)
ld = data.get_last_range(appkey, devid, [MAX_PG_ENTRIES_DATA, 0])
cnt = data.get_count(appkey, devid)
ltup = 'Device have not any sent data yet'
if ld[0] and ld[1][0] != []:
ltup = ld[1][0][1]
if ld[0]:
return render_template('new/admin/user-device.html', dev=dev[1], app=ap[1], ltup=ltup, data=ld[1], total=cnt[1][0], user=name)
else:
return render_template('new/admin/user-device.html', dev=dev[1], app=ap[1], ltup=ltup, data=[], total=cnt[1][0], user=name)
@app.route('/administration/users/<name>/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>')
@restricted(access_level='admin')
def administration_users_user_application_device_data(name, appkey, devid, var, dest, page):
if dest == 'graph':
last = data.get_last_hours(appkey, devid, MAX_PG_ENTRIES_GRAPH_HOURS, int(page))
arr = '[["Time", "{}"],'.format(var)
if last[0]:
for d in last[1]:
arr += '[new Date('+str(d[0])+'*1000),'+str(d[2][var])+'],'
arr += ']'
return arr
elif dest == 'table':
# for table <cnt> is in items
last = data.get_last_range(appkey, devid, [MAX_PG_ENTRIES_DATA, (int(page)-1)*MAX_PG_ENTRIES_DATA])
t = ''
if last[0]:
for d in last[1]:
t += '<tr><th>'+d[1]+'</th><th>'+str(d[2][var])+'</th></tr>'
return t
@app.route('/administration/users/<name>/chart-update')
@restricted(access_level='admin')
def administration_users_user_chart_update(name):
......
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