Add initial views for tempmon

This commit is contained in:
Lance Edgar 2016-11-21 23:53:20 -06:00
parent 668191b2e9
commit a39c347ad3
7 changed files with 363 additions and 5 deletions

View file

@ -0,0 +1,17 @@
## -*- coding: utf-8 -*-
<%inherit file="/master/create.mako" />
<%def name="head_tags()">
${parent.head_tags()}
<script type="text/javascript">
$(function() {
$('.field-wrapper.client_uuid select').selectmenu();
$('.field-wrapper.appliance_type select').selectmenu();
});
</script>
</%def>
${parent.body()}

View file

@ -0,0 +1,17 @@
## -*- coding: utf-8 -*-
<%inherit file="/master/edit.mako" />
<%def name="head_tags()">
${parent.head_tags()}
<script type="text/javascript">
$(function() {
$('.field-wrapper.client_uuid select').selectmenu();
$('.field-wrapper.appliance_type select').selectmenu();
});
</script>
</%def>
${parent.body()}

View file

@ -26,8 +26,6 @@ Model Master View
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import re
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy import orm from sqlalchemy import orm
@ -520,9 +518,7 @@ class MasterView(View):
""" """
if hasattr(cls, 'model_title'): if hasattr(cls, 'model_title'):
return cls.model_title return cls.model_title
title = cls.get_model_class().__name__ return cls.get_model_class().get_model_title()
# convert "CamelCase" to "Camel Case"
return re.sub(r'([a-z])([A-Z])', r'\g<1> \g<2>', title)
@classmethod @classmethod
def get_model_title_plural(cls): def get_model_title_plural(cls):

View file

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Views for tempmon
"""
from __future__ import unicode_literals, absolute_import
def includeme(config):
config.include('tailbone.views.tempmon.clients')
config.include('tailbone.views.tempmon.probes')
config.include('tailbone.views.tempmon.readings')

View file

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Views for tempmon clients
"""
from __future__ import unicode_literals, absolute_import
from rattail.db import model
import formalchemy as fa
from webhelpers.html import HTML, tags
from tailbone.db import Session
from tailbone.views import MasterView
class ProbesFieldRenderer(fa.FieldRenderer):
def render_readonly(self, **kwargs):
probes = self.raw_value
if not probes:
return ''
items = []
for probe in probes:
items.append(HTML.tag('li', c=tags.link_to(probe, self.request.route_url('tempmon.probes.view', uuid=probe.uuid))))
return HTML.tag('ul', c=items)
def unique_config_key(value, field):
client = field.parent.model
query = Session.query(model.TempmonClient)\
.filter(model.TempmonClient.config_key == value)
if client.uuid:
query = query.filter(model.TempmonClient.uuid != client.uuid)
if query.count():
raise fa.ValidationError("Config key must be unique")
class TempmonClientView(MasterView):
"""
Master view for tempmon clients.
"""
model_class = model.TempmonClient
route_prefix = 'tempmon.clients'
url_prefix = '/tempmon/clients'
def _preconfigure_grid(self, g):
g.filters['hostname'].default_active = True
g.filters['hostname'].default_verb = 'contains'
g.filters['location'].default_active = True
g.filters['location'].default_verb = 'contains'
g.default_sortkey = 'config_key'
g.config_key.set(label="Key")
def configure_grid(self, g):
g.configure(
include=[
g.config_key,
g.hostname,
g.location,
g.enabled,
g.online,
],
readonly=True)
def _preconfigure_fieldset(self, fs):
fs.config_key.set(validate=unique_config_key)
fs.probes.set(renderer=ProbesFieldRenderer)
def configure_fieldset(self, fs):
fs.configure(
include=[
fs.config_key,
fs.hostname,
fs.location,
fs.probes,
fs.enabled,
fs.online,
])
if self.creating or self.editing:
del fs.probes
del fs.online
def includeme(config):
TempmonClientView.defaults(config)

View file

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Views for tempmon probes
"""
from __future__ import unicode_literals, absolute_import
from rattail.db import model
from formalchemy.fields import SelectFieldRenderer
from webhelpers.html import tags
from tailbone import forms
from tailbone.views import MasterView
class ClientFieldRenderer(SelectFieldRenderer):
def render_readonly(self, **kwargs):
client = self.raw_value
if not client:
return ''
return tags.link_to(client, self.request.route_url('tempmon.clients.view', uuid=client.uuid))
class TempmonProbeView(MasterView):
"""
Master view for tempmon probes.
"""
model_class = model.TempmonProbe
route_prefix = 'tempmon.probes'
url_prefix = '/tempmon/probes'
def _preconfigure_grid(self, g):
g.joiners['client'] = lambda q: q.join(model.TempmonClient)
g.sorters['client'] = g.make_sorter(model.TempmonClient.config_key)
g.default_sortkey = 'client'
g.config_key.set(label="Key")
g.appliance_type.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.TEMPMON_APPLIANCE_TYPE))
def configure_grid(self, g):
g.configure(
include=[
g.client,
g.config_key,
g.appliance_type,
g.description,
g.device_path,
g.enabled,
],
readonly=True)
def _preconfigure_fieldset(self, fs):
fs.client.set(label="TempMon Client", renderer=ClientFieldRenderer)
fs.appliance_type.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.TEMPMON_APPLIANCE_TYPE))
def configure_fieldset(self, fs):
fs.configure(
include=[
fs.client,
fs.config_key,
fs.appliance_type,
fs.description,
fs.device_path,
fs.good_temp_min,
fs.good_temp_max,
fs.temp_warn,
fs.therm_status_timeout,
fs.alert_timeout,
fs.enabled,
])
def includeme(config):
TempmonProbeView.defaults(config)

View file

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Views for tempmon readings
"""
from __future__ import unicode_literals, absolute_import
from rattail.db import model
from formalchemy.fields import SelectFieldRenderer
from webhelpers.html import tags
from tailbone.db import Session
from tailbone.views import MasterView
from tailbone.views.tempmon.probes import ClientFieldRenderer
class ProbeFieldRenderer(SelectFieldRenderer):
def render_readonly(self, **kwargs):
probe = self.raw_value
if not probe:
return ''
return tags.link_to(probe, self.request.route_url('tempmon.probes.view', uuid=probe.uuid))
class TempmonReadingView(MasterView):
"""
Master view for tempmon readings.
"""
model_class = model.TempmonReading
route_prefix = 'tempmon.readings'
url_prefix = '/tempmon/readings'
def configure_grid(self, g):
g.configure(
include=[
g.client,
g.probe,
g.taken,
g.degrees_f,
],
readonly=True)
def _preconfigure_fieldset(self, fs):
fs.client.set(label="TempMon Client", renderer=ClientFieldRenderer)
fs.probe.set(label="TempMon Probe", renderer=ProbeFieldRenderer)
def configure_fieldset(self, fs):
fs.configure(
include=[
fs.client,
fs.probe,
fs.taken,
fs.degrees_f,
])
if self.creating:
del fs.taken
# TODO: this should not be so complicated....
def save_create_form(self, form):
with Session.no_autoflush:
form.fieldset.sync()
reading = form.fieldset.model
probe = Session.query(model.TempmonProbe).get(reading.probe_uuid)
reading.client = probe.client
Session.flush()
def includeme(config):
TempmonReadingView.defaults(config)