Skip to content

Commit 6724d9a

Browse files
improve moisture map colors and add reading deletion
1 parent 32f655c commit 6724d9a

File tree

11 files changed

+104
-17
lines changed

11 files changed

+104
-17
lines changed

frontend/api/__tests__/api_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe("API", () => {
1010
[
1111
[API.current.pointSearchPath, BASE + "/api/points/search"],
1212
[API.current.allPointsPath, BASE + "/api/points/?filter=all"],
13-
[API.current.sensorReadingPath, BASE + "/api/sensor_readings"],
13+
[API.current.sensorReadingPath, BASE + "/api/sensor_readings/"],
1414
[API.current.farmwareEnvPath, BASE + "/api/farmware_envs/"],
1515
[API.current.plantTemplatePath, BASE + "/api/plant_templates/"],
1616
[API.current.farmwareInstallationPath, BASE + "/api/farmware_installations/"],

frontend/api/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class API {
139139
/** /api/firmware_config */
140140
get firmwareConfigPath() { return `${this.baseUrl}/api/firmware_config/`; }
141141
/** /api/sensor_readings */
142-
get sensorReadingPath() { return `${this.baseUrl}/api/sensor_readings`; }
142+
get sensorReadingPath() { return `${this.baseUrl}/api/sensor_readings/`; }
143143
/** /api/sensors/ */
144144
get sensorPath() { return `${this.baseUrl}/api/sensors/`; }
145145
/** /api/farmware_envs/:id */

frontend/css/panels/sensors.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,32 @@
2323
th,
2424
td {
2525
width: 1%;
26+
padding: 0.25rem;
27+
&:first-of-type {
28+
padding-left: 0.5rem;
29+
}
30+
&:last-of-type {
31+
padding: 0;
32+
}
2633
}
2734
tr {
35+
height: 3rem;
2836
&.previous {
2937
color: $medium_gray;
3038
}
3139
&.selected {
3240
background: $translucent1_white;
3341
}
3442
}
43+
label {
44+
font-size: 1.1rem;
45+
}
46+
.fa-trash {
47+
color: $transparent;
48+
&:hover {
49+
color: unset; // sass-lint:disable-line variable-for-property
50+
}
51+
}
3552
.sensor-history-table-contents {
3653
max-height: 20rem;
3754
overflow-y: auto;

frontend/farm_designer/location_info.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ const ReadingsListItem = (props: ReadingsListItemProps) =>
397397
const sensorName = `${props.sensorNameByPinLookup[pin]} (pin ${pin})`;
398398
return <TableRow
399399
key={item.uuid}
400+
dispatch={props.dispatch}
400401
sensorName={sensorName}
401402
sensorReading={item}
402403
timeSettings={props.timeSettings}

frontend/farm_designer/map/layers/sensor_readings/__tests__/sensor_readings_layer_test.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe("<SensorReadingsLayer />", () => {
4949
p.sensorReadings[0].body.mode = ANALOG;
5050
const reading = fakeSensorReading();
5151
reading.body.mode = ANALOG;
52-
reading.body.value = 1000;
52+
reading.body.value = 800;
5353
reading.body.x = 100;
5454
reading.body.y = 200;
5555
p.sensorReadings.push(reading);
@@ -62,10 +62,10 @@ describe("<SensorReadingsLayer />", () => {
6262

6363
describe("getMoistureColor()", () => {
6464
it.each<[number, string, number]>([
65-
[0, "rgb(255, 255, 255)", 0],
66-
[200, "rgb(198, 198, 255)", 0.11],
67-
[700, "rgb(57, 57, 255)", 0.39],
68-
[900, "rgb(0, 0, 255)", 0.5],
65+
[0, "rgb(0, 0, 255)", 0],
66+
[200, "rgb(0, 0, 255)", 0],
67+
[700, "rgb(0, 0, 255)", 0.2],
68+
[900, "rgb(0, 0, 255)", 0.42],
6969
[1024, "rgb(0, 0, 0)", 0],
7070
])("returns color for %s: %s %s", (value, color, alpha) => {
7171
const c = getMoistureColor(value);

frontend/farm_designer/map/layers/sensor_readings/sensor_readings_layer.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export const filterMoistureReadings = (
1919
const readings = sensorReadings
2020
.filter(r =>
2121
(sensorNameByPinLookup[r.body.pin] || "").toLowerCase().includes("soil")
22-
&& r.body.mode == ANALOG);
22+
&& r.body.mode == ANALOG)
23+
.filter(r => r.body.value <= 900);
2324
return { readings, sensorNameByPinLookup };
2425
};
2526

@@ -71,11 +72,10 @@ export function SensorReadingsLayer(props: SensorReadingsLayerProps) {
7172
export const getMoistureColor: GetColor = (value: number) => {
7273
const maxValue = 900;
7374
if (value > maxValue) { return { rgb: "rgb(0, 0, 0)", a: 0 }; }
74-
const normalizedValue = round(255 * value / maxValue);
75-
const r = 255 - normalizedValue;
76-
const g = 255 - normalizedValue;
75+
const r = 0;
76+
const g = 0;
7777
const b = 255;
78-
const a = round(0 + 0.5 * value / maxValue, 2);
78+
const a = round((0.75 * value / maxValue) ** 3, 2);
7979
return {
8080
rgb: `rgb(${r}, ${g}, ${b})`,
8181
a: a,

frontend/sensors/sensor_readings/__tests__/sensor_readings_test.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
jest.mock("../../../api/crud", () => ({
2+
destroy: jest.fn(),
3+
}));
4+
15
import React from "react";
26
import { mount } from "enzyme";
37
import moment from "moment";
@@ -7,6 +11,7 @@ import {
711
fakeSensorReading, fakeSensor,
812
} from "../../../__test_support__/fake_state/resources";
913
import { fakeTimeSettings } from "../../../__test_support__/fake_time_settings";
14+
import { destroy } from "../../../api/crud";
1015

1116
describe("<SensorReadings />", () => {
1217
const fakeProps = (): SensorReadingsProps => ({
@@ -98,4 +103,24 @@ describe("<SensorReadings />", () => {
98103
expect(wrapper.instance().state.xyzLocation).toEqual(undefined);
99104
expect(wrapper.instance().state.sensor).toEqual(undefined);
100105
});
106+
107+
it("deletes selected readings", () => {
108+
window.confirm = () => true;
109+
const p = fakeProps();
110+
const wrapper = mount<SensorReadings>(<SensorReadings {...p} />);
111+
const reading = fakeSensorReading();
112+
reading.uuid = "uuid0";
113+
wrapper.instance().deleteSelected([reading])();
114+
expect(destroy).toHaveBeenCalledWith("uuid0");
115+
});
116+
117+
it("doesn't delete selected readings", () => {
118+
window.confirm = () => false;
119+
const p = fakeProps();
120+
const wrapper = mount<SensorReadings>(<SensorReadings {...p} />);
121+
const reading = fakeSensorReading();
122+
reading.uuid = "uuid0";
123+
wrapper.instance().deleteSelected([reading])();
124+
expect(destroy).not.toHaveBeenCalled();
125+
});
101126
});

frontend/sensors/sensor_readings/__tests__/table_test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
jest.mock("../../../api/crud", () => ({
2+
destroy: jest.fn(),
3+
}));
4+
15
import React from "react";
26
import { mount } from "enzyme";
37
import { SensorReadingsTable } from "../table";
@@ -6,6 +10,7 @@ import {
610
fakeSensorReading, fakeSensor,
711
} from "../../../__test_support__/fake_state/resources";
812
import { fakeTimeSettings } from "../../../__test_support__/fake_time_settings";
13+
import { destroy } from "../../../api/crud";
914

1015
describe("<SensorReadingsTable />", () => {
1116
const fakeProps = (sr = fakeSensorReading()): SensorReadingsTableProps => ({
@@ -14,6 +19,7 @@ describe("<SensorReadingsTable />", () => {
1419
timeSettings: fakeTimeSettings(),
1520
hover: jest.fn(),
1621
hovered: undefined,
22+
dispatch: jest.fn(),
1723
});
1824

1925
it("renders", () => {
@@ -68,4 +74,14 @@ describe("<SensorReadingsTable />", () => {
6874
const wrapper = mount(<SensorReadingsTable {...p} />);
6975
expect(wrapper.find("tr").last().hasClass("selected")).toEqual(true);
7076
});
77+
78+
it("deletes reading", () => {
79+
const sr = fakeSensorReading();
80+
const p = fakeProps(sr);
81+
p.hovered = sr.uuid;
82+
const wrapper = mount(<SensorReadingsTable {...p} />);
83+
expect(wrapper.find("tr").last().hasClass("selected")).toEqual(true);
84+
wrapper.find(".fa-trash").first().simulate("click");
85+
expect(destroy).toHaveBeenCalledWith(sr.uuid);
86+
});
7187
});

frontend/sensors/sensor_readings/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface SensorReadingsTableProps {
3434
/** TaggedSensorReading UUID */
3535
hovered: string | undefined;
3636
hover: (hovered: string | undefined) => void;
37+
dispatch: Function;
3738
}
3839

3940
export interface TableRowProps {
@@ -46,6 +47,7 @@ export interface TableRowProps {
4647
hover: (hovered: string | undefined) => void;
4748
hideLocation?: boolean;
4849
distance?: number;
50+
dispatch: Function;
4951
}
5052

5153
export interface SensorSelectionProps {

frontend/sensors/sensor_readings/sensor_readings.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import {
99
} from "./time_period_selection";
1010
import { LocationSelection, LocationDisplay } from "./location_selection";
1111
import { SensorSelection } from "./sensor_selection";
12-
import { TaggedSensor } from "farmbot";
12+
import { TaggedSensor, TaggedSensorReading } from "farmbot";
1313
import { AxisInputBoxGroupState } from "../../controls/interfaces";
1414
import { SensorReadingsPlot } from "./graph";
1515
import { Position } from "@blueprintjs/core";
1616
import { AddSensorReadingMenu } from "./add_reading";
17+
import { destroy } from "../../api/crud";
1718

1819
export class SensorReadings
1920
extends React.Component<SensorReadingsProps, SensorReadingsState> {
@@ -46,6 +47,12 @@ export class SensorReadings
4647
showPreviousPeriod: false,
4748
deviation: 0,
4849
});
50+
deleteSelected = (readings: TaggedSensorReading[]) => () => {
51+
if (!confirm(t("Delete {{count}} sensor readings?", {
52+
count: readings.length,
53+
}))) { return; }
54+
readings.map(reading => this.props.dispatch(destroy(reading.uuid)));
55+
};
4956

5057
toggleAddReadingMenu = () => {
5158
this.setState({ addReadingMenuOpen: !this.state.addReadingMenuOpen });
@@ -61,6 +68,11 @@ export class SensorReadings
6168
<div className="panel-header">
6269
<h2 className="panel-title">{t("History")}</h2>
6370
<div className="row">
71+
<button className={"fb-button red"}
72+
title={t("delete selected")}
73+
onClick={this.deleteSelected(readingsForPeriod("current"))}>
74+
{t("delete selected")}
75+
</button>
6476
<button className="fb-button gray"
6577
title={t("clear filters")}
6678
onClick={this.clearFilters}>
@@ -107,6 +119,7 @@ export class SensorReadings
107119
showPreviousPeriod={this.state.showPreviousPeriod}
108120
timePeriod={this.state.timePeriod} />
109121
<SensorReadingsTable
122+
dispatch={this.props.dispatch}
110123
readingsForPeriod={readingsForPeriod}
111124
sensors={this.props.sensors}
112125
timeSettings={this.props.timeSettings}

0 commit comments

Comments
 (0)