Skip to content

Commit

Permalink
fix curve svg issues and allow curve deselection
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielburnworth committed Feb 2, 2023
1 parent bcf7726 commit d28d4e0
Show file tree
Hide file tree
Showing 17 changed files with 318 additions and 267 deletions.
9 changes: 5 additions & 4 deletions frontend/__test_support__/resource_index_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "farmbot";
import { resourceReducer, emptyState } from "../resources/reducer";
import { resourceReady } from "../sync/actions";
import { threeWayComparison as c3 } from "../util/move";
import { threeWayComparison as compare3 } from "../util/move";
import { defensiveClone } from "../util/util";
import { chain, groupBy } from "lodash";
import { MessageType } from "../sequences/interfaces";
Expand Down Expand Up @@ -406,6 +406,7 @@ const KIND_PRIORITY: ResourceLookupTable = {
FarmwareInstallation: 0,
WebAppConfig: 0,
SavedGarden: 0,
Curve: 0,
PlantTemplate: 1,
Peripheral: 1,
Point: 1,
Expand All @@ -426,17 +427,17 @@ const KIND_PRIORITY: ResourceLookupTable = {
WizardStepResult: 4,
Telemetry: 4,
Crop: 4,
Curve: 4,
};
export function buildResourceIndex(resources: TaggedResource[] = FAKE_RESOURCES,
state = emptyState()) {
const sortedResources = repairBrokeReferences(resources)
.sort((l, r) => c3(KIND_PRIORITY[l.kind], KIND_PRIORITY[r.kind]));
.sort((l, r) => compare3(KIND_PRIORITY[l.kind], KIND_PRIORITY[r.kind]));
type K = keyof typeof KIND_PRIORITY;
return chain(sortedResources)
.groupBy(KIND)
.toPairs()
.sort((l, r) => c3(KIND_PRIORITY[l[0] as K || 4], KIND_PRIORITY[r[0] as K || 4]))
.sort((l, r) =>
compare3(KIND_PRIORITY[l[0] as K || 4], KIND_PRIORITY[r[0] as K || 4]))
.map((y) => resourceReady((y as TaggedResource["kind"][])[0], y[1]))
.reduce(resourceReducer, state)
.value();
Expand Down
1 change: 1 addition & 0 deletions frontend/css/farm_designer/farm_designer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
}
}
}
.curve-search-item-name,
.plant-search-item-name,
.group-search-item-name,
.regimen-search-item-name,
Expand Down
48 changes: 21 additions & 27 deletions frontend/css/farm_designer/farm_designer_panels.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2413,6 +2413,13 @@ li {
}
}

.curve-svg {
.y-axis-line,
.warning-line {
pointer-events: none;
}
}

.curve-info-panel {
.panel-title {
.white-text {
Expand Down Expand Up @@ -2538,25 +2545,10 @@ li {
}

.crop-curve-info {
margin-top: 1.5rem;
.bp4-collapse {
padding-top: 0.5rem;
}
.header {
display: flex;
position: relative;
height: 4rem;
cursor: pointer;
margin-left: -1rem;
padding-left: 1rem;
margin-right: -1rem;
padding-right: 1rem;
&:hover {
background: $light_gray;
}
label {
cursor: pointer;
}
}
p {
line-height: 4rem;
font-size: 1.3rem;
Expand All @@ -2566,26 +2558,28 @@ li {
}
i {
position: absolute;
right: 2rem;
right: 0.5rem;
line-height: 4rem;
}
.active-curve-name {
position: relative;
height: 4rem;
line-height: 3rem;
a {
position: absolute;
top: -0.25rem;
left: 5rem;
}
p,
.filter-search {
width: 90%;
float: right;
display: inline-block;
position: absolute;
right: 3rem;
width: 75%;
margin-top: 0.5rem;
}
p {
width: 90%;
line-height: 3rem;
float: right;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
label {
line-height: 4rem;
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions frontend/curves/__tests__/chart_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe("<CurveSvg />", () => {
const p = fakeProps();
p.curve.body.data = TEST_DATA;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(22);
expect(wrapper.find("text").length).toEqual(16);
expect(wrapper.text()).not.toContain("⚠");
expect(wrapper.html()).toContain("row-resize");
expect(wrapper.html()).not.toContain("not-allowed");
Expand All @@ -47,7 +47,7 @@ describe("<CurveSvg />", () => {
p.curve.body.data = TEST_DATA;
p.editable = false;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(22);
expect(wrapper.find("text").length).toEqual(16);
expect(wrapper.html()).not.toContain("row-resize");
});

Expand All @@ -57,15 +57,15 @@ describe("<CurveSvg />", () => {
1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 12: 12,
};
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(13);
expect(wrapper.find("text").length).toEqual(7);
expect(wrapper.html()).toContain("not-allowed");
});

it("renders chart: max days", () => {
const p = fakeProps();
p.curve.body.data = { 1: 0, 200: 100 };
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(22);
expect(wrapper.find("text").length).toEqual(16);
});

it("hovers bar", () => {
Expand Down Expand Up @@ -162,7 +162,7 @@ describe("<CurveSvg />", () => {
p.botSize.y.value = 200;
p.curve.body.data = TEST_DATA;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(24);
expect(wrapper.find("text").length).toEqual(18);
expect(wrapper.text()).toContain("⚠");
wrapper.find("#warning-icon").first().simulate("mouseEnter");
expect(wrapper.text()).toContain("spread beyond");
Expand Down Expand Up @@ -190,7 +190,7 @@ describe("<CurveSvg />", () => {
p.botSize.y.value = 1000;
p.curve.body.data = TEST_DATA;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(26);
expect(wrapper.find("text").length).toEqual(20);
expect(wrapper.text()).toContain("⚠");
wrapper.find("#warning-icon").first().simulate("mouseEnter");
expect(wrapper.text()).toContain("spread beyond");
Expand All @@ -204,7 +204,7 @@ describe("<CurveSvg />", () => {
p.sourceFbosConfig = () => ({ value: 100, consistent: true });
p.curve.body.data = TEST_DATA;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(24);
expect(wrapper.find("text").length).toEqual(18);
expect(wrapper.text()).toContain("⚠");
wrapper.find("#warning-icon").first().simulate("mouseEnter");
expect(wrapper.text()).toContain("exceed the distance");
Expand All @@ -219,7 +219,7 @@ describe("<CurveSvg />", () => {
p.sourceFbosConfig = () => ({ value: 100, consistent: true });
p.curve.body.data = TEST_DATA;
const wrapper = mount(<CurveSvg {...p} />);
expect(wrapper.find("text").length).toEqual(24);
expect(wrapper.find("text").length).toEqual(18);
expect(wrapper.text()).toContain("⚠");
wrapper.find("#warning-icon").first().simulate("mouseEnter");
expect(wrapper.text()).toContain("exceed the distance");
Expand Down
36 changes: 20 additions & 16 deletions frontend/curves/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { floor, isUndefined, range, round } from "lodash";
import { Curve } from "farmbot/dist/resources/api_resources";
import { Color } from "../ui";
import {
maxValue, maxDay, populatedData, inData, addOrRemoveItem, dataFull,
maxValue, maxDay, populatedData, inData, addOrRemoveItem, dataFull, scaleData,
} from "./data_actions";
import {
CurveIconProps,
Expand Down Expand Up @@ -50,7 +50,7 @@ export const CurveSvg = (props: CurveSvgProps) => {
const [dragging, setDragging] = React.useState<string | undefined>(undefined);
const showHoverEffect = (day: string | undefined) =>
dragging == day || (!dragging && hovered == day);
return <svg width={"100%"} height={"100%"}
return <svg className={"curve-svg"} width={"100%"} height={"100%"}
viewBox={`-15 -10 ${svgXMax(data)} ${svgYMax() + 30}`}
style={dragging ? { cursor: "grabbing" } : {}}
onMouseUp={() => setDragging(undefined)}
Expand Down Expand Up @@ -251,11 +251,13 @@ const YAxis = (props: YAxisProps) => {
{range(yStep, yStep * 10, yStep).map(value => {
const y = normY(value);
return <g id={"" + value} key={value}>
<text fontSize={5} textAnchor={"end"} fill={Color.darkGray}
x={-2} y={y + 1.5}>
{value}
</text>
<line stroke={Color.darkGray} opacity={0.1} strokeWidth={0.3}
{y > -1 &&
<text fontSize={5} textAnchor={"end"} fill={Color.darkGray}
x={-2} y={y + 1.5}>
{value}
</text>}
<line className={"y-axis-line"}
stroke={Color.darkGray} opacity={0.1} strokeWidth={0.3}
x1={0} y1={y} x2={xMax} y2={y} />
</g>;
})}
Expand Down Expand Up @@ -323,11 +325,11 @@ const WarningLines = (props: WarningLinesProps) => {
},
{
value: distanceToEdge.y.min, textValue: edgeBleed.y.min,
text: t("Y-min bleed"), style: "low"
text: t("Y-min bleed"), style: "high"
},
{
value: distanceToEdge.x.max, textValue: edgeBleed.x.max,
text: t("X-max bleed"), style: "high"
text: t("X-max bleed"), style: "low"
},
{
value: distanceToEdge.y.max, textValue: edgeBleed.y.max,
Expand All @@ -348,19 +350,21 @@ const WarningLines = (props: WarningLinesProps) => {
return <g id={"warning-lines"}>
{lines().map((line, index) =>
line.value &&
<line id={"low-line"} key={index}
<line id={"warning-line"} className={"warning-line"} key={index}
strokeDasharray={line.style == "low" ? 2 : undefined}
stroke={Color.darkOrange} opacity={0.75} strokeWidth={0.3}
x1={xZero} y1={normY(line.value)}
x2={svgXMax(props.curve.body.data)} y2={normY(line.value)} />)}
x2={svgXMax(props.curve.body.data) - 20} y2={normY(line.value)} />)}
{lines().map((clearance, index) =>
clearance.value &&
<text id={"warning-icon"} key={index}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
fontSize={5} textAnchor={"end"}
fill={Color.darkOrange} fontWeight={"bold"}
x={-5} y={normY(clearance.value)}></text>)}
x={svgXMax(props.curve.body.data) - 15} y={normY(clearance.value) + 1}>
</text>)}
{hovered && <g id={"warning-content"}
fontSize={5} fill={Color.offWhite}>
<rect x={0} y={0} width={X_MAX * 0.75}
Expand All @@ -383,22 +387,22 @@ const WarningLines = (props: WarningLinesProps) => {
};

export const CurveIcon = (props: CurveIconProps) => {
const { data } = props.curve.body;
const data = scaleData(props.curve.body.data, 100, 100);
const normX = normDay(data);
const normY = normValue(data);
const curvePathArray = Object.entries(data)
const curvePathArray = Object.entries(populatedData(data))
.map(([day, value], index) => {
const prefix = index == 0 ? "M" : "L";
return `${prefix}${normX(day)},${normY(value)}`;
});
return <svg className={"curve-icon"}
width={"32px"} height={"32px"}
viewBox={`-15 -10 ${svgXMax(data)} ${svgYMax() + 30}`}>
viewBox={`-15 -10 ${X_MAX + 25} ${svgYMax() + 30}`}>
<path id={"fill"} strokeWidth={0}
fill={curvePanelColor(props.curve)}
d={curvePathArray
.concat(`L${normX(maxDay(data))},${normY(0)}`)
.concat(`L${normX(0)},${normY(0)}z`)
.concat(`L${normX(1)},${normY(0)}z`)
.join(" ")} />
<path id={"line"}
stroke={curveColor(props.curve)} strokeWidth={5}
Expand Down
9 changes: 6 additions & 3 deletions frontend/curves/data_actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { cloneDeep, first, last, max, range, round, sum } from "lodash";
import {
cloneDeep, first, isUndefined, last, max, range, round, sum,
} from "lodash";
import { Curve } from "farmbot/dist/resources/api_resources";
import { error } from "../toast/toast";
import { t } from "../i18next_wrapper";
Expand Down Expand Up @@ -82,8 +84,9 @@ export const scaleData =
const newValue = round(val * valueScale);
newData[newDay] = newValue;
});
if (Object.values(data).length < 2 && dayInput > 1) {
newData[dayScale] = newData[1];
if (Object.values(data).length < 2 && dayInput > 1
&& !isUndefined(newData[1])) {
newData[dayInput] = newData[1];
}
return newData;
};
2 changes: 1 addition & 1 deletion frontend/farm_designer/map/layers/plants/plant_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { Path } from "../../../../internal_urls";
import { GetWebAppConfigValue } from "../../../../config_storage/actions";
import { NumericSetting } from "../../../../session_keys";
import { findMostUsedCurveForCrop } from "../../../../plants/crop_info";
import { findMostUsedCurveForCrop } from "../../../../plants/curve_info";
import { CurveType } from "../../../../curves/templates";
import { DevSettings } from "../../../../settings/dev/dev_support";

Expand Down
Loading

0 comments on commit d28d4e0

Please sign in to comment.