Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
timcowlishaw committed Jan 12, 2025
1 parent 36a6a9d commit d57d075
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 5 deletions.
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
@import "components/copyable_input";
@import "components/device_map";
@import "components/map_location_picker";
@import "components/reading";
29 changes: 29 additions & 0 deletions app/assets/stylesheets/components/reading.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.reading {
.big-number {
line-height: 4rem;
height: 4rem;
.trend {
vertical-align: top;
line-height: 4rem;
font-size: 2rem;

}
.value {
font-size: 4rem;
line-height: 4rem;
font-weight: bold;
}
.unit {
font-size: 2rem;
line-height: 4rem;
}
}
.sparkline {
height: 4rem;
width: 100%;
margin-bottom: 0.5rem;
.u-under {
display: none;
}
}
}
2 changes: 2 additions & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import Tags from "bootstrap5-tags";
import {setupCopyableInputs} from "components/copyable_input";
import {setupDeviceMaps} from "components/device_map";
import {setupMapLocationPickers} from "components/map_location_picker";
import {setupSparklines} from "components/sparkline";

export default function setupApplication() {
$(function() {
setupCopyableInputs();
setupDeviceMaps();
setupMapLocationPickers();
setupSparklines();
Tags.init(".tag-select", {
baseClass: "tags-badge badge bg-light border text-dark text-truncate p-2 rounded-4"
});
Expand Down
72 changes: 72 additions & 0 deletions app/javascript/components/sparkline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as $ from "jquery";
import uPlot from "uplot";

class Sparkline {
constructor(element) {
this.element = element;
this.deviceId = element.dataset["deviceId"];
this.sensorId = element.dataset["sensorId"];
this.fromDate = element.dataset["fromDate"] ?? this.getDateString(-24 * 60 * 60 * 1000);
this.toDate = element.dataset["toDate"] = this.getDateString();
}

getDateString(offset = 0) {
return new Date(new Date() - offset).toISOString()
}

async init() {
const data = await $.ajax({
url:`/devices/${this.deviceId}/readings?rollup=5m&sensor_id=${this.sensorId}&from=${this.fromDate}&to=${this.toDate}`,
method: "GET",
});
const timestamps = data.readings.map(x => Date.parse(x[0]) / 1000);
const values = data.readings.map(x => x[1]);
self.uplot = new uPlot(
{
width: this.element.offsetWidth / window.devicePixelRatio,
height: this.element.offsetHeight / window.devicePixelRatio,
pxAlign: false,
cursor: {
show: false
},
select: {
show: false,
},
legend: {
show: false,
},
series: [
{},
{
show: true,
spanGaps: false,
stroke: "#1C1C1C",
fill: "#FFC100",
width: 1
}
],
axes: [
{ show: false },
{ show: false }
],
cursor: {
hover: {
prox: 30,
bias: 0,
skip: [null]
}
},
},
[timestamps, values],
this.element
);
}
}

export function setupSparklines() {
$(".sparkline").each(function(ix, element) {
const line = new Sparkline(element);
line.init();
});
}

29 changes: 29 additions & 0 deletions app/models/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,35 @@ def get_unique_key(default_key, other_keys)
ix == 0 ? default_key : "#{default_key}_#{ix}"
end

def measurement_name
self&.sensor&.measurement&.name
end

def measurement_description
self&.sensor&.measurement&.description
end

def value_unit
self&.sensor&.unit
end

def latest_value
self.device.data[self.sensor.id.to_s]
end

def previous_value
self.device.old_data[self.sensor.id.to_s]
end

def is_raw?
sensor&.tags&.include?("raw")
end

def trend
return 0 if !self.latest_value || !self.previous_value
(self.latest_value - self.previous_value) <=> 0
end

private

def set_key
Expand Down
2 changes: 1 addition & 1 deletion app/models/device.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Device < ActiveRecord::Base

has_many :devices_tags, dependent: :destroy
has_many :tags, through: :devices_tags
has_many :components, dependent: :destroy
has_many :components, -> { order("sensor_id ASC") }, dependent: :destroy
has_many :sensors, through: :components
has_one :postprocessing, dependent: :destroy
has_many :ingest_errors, dependent: :destroy
Expand Down
23 changes: 23 additions & 0 deletions app/views/ui/devices/_reading.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div class="reading">
<%= render layout: "ui/shared/box", locals: { class: "mb-3 p-3", no_padding: true } do %>
<div class="row align-items-top mb-3">
<div class="col-12 col-md-4">
<h3><%= component.measurement_name %></h3>
<p>Last reading at: <%= component.last_reading_at.to_s(:long_ordinal) %></p>
</div>
<div class="col-12 col-md-3">
<div class="big-number">
<span class="trend"><% case component.trend %><% when -1 %>🔺<% when 1 %>🔻<% else %><strong>=</strong><% end %></span><span class="value"><%= component.latest_value.round(2) %></span><span class="unit"><%= component.value_unit %></span>
</div>
</div>
<div class="col-12 col-md-5">
<%= render partial: "ui/shared/sparkline", locals: { component: component } %>
</div>
</div>
<div class="row">
<div class="col-12">
<p><i><%= component.measurement_description %></i></p>
</div>
</div>
<% end %>
</div>
8 changes: 8 additions & 0 deletions app/views/ui/devices/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
<%= render partial: "ui/devices/actions", locals: { device: @device } %>
<% end %>
<%= render partial: "ui/shared/profile_header", locals: { title: t(:show_device_headline, name: @device.name) } %>

<%= render layout: "ui/shared/container" do %>
<% @device.components.each do |component| %>
<% unless component.is_raw? %>
<%= render partial: "reading", locals: { component: component } %>
<% end %>
<% end %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/ui/shared/_box.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="bg-white w-100 border border-thick <%= "p-3 pb-4 pb-md-5" unless local_assigns[:no_padding] %>">
<div class="bg-white w-100 border border-thick <%= "p-3 pb-4 pb-md-5" unless local_assigns[:no_padding] %> <%= local_assigns[:class] || "" %>">
<%= yield %>
</div>
7 changes: 7 additions & 0 deletions app/views/ui/shared/_sparkline.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div
class="sparkline"
data-device-id="<%= component.device_id %>"
data-sensor-id="<%= component.sensor_id %>"
data-from-date="<%= local_assigns[:from] || component.last_reading_at - 1.day %>"
data-to-date="<%= local_assigns[:to] || component.last_reading_at %>"
></div>
5 changes: 4 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ module.exports = function(api) {
'@babel/plugin-syntax-dynamic-import',
isTestEnv && 'babel-plugin-dynamic-import-node',
'@babel/plugin-transform-destructuring',
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-logical-assignment-operators",
[
'@babel/plugin-proposal-class-properties',
{
Expand Down Expand Up @@ -76,7 +79,7 @@ module.exports = function(api) {
{
async: false
}
]
],
].filter(Boolean)
}
}
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
"jquery": "^3.7.1",
"leaflet": "^1.9.4",
"leaflet-defaulticon-compatibility": "^0.1.2",
"uplot": "^1.6.31",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
},
"devDependencies": {
"@babel/plugin-proposal-logical-assignment-operators": "^7.20.7",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9",
"@babel/plugin-transform-optional-chaining": "^7.25.9",
"webpack-dev-server": "^3"
}
}
55 changes: 53 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
dependencies:
"@babel/types" "^7.25.9"

