Add basic dashboard page for TempMon
only the older jQuery theme is supported for now...
This commit is contained in:
		
							parent
							
								
									0fbc8c9247
								
							
						
					
					
						commit
						d2c4791611
					
				
					 11 changed files with 375 additions and 1 deletions
				
			
		| 
						 | 
					@ -27,4 +27,12 @@
 | 
				
			||||||
  </style>
 | 
					  </style>
 | 
				
			||||||
</%def>
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
${parent.body()}
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								tailbone/templates/tempmon/appliances/view.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tailbone/templates/tempmon/appliances/view.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/view.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
							
								
								
									
										12
									
								
								tailbone/templates/tempmon/clients/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tailbone/templates/tempmon/clients/index.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/index.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,13 @@
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
</%def>
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%def name="object_helpers()">
 | 
					<%def name="object_helpers()">
 | 
				
			||||||
  % if instance.enabled and master.restartable_client(instance) and request.has_perm('{}.restart'.format(route_prefix)):
 | 
					  % if instance.enabled and master.restartable_client(instance) and request.has_perm('{}.restart'.format(route_prefix)):
 | 
				
			||||||
      <div class="object-helper">
 | 
					      <div class="object-helper">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										135
									
								
								tailbone/templates/tempmon/dashboard.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								tailbone/templates/tempmon/dashboard.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,135 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					<%inherit file="/page.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="title()">TempMon Appliances » Dashboard</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="content_title()">Dashboard</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="extra_javascript()">
 | 
				
			||||||
 | 
					  ${parent.extra_javascript()}
 | 
				
			||||||
 | 
					  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
 | 
				
			||||||
 | 
					  % if not use_buefy:
 | 
				
			||||||
 | 
					  <script type="text/javascript">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var contexts = {};
 | 
				
			||||||
 | 
					    var charts = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function fetchReadings(appliance_uuid) {
 | 
				
			||||||
 | 
					        if (appliance_uuid === undefined) {
 | 
				
			||||||
 | 
					            appliance_uuid = $('#appliance_uuid').val();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('.form-wrapper').mask("Fetching data");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (Object.keys(charts).length) {
 | 
				
			||||||
 | 
					            Object.keys(charts).forEach(function(key) {
 | 
				
			||||||
 | 
					                charts[key].destroy();
 | 
				
			||||||
 | 
					                delete charts[key];
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var url = '${url("tempmon.dashboard.readings")}';
 | 
				
			||||||
 | 
					        var params = {'appliance_uuid': appliance_uuid};
 | 
				
			||||||
 | 
					        $.get(url, params, function(data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (data.probes) {
 | 
				
			||||||
 | 
					                data.probes.forEach(function(probe) {
 | 
				
			||||||
 | 
					                    charts[probe.uuid] = new Chart(contexts[probe.uuid], {
 | 
				
			||||||
 | 
					                        type: 'scatter',
 | 
				
			||||||
 | 
					                        data: {
 | 
				
			||||||
 | 
					                            datasets: [{
 | 
				
			||||||
 | 
					                                label: probe.description,
 | 
				
			||||||
 | 
					                                data: probe.readings
 | 
				
			||||||
 | 
					                            }]
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        options: {
 | 
				
			||||||
 | 
					                            scales: {
 | 
				
			||||||
 | 
					                                xAxes: [{
 | 
				
			||||||
 | 
					                                    type: 'time',
 | 
				
			||||||
 | 
					                                    time: {unit: 'minute'},
 | 
				
			||||||
 | 
					                                    position: 'bottom'
 | 
				
			||||||
 | 
					                                }]
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // TODO: should improve this
 | 
				
			||||||
 | 
					                alert(data.error);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $('.form-wrapper').unmask();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $(function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % for probe in appliance.probes:
 | 
				
			||||||
 | 
					            contexts['${probe.uuid}'] = $('#tempchart-${probe.uuid}');
 | 
				
			||||||
 | 
					        % endfor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('#appliance_uuid').selectmenu({
 | 
				
			||||||
 | 
					            change: function(event, ui) {
 | 
				
			||||||
 | 
					                $('.form-wrapper').mask("Fetching data");
 | 
				
			||||||
 | 
					                $(this).parents('form').submit();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fetchReadings();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="render_this_page()">
 | 
				
			||||||
 | 
					  <div style="display: flex;">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="form-wrapper">
 | 
				
			||||||
 | 
					      <div class="form">
 | 
				
			||||||
 | 
					        ${h.form(request.current_route_url())}
 | 
				
			||||||
 | 
					        ${h.csrf_token(request)}
 | 
				
			||||||
 | 
					        % if use_buefy:
 | 
				
			||||||
 | 
					            <b-field horizontal label="Appliance">
 | 
				
			||||||
 | 
					              ${appliance_select}
 | 
				
			||||||
 | 
					            </b-field>
 | 
				
			||||||
 | 
					        % else:
 | 
				
			||||||
 | 
					            <div class="field-wrapper">
 | 
				
			||||||
 | 
					              <label>Appliance</label>
 | 
				
			||||||
 | 
					              <div class="field">
 | 
				
			||||||
 | 
					                ${appliance_select}
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        % endif
 | 
				
			||||||
 | 
					        ${h.end_form()}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <a href="${url('tempmon.appliances.view', uuid=appliance.uuid)}">
 | 
				
			||||||
 | 
					      ${h.image(url('tempmon.appliances.thumbnail', uuid=appliance.uuid), "")}
 | 
				
			||||||
 | 
					    </a>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  % if appliance.probes:
 | 
				
			||||||
 | 
					      % for probe in appliance.probes:
 | 
				
			||||||
 | 
					          <h3>
 | 
				
			||||||
 | 
					            Probe:  ${h.link_to(probe.description, url('tempmon.probes.graph', uuid=probe.uuid))}
 | 
				
			||||||
 | 
					            (status: ${enum.TEMPMON_PROBE_STATUS[probe.status]})
 | 
				
			||||||
 | 
					          </h3>
 | 
				
			||||||
 | 
					          % if probe.enabled:
 | 
				
			||||||
 | 
					              % if use_buefy:
 | 
				
			||||||
 | 
					                  <canvas ref="tempchart" width="400" height="150"></canvas>
 | 
				
			||||||
 | 
					              % else:
 | 
				
			||||||
 | 
					                  <canvas id="tempchart-${probe.uuid}" width="400" height="60"></canvas>
 | 
				
			||||||
 | 
					              % endif
 | 
				
			||||||
 | 
					          % else:
 | 
				
			||||||
 | 
					              <p>This probe is not enabled.</p>
 | 
				
			||||||
 | 
					          % endif
 | 
				
			||||||
 | 
					      % endfor
 | 
				
			||||||
 | 
					  % else:
 | 
				
			||||||
 | 
					      <h3>This appliance has no probes configured!</h3>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,16 @@
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
</%def>
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if master.has_perm('view'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("View this {}".format(model_title), master.get_action_url('view', probe))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%def name="render_this_page()">
 | 
					<%def name="render_this_page()">
 | 
				
			||||||
  <div style="display: flex; justify-content: space-between;">
 | 
					  <div style="display: flex; justify-content: space-between;">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								tailbone/templates/tempmon/probes/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tailbone/templates/tempmon/probes/index.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/index.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					@ -92,6 +92,9 @@
 | 
				
			||||||
<%def name="context_menu_items()">
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
  ${parent.context_menu_items()}
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
  <li>${h.link_to("View Readings as Graph", action_url('graph', instance))}</li>
 | 
					  <li>${h.link_to("View Readings as Graph", action_url('graph', instance))}</li>
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
</%def>
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%def name="render_main_fields(form)">
 | 
					<%def name="render_main_fields(form)">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								tailbone/templates/tempmon/readings/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tailbone/templates/tempmon/readings/index.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/index.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('tempmon.appliances.dashboard'):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Go to the Dashboard", url('tempmon.dashboard'))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
################################################################################
 | 
					################################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  Rattail -- Retail Software Framework
 | 
					#  Rattail -- Retail Software Framework
 | 
				
			||||||
#  Copyright © 2010-2018 Lance Edgar
 | 
					#  Copyright © 2010-2020 Lance Edgar
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  This file is part of Rattail.
 | 
					#  This file is part of Rattail.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -34,3 +34,4 @@ def includeme(config):
 | 
				
			||||||
    config.include('tailbone.views.tempmon.clients')
 | 
					    config.include('tailbone.views.tempmon.clients')
 | 
				
			||||||
    config.include('tailbone.views.tempmon.probes')
 | 
					    config.include('tailbone.views.tempmon.probes')
 | 
				
			||||||
    config.include('tailbone.views.tempmon.readings')
 | 
					    config.include('tailbone.views.tempmon.readings')
 | 
				
			||||||
 | 
					    config.include('tailbone.views.tempmon.dashboard')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										162
									
								
								tailbone/views/tempmon/dashboard.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								tailbone/views/tempmon/dashboard.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,162 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8; -*-
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#  Rattail -- Retail Software Framework
 | 
				
			||||||
 | 
					#  Copyright © 2010-2020 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 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 General Public License for more
 | 
				
			||||||
 | 
					#  details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#  You should have received a copy of the GNU General Public License along with
 | 
				
			||||||
 | 
					#  Rattail.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Tempmon "Dashboard" View
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import unicode_literals, absolute_import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from rattail.time import localtime, make_utc
 | 
				
			||||||
 | 
					from rattail_tempmon.db import model as tempmon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from webhelpers2.html import tags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tailbone.views import View
 | 
				
			||||||
 | 
					from tailbone.db import TempmonSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TempmonDashboardView(View):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Dashboard view for tempmon
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    session_key = 'tempmon.dashboard.appliance_uuid'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dashboard(self):
 | 
				
			||||||
 | 
					        use_buefy = self.get_use_buefy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.method == 'POST':
 | 
				
			||||||
 | 
					            appliance = None
 | 
				
			||||||
 | 
					            uuid = self.request.POST.get('appliance_uuid')
 | 
				
			||||||
 | 
					            if uuid:
 | 
				
			||||||
 | 
					                appliance = TempmonSession.query(tempmon.Appliance).get(uuid)
 | 
				
			||||||
 | 
					                if appliance:
 | 
				
			||||||
 | 
					                    self.request.session[self.session_key] = appliance.uuid
 | 
				
			||||||
 | 
					            if not appliance:
 | 
				
			||||||
 | 
					                self.request.session.flash("Appliance could not be found: {}".format(uuid), 'error')
 | 
				
			||||||
 | 
					            raise self.redirect(self.request.current_route_url())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        selected_uuid = self.request.params.get('appliance_uuid')
 | 
				
			||||||
 | 
					        selected_appliance = None
 | 
				
			||||||
 | 
					        if not selected_uuid:
 | 
				
			||||||
 | 
					            selected_uuid = self.request.session.get(self.session_key)
 | 
				
			||||||
 | 
					            if not selected_uuid:
 | 
				
			||||||
 | 
					                # must declare the "first" appliance selected
 | 
				
			||||||
 | 
					                selected_appliance = TempmonSession.query(tempmon.Appliance)\
 | 
				
			||||||
 | 
					                                                   .order_by(tempmon.Appliance.name)\
 | 
				
			||||||
 | 
					                                                   .first()
 | 
				
			||||||
 | 
					                if selected_appliance:
 | 
				
			||||||
 | 
					                    selected_uuid = selected_appliance.uuid
 | 
				
			||||||
 | 
					                    self.request.session[self.session_key] = selected_uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not selected_appliance and selected_uuid:
 | 
				
			||||||
 | 
					            selected_appliance = TempmonSession.query(tempmon.Appliance)\
 | 
				
			||||||
 | 
					                                               .get(selected_uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        appliances = TempmonSession.query(tempmon.Appliance)\
 | 
				
			||||||
 | 
					                                   .order_by(tempmon.Appliance.name)\
 | 
				
			||||||
 | 
					                                   .all()
 | 
				
			||||||
 | 
					        appliance_options = tags.Options([
 | 
				
			||||||
 | 
					            tags.Option(appliance.name, appliance.uuid)
 | 
				
			||||||
 | 
					            for appliance in appliances])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if use_buefy:
 | 
				
			||||||
 | 
					            appliance_select = None
 | 
				
			||||||
 | 
					            raise NotImplementedError
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            appliance_select = tags.select('appliance_uuid', selected_uuid, appliance_options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            'index_url': self.request.route_url('tempmon.appliances'),
 | 
				
			||||||
 | 
					            'index_title': "TempMon Appliances",
 | 
				
			||||||
 | 
					            'use_buefy': use_buefy,
 | 
				
			||||||
 | 
					            'appliance_select': appliance_select,
 | 
				
			||||||
 | 
					            'appliance': selected_appliance,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def readings(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # track down the requested appliance
 | 
				
			||||||
 | 
					        uuid = self.request.params.get('appliance_uuid')
 | 
				
			||||||
 | 
					        if not uuid:
 | 
				
			||||||
 | 
					            return {'error': "Must specify valid appliance_uuid"}
 | 
				
			||||||
 | 
					        appliance = TempmonSession.query(tempmon.Appliance).get(uuid)
 | 
				
			||||||
 | 
					        if not appliance:
 | 
				
			||||||
 | 
					            return {'error': "Must specify valid appliance_uuid"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # remember which appliance was shown last
 | 
				
			||||||
 | 
					        self.request.session[self.session_key] = appliance.uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # fetch all "current" (recent) readings for all connected probes
 | 
				
			||||||
 | 
					        probes = []
 | 
				
			||||||
 | 
					        cutoff = make_utc() - datetime.timedelta(seconds=7200) # 2 hours ago
 | 
				
			||||||
 | 
					        for probe in appliance.probes:
 | 
				
			||||||
 | 
					            probes.append({
 | 
				
			||||||
 | 
					                'uuid': probe.uuid,
 | 
				
			||||||
 | 
					                'description': probe.description,
 | 
				
			||||||
 | 
					                'location': probe.location,
 | 
				
			||||||
 | 
					                'enabled': str(probe.enabled) if probe.enabled else None,
 | 
				
			||||||
 | 
					                'readings': self.get_probe_readings(probe, cutoff),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        return {'probes': probes}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_probe_readings(self, probe, cutoff):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # figure out which readings we need to graph
 | 
				
			||||||
 | 
					        readings = TempmonSession.query(tempmon.Reading)\
 | 
				
			||||||
 | 
					                                 .filter(tempmon.Reading.probe == probe)\
 | 
				
			||||||
 | 
					                                 .filter(tempmon.Reading.taken >= cutoff)\
 | 
				
			||||||
 | 
					                                 .order_by(tempmon.Reading.taken)\
 | 
				
			||||||
 | 
					                                 .all()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # convert readings to data for scatter plot
 | 
				
			||||||
 | 
					        return [{
 | 
				
			||||||
 | 
					            'x': localtime(self.rattail_config, reading.taken, from_utc=True).isoformat(),
 | 
				
			||||||
 | 
					            'y': float(reading.degrees_f),
 | 
				
			||||||
 | 
					        } for reading in readings]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def defaults(cls, config):
 | 
				
			||||||
 | 
					        cls._defaults(config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def _defaults(cls, config):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # dashboard
 | 
				
			||||||
 | 
					        config.add_tailbone_permission('tempmon.appliances', 'tempmon.appliances.dashboard',
 | 
				
			||||||
 | 
					                                       "View the Tempmon Appliance \"Dashboard\" page")
 | 
				
			||||||
 | 
					        config.add_route('tempmon.dashboard', '/tempmon/dashboard',
 | 
				
			||||||
 | 
					                         request_method=('GET', 'POST'))
 | 
				
			||||||
 | 
					        config.add_view(cls, attr='dashboard', route_name='tempmon.dashboard',
 | 
				
			||||||
 | 
					                        renderer='/tempmon/dashboard.mako')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # readings
 | 
				
			||||||
 | 
					        config.add_route('tempmon.dashboard.readings', '/tempmon/dashboard/readings',
 | 
				
			||||||
 | 
					                         request_method='GET')
 | 
				
			||||||
 | 
					        config.add_view(cls, attr='readings', route_name='tempmon.dashboard.readings',
 | 
				
			||||||
 | 
					                        renderer='json')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def includeme(config):
 | 
				
			||||||
 | 
					    TempmonDashboardView.defaults(config)
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue