Show tempmon readings when viewing client or probe
also make the probes list more helpful when viewing client
This commit is contained in:
parent
7650064b64
commit
29e023096b
|
@ -24,6 +24,23 @@ div.form-wrapper ul.context-menu li {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* "object helper" panel
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
.object-helper {
|
||||||
|
border: 1px solid black;
|
||||||
|
float: right;
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-helper-content {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
* Forms
|
* Forms
|
||||||
******************************/
|
******************************/
|
||||||
|
|
|
@ -40,18 +40,6 @@
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.batch-helper {
|
|
||||||
border: 1px solid black;
|
|
||||||
float: right;
|
|
||||||
margin-top: 1em;
|
|
||||||
padding: 1em;
|
|
||||||
width: 20em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch-helper-content {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -92,9 +80,9 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
% if status_breakdown is not Undefined:
|
% if status_breakdown is not Undefined:
|
||||||
<div class="batch-helper">
|
<div class="object-helper">
|
||||||
<h3>Row Status Breakdown</h3>
|
<h3>Row Status Breakdown</h3>
|
||||||
<div class="batch-helper-content">
|
<div class="object-helper-content">
|
||||||
% if status_breakdown:
|
% if status_breakdown:
|
||||||
<div class="grid full">
|
<div class="grid full">
|
||||||
<table>
|
<table>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="head_tags()">
|
<%def name="head_tags()">
|
||||||
|
@ -13,10 +13,23 @@
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
${parent.body()}
|
<ul id="context-menu">
|
||||||
|
${self.context_menu_items()}
|
||||||
|
</ul>
|
||||||
|
|
||||||
% if instance.enabled and master.restartable_client(instance) and request.has_perm('tempmon.clients.restart'):
|
% if instance.enabled and master.restartable_client(instance) and request.has_perm('{}.restart'.format(route_prefix)):
|
||||||
<div class="buttons">
|
<div class="object-helper">
|
||||||
<button type="button" id="restart-client">Restart this Client</button>
|
<h3>Client Tools</h3>
|
||||||
|
<div class="object-helper-content">
|
||||||
|
<button type="button" id="restart-client">Restart tempmon-client daemon</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
<div class="form-wrapper">
|
||||||
|
${form.render()|n}
|
||||||
|
</div><!-- form-wrapper -->
|
||||||
|
|
||||||
|
% if master.has_rows:
|
||||||
|
${rows_grid|n}
|
||||||
|
% endif
|
||||||
|
|
|
@ -35,6 +35,7 @@ from rattail_tempmon.db import model as tempmon
|
||||||
import colander
|
import colander
|
||||||
from webhelpers2.html import HTML, tags
|
from webhelpers2.html import HTML, tags
|
||||||
|
|
||||||
|
from tailbone import grids
|
||||||
from tailbone.views.tempmon import MasterView
|
from tailbone.views.tempmon import MasterView
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +49,9 @@ class TempmonClientView(MasterView):
|
||||||
route_prefix = 'tempmon.clients'
|
route_prefix = 'tempmon.clients'
|
||||||
url_prefix = '/tempmon/clients'
|
url_prefix = '/tempmon/clients'
|
||||||
|
|
||||||
|
has_rows = True
|
||||||
|
model_row_class = tempmon.Reading
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'config_key',
|
'config_key',
|
||||||
'hostname',
|
'hostname',
|
||||||
|
@ -71,6 +75,12 @@ class TempmonClientView(MasterView):
|
||||||
'archived',
|
'archived',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
row_grid_columns = [
|
||||||
|
'probe',
|
||||||
|
'taken',
|
||||||
|
'degrees_f',
|
||||||
|
]
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(TempmonClientView, self).configure_grid(g)
|
super(TempmonClientView, self).configure_grid(g)
|
||||||
|
|
||||||
|
@ -106,15 +116,21 @@ class TempmonClientView(MasterView):
|
||||||
f.set_enum('disk_type', self.enum.TEMPMON_DISK_TYPE)
|
f.set_enum('disk_type', self.enum.TEMPMON_DISK_TYPE)
|
||||||
f.widgets['disk_type'].values.insert(0, ('', "(unknown)"))
|
f.widgets['disk_type'].values.insert(0, ('', "(unknown)"))
|
||||||
|
|
||||||
|
# delay
|
||||||
|
f.set_helptext('delay', tempmon.Client.delay.__doc__)
|
||||||
|
|
||||||
# probes
|
# probes
|
||||||
f.set_renderer('probes', self.render_probes)
|
if self.viewing:
|
||||||
|
f.set_renderer('probes', self.render_probes)
|
||||||
|
else:
|
||||||
|
f.remove_field('probes')
|
||||||
|
|
||||||
# notes
|
# notes
|
||||||
f.set_type('notes', 'text')
|
f.set_type('notes', 'text')
|
||||||
|
|
||||||
|
# online
|
||||||
if self.creating or self.editing:
|
if self.creating or self.editing:
|
||||||
f.remove_fields('probes',
|
f.remove_field('online')
|
||||||
'online')
|
|
||||||
|
|
||||||
def unique_config_key(self, node, value):
|
def unique_config_key(self, node, value):
|
||||||
query = self.Session.query(tempmon.Client)\
|
query = self.Session.query(tempmon.Client)\
|
||||||
|
@ -126,15 +142,43 @@ class TempmonClientView(MasterView):
|
||||||
raise colander.Invalid(node, "Config key must be unique")
|
raise colander.Invalid(node, "Config key must be unique")
|
||||||
|
|
||||||
def render_probes(self, client, field):
|
def render_probes(self, client, field):
|
||||||
probes = client.probes
|
if not client.probes:
|
||||||
if not probes:
|
|
||||||
return ""
|
return ""
|
||||||
items = []
|
|
||||||
for probe in probes:
|
route_prefix = self.get_route_prefix()
|
||||||
text = six.text_type(probe)
|
view_url = lambda p, i: self.request.route_url('tempmon.probes.view', uuid=p.uuid)
|
||||||
url = self.request.route_url('tempmon.probes.view', uuid=probe.uuid)
|
actions = [
|
||||||
items.append(HTML.tag('li', c=[tags.link_to(text, url)]))
|
grids.GridAction('view', icon='zoomin', url=view_url),
|
||||||
return HTML.tag('ul', c=items)
|
]
|
||||||
|
if self.request.has_perm('tempmon.probes.edit'):
|
||||||
|
url = lambda p, i: self.request.route_url('tempmon.probes.edit', uuid=p.uuid)
|
||||||
|
actions.append(grids.GridAction('edit', icon='pencil', url=url))
|
||||||
|
|
||||||
|
g = grids.Grid(
|
||||||
|
key='{}.probes'.format(route_prefix),
|
||||||
|
data=client.probes,
|
||||||
|
columns=[
|
||||||
|
'description',
|
||||||
|
'critical_temp_min',
|
||||||
|
'good_temp_min',
|
||||||
|
'good_temp_max',
|
||||||
|
'critical_temp_max',
|
||||||
|
'status',
|
||||||
|
'enabled',
|
||||||
|
],
|
||||||
|
labels={
|
||||||
|
'critical_temp_min': "Crit. Min",
|
||||||
|
'good_temp_min': "Good Min",
|
||||||
|
'good_temp_max': "Good Max",
|
||||||
|
'critical_temp_max': "Crit. Max",
|
||||||
|
},
|
||||||
|
url=lambda p: self.request.route_url('tempmon.probes.view', uuid=p.uuid),
|
||||||
|
linked_columns=['description'],
|
||||||
|
main_actions=actions,
|
||||||
|
)
|
||||||
|
g.set_enum('status', self.enum.TEMPMON_PROBE_STATUS)
|
||||||
|
g.set_type('enabled', 'boolean')
|
||||||
|
return HTML.literal(g.render_grid())
|
||||||
|
|
||||||
def delete_instance(self, client):
|
def delete_instance(self, client):
|
||||||
# bulk-delete all readings first
|
# bulk-delete all readings first
|
||||||
|
@ -149,6 +193,24 @@ class TempmonClientView(MasterView):
|
||||||
self.Session.delete(client)
|
self.Session.delete(client)
|
||||||
self.Session.flush()
|
self.Session.flush()
|
||||||
|
|
||||||
|
def get_row_data(self, client):
|
||||||
|
query = self.Session.query(tempmon.Reading)\
|
||||||
|
.join(tempmon.Probe)\
|
||||||
|
.filter(tempmon.Reading.client == client)
|
||||||
|
return query
|
||||||
|
|
||||||
|
def get_parent(self, reading):
|
||||||
|
return reading.client
|
||||||
|
|
||||||
|
def configure_row_grid(self, g):
|
||||||
|
super(TempmonClientView, self).configure_row_grid(g)
|
||||||
|
|
||||||
|
# probe
|
||||||
|
g.set_filter('probe', tempmon.Probe.description)
|
||||||
|
g.set_sorter('probe', tempmon.Probe.description)
|
||||||
|
|
||||||
|
g.set_sort_defaults('taken', 'desc')
|
||||||
|
|
||||||
def restartable_client(self, client):
|
def restartable_client(self, client):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ import colander
|
||||||
from deform import widget as dfwidget
|
from deform import widget as dfwidget
|
||||||
from webhelpers2.html import tags
|
from webhelpers2.html import tags
|
||||||
|
|
||||||
|
from tailbone import grids
|
||||||
from tailbone.views.tempmon import MasterView
|
from tailbone.views.tempmon import MasterView
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +48,9 @@ class TempmonProbeView(MasterView):
|
||||||
route_prefix = 'tempmon.probes'
|
route_prefix = 'tempmon.probes'
|
||||||
url_prefix = '/tempmon/probes'
|
url_prefix = '/tempmon/probes'
|
||||||
|
|
||||||
|
has_rows = True
|
||||||
|
model_row_class = tempmon.Reading
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'client',
|
'client',
|
||||||
'config_key',
|
'config_key',
|
||||||
|
@ -74,6 +78,11 @@ class TempmonProbeView(MasterView):
|
||||||
'status',
|
'status',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
row_grid_columns = [
|
||||||
|
'taken',
|
||||||
|
'degrees_f',
|
||||||
|
]
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(TempmonProbeView, self).configure_grid(g)
|
super(TempmonProbeView, self).configure_grid(g)
|
||||||
|
|
||||||
|
@ -103,8 +112,10 @@ class TempmonProbeView(MasterView):
|
||||||
f.set_label('client', "Tempmon Client")
|
f.set_label('client', "Tempmon Client")
|
||||||
if self.creating or self.editing:
|
if self.creating or self.editing:
|
||||||
f.replace('client', 'client_uuid')
|
f.replace('client', 'client_uuid')
|
||||||
clients = self.Session.query(tempmon.Client)\
|
clients = self.Session.query(tempmon.Client)
|
||||||
.order_by(tempmon.Client.config_key)
|
if self.creating:
|
||||||
|
clients = clients.filter(tempmon.Client.archived == False)
|
||||||
|
clients = clients.order_by(tempmon.Client.config_key)
|
||||||
client_values = [(client.uuid, "{} ({})".format(client.config_key, client.hostname))
|
client_values = [(client.uuid, "{} ({})".format(client.config_key, client.hostname))
|
||||||
for client in clients]
|
for client in clients]
|
||||||
f.set_widget('client_uuid', dfwidget.SelectWidget(values=client_values))
|
f.set_widget('client_uuid', dfwidget.SelectWidget(values=client_values))
|
||||||
|
@ -151,6 +162,23 @@ class TempmonProbeView(MasterView):
|
||||||
self.Session.delete(probe)
|
self.Session.delete(probe)
|
||||||
self.Session.flush()
|
self.Session.flush()
|
||||||
|
|
||||||
|
def get_row_data(self, probe):
|
||||||
|
query = self.Session.query(tempmon.Reading)\
|
||||||
|
.filter(tempmon.Reading.probe == probe)
|
||||||
|
return query
|
||||||
|
|
||||||
|
def get_parent(self, reading):
|
||||||
|
return reading.client
|
||||||
|
|
||||||
|
def configure_row_grid(self, g):
|
||||||
|
super(TempmonProbeView, self).configure_row_grid(g)
|
||||||
|
|
||||||
|
# # probe
|
||||||
|
# g.set_filter('probe', tempmon.Probe.description)
|
||||||
|
# g.set_sorter('probe', tempmon.Probe.description)
|
||||||
|
|
||||||
|
g.set_sort_defaults('taken', 'desc')
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
TempmonProbeView.defaults(config)
|
TempmonProbeView.defaults(config)
|
||||||
|
|
Loading…
Reference in a new issue