Show tempmon readings when viewing client or probe

also make the probes list more helpful when viewing client
This commit is contained in:
Lance Edgar 2018-10-05 19:29:26 -05:00
parent 7650064b64
commit 29e023096b
5 changed files with 140 additions and 32 deletions

View file

@ -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
******************************/ ******************************/

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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)