"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0":
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46"
integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==
Expand All @@ -162,7 +162,7 @@
"@babel/helper-optimise-call-expression" "^7.25.9"
"@babel/traverse" "^7.25.9"

"@babel/helper-skip-transparent-expression-wrappers@^7.25.9":
"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9"
integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==
Expand Down Expand Up @@ -256,6 +256,22 @@
"@babel/helper-create-class-features-plugin" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"

"@babel/plugin-proposal-logical-assignment-operators@^7.20.7":
version "7.20.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83"
integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"

"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"

"@babel/plugin-proposal-object-rest-spread@^7.14.7":
version "7.20.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a"
Expand All @@ -267,6 +283,15 @@
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.20.7"

"@babel/plugin-proposal-optional-chaining@^7.21.0":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea"
integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"

"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
version "7.21.0-placeholder-for-preset-env.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
Expand Down Expand Up @@ -303,13 +328,34 @@
dependencies:
"@babel/helper-plugin-utils" "^7.25.9"

"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"

"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"

"@babel/plugin-syntax-object-rest-spread@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"

"@babel/plugin-syntax-optional-chaining@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"

"@babel/plugin-syntax-private-property-in-object@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
Expand Down Expand Up @@ -7218,6 +7264,11 @@ update-browserslist-db@^1.1.1:
escalade "^3.2.0"
picocolors "^1.1.0"

uplot@^1.6.31:
version "1.6.31"
resolved "https://registry.yarnpkg.com/uplot/-/uplot-1.6.31.tgz#092a4b586590e9794b679e1df885a15584b03698"
integrity sha512-sQZqSwVCbJGnFB4IQjQYopzj5CoTZJ4Br1fG/xdONimqgHmsacvCjNesdGDypNKFbrhLGIeshYhy89FxPF+H+w==

uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
Expand Down

0 comments on commit d57d075

Please sign in to comment.