regimen variable labels
parent
46d7413610
commit
db203a444a
|
@ -42,10 +42,11 @@
|
|||
}
|
||||
|
||||
.regimen-event {
|
||||
position: relative;
|
||||
background: $gray;
|
||||
padding: 0.7rem;
|
||||
border-radius: 3px;
|
||||
height: 3.5rem;
|
||||
min-height: 3.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
|
@ -58,12 +59,18 @@
|
|||
|
||||
.regimen-event-time {
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.regimen-event-variable {
|
||||
display: inline-block;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.regimen-control {
|
||||
float: right;
|
||||
margin-right: 0.7rem;
|
||||
margin-top: 0.3rem;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
.regimen-days-label {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import { mapStateToProps } from "../state_to_props";
|
||||
import { fakeState } from "../../__test_support__/fake_state";
|
||||
import { TaggedResource } from "farmbot";
|
||||
import { buildResourceIndex } from "../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../__test_support__/resource_index_builder";
|
||||
import { newTaggedResource } from "../../sync/actions";
|
||||
import { selectAllRegimens } from "../../resources/selectors";
|
||||
import { fakeVariableNameSet } from "../../__test_support__/fake_variables";
|
||||
import { fakeRegimen, fakeSequence } from "../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
fakeRegimen, fakeSequence
|
||||
} from "../../__test_support__/fake_state/resources";
|
||||
|
||||
describe("mapStateToProps()", () => {
|
||||
it("returns props: no regimen selected", () => {
|
||||
|
@ -48,7 +52,9 @@ describe("mapStateToProps()", () => {
|
|||
it("returns variableData", () => {
|
||||
const reg = fakeRegimen();
|
||||
const seq = fakeSequence();
|
||||
reg.body.regimen_items = [{ sequence_id: seq.body.id || 0, time_offset: 1000 }];
|
||||
reg.body.regimen_items = [{
|
||||
sequence_id: seq.body.id || 0, time_offset: 1000
|
||||
}];
|
||||
const state = fakeState();
|
||||
state.resources = buildResourceIndex([reg, seq]);
|
||||
state.resources.consumers.regimens.currentRegimen = reg.uuid;
|
||||
|
@ -57,4 +63,37 @@ describe("mapStateToProps()", () => {
|
|||
const props = mapStateToProps(state);
|
||||
expect(props.variableData).toEqual(varData);
|
||||
});
|
||||
|
||||
it("returns calendar rows", () => {
|
||||
const reg = fakeRegimen();
|
||||
const seq = fakeSequence();
|
||||
seq.body.body = [{
|
||||
kind: "move_absolute", args: {
|
||||
location: { kind: "identifier", args: { label: "variable" } },
|
||||
offset: { kind: "coordinate", args: { x: 0, y: 0, z: 0 } },
|
||||
speed: 100,
|
||||
}
|
||||
}];
|
||||
seq.body.args.locals.body = [{
|
||||
kind: "parameter_declaration",
|
||||
args: {
|
||||
label: "variable",
|
||||
default_value: { kind: "coordinate", args: { x: 1, y: 2, z: 3 } }
|
||||
}
|
||||
}];
|
||||
reg.body.regimen_items = [{
|
||||
sequence_id: seq.body.id || 0, time_offset: 1000
|
||||
}];
|
||||
const state = fakeState();
|
||||
state.resources = buildResourceIndex([reg, seq]);
|
||||
state.resources.consumers.regimens.currentRegimen = reg.uuid;
|
||||
const props = mapStateToProps(state);
|
||||
expect(props.calendar).toEqual([{
|
||||
day: "1",
|
||||
items: [expect.objectContaining({
|
||||
item: reg.body.regimen_items[0],
|
||||
sortKey: 1000, variable: "variable"
|
||||
})]
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
jest.mock("../../../api/crud", () => ({
|
||||
overwrite: jest.fn(),
|
||||
}));
|
||||
jest.mock("../../../api/crud", () => ({ overwrite: jest.fn() }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
|
@ -18,8 +16,8 @@ import { Actions } from "../../../constants";
|
|||
const testVariable: VariableDeclaration = {
|
||||
kind: "variable_declaration",
|
||||
args: {
|
||||
label: "label", data_value: {
|
||||
kind: "identifier", args: { label: "new_var" }
|
||||
label: "variable", data_value: {
|
||||
kind: "coordinate", args: { x: 1, y: 2, z: 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -40,7 +38,8 @@ describe("<ActiveEditor />", () => {
|
|||
regimen: fakeRegimen(),
|
||||
item: {
|
||||
sequence_id: 0, time_offset: 1000
|
||||
}
|
||||
},
|
||||
variable: undefined,
|
||||
}]
|
||||
}],
|
||||
resources: buildResourceIndex([]).index,
|
||||
|
@ -115,6 +114,23 @@ describe("<ActiveEditor />", () => {
|
|||
wrapper.instance().toggleVarShow();
|
||||
expect(wrapper.state()).toEqual({ variablesCollapsed: true });
|
||||
});
|
||||
|
||||
it("shows location variable label: coordinate", () => {
|
||||
const p = fakeProps();
|
||||
p.calendar[0].items[0].regimen.body.body = [testVariable];
|
||||
p.calendar[0].items[0].variable = testVariable.args.label;
|
||||
const wrapper = mount(<ActiveEditor {...p} />);
|
||||
expect(wrapper.find(".regimen-event-variable").text())
|
||||
.toEqual("Location Variable - Coordinate (1, 2, 3)");
|
||||
});
|
||||
|
||||
it("doesn't show location variable label", () => {
|
||||
const p = fakeProps();
|
||||
p.calendar[0].items[0].regimen.body.body = [];
|
||||
p.calendar[0].items[0].variable = "variable";
|
||||
const wrapper = mount(<ActiveEditor {...p} />);
|
||||
expect(wrapper.find(".regimen-event-variable").length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("editRegimenVariables()", () => {
|
||||
|
|
|
@ -37,7 +37,8 @@ describe("<RegimenEditor />", () => {
|
|||
regimen: regimen,
|
||||
item: {
|
||||
sequence_id: 0, time_offset: 1000
|
||||
}
|
||||
},
|
||||
variable: undefined,
|
||||
}]
|
||||
}],
|
||||
resources: buildResourceIndex([]).index,
|
||||
|
|
|
@ -17,6 +17,9 @@ import {
|
|||
import { addOrEditBodyVariables } from "../../sequences/locals_list/handle_select";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import { Actions } from "../../constants";
|
||||
import { reduceVariables } from "../../sequences/locals_list/variable_support";
|
||||
import { determineDropdown, withPrefix } from "../../resources/sequence_meta";
|
||||
import { ResourceIndex } from "../../resources/interfaces";
|
||||
|
||||
/**
|
||||
* The bottom half of the regimen editor panel (when there's something to
|
||||
|
@ -60,7 +63,8 @@ export class ActiveEditor
|
|||
<OpenSchedulerButton dispatch={this.props.dispatch} />
|
||||
<RegimenRows {...this.regimenProps}
|
||||
calendar={this.props.calendar}
|
||||
varsCollapsed={this.state.variablesCollapsed} />
|
||||
varsCollapsed={this.state.variablesCollapsed}
|
||||
resources={this.props.resources} />
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
@ -111,28 +115,32 @@ interface RegimenRowsProps {
|
|||
calendar: CalendarRow[];
|
||||
dispatch: Function;
|
||||
varsCollapsed: boolean;
|
||||
resources: ResourceIndex;
|
||||
}
|
||||
|
||||
const RegimenRows = (props: RegimenRowsProps) =>
|
||||
<div className="regimen" style={{
|
||||
height: regimenSectionHeight(props.regimen, props.varsCollapsed)
|
||||
}}>
|
||||
{props.calendar.map(regimenDay(props.dispatch))}
|
||||
{props.calendar.map(regimenDay(props.dispatch, props.resources))}
|
||||
</div>;
|
||||
|
||||
const regimenDay = (dispatch: Function) =>
|
||||
const regimenDay = (dispatch: Function, resources: ResourceIndex) =>
|
||||
(group: CalendarRow, dayIndex: number) =>
|
||||
<div className="regimen-day" key={dayIndex}>
|
||||
<label> {t("Day {{day}}", { day: group.day })} </label>
|
||||
{group.items.map(regimenItemRow(dispatch, dayIndex))}
|
||||
{group.items.map(regimenItemRow(dispatch, resources, dayIndex))}
|
||||
</div>;
|
||||
|
||||
const regimenItemRow = (dispatch: Function, dayIndex: number) =>
|
||||
const regimenItemRow = (
|
||||
dispatch: Function, resources: ResourceIndex, dayIndex: number
|
||||
) =>
|
||||
(row: RegimenItemCalendarRow, itemIndex: number) =>
|
||||
<div className={`${row.color} regimen-event`}
|
||||
key={`${dayIndex}.${itemIndex}`}>
|
||||
<span className="regimen-event-title">{row.name}</span>
|
||||
<span className="regimen-event-time">{row.hhmm}</span>
|
||||
<DisplayVarValue row={row} resources={resources} />
|
||||
<i className="fa fa-trash regimen-control" onClick={() =>
|
||||
dispatch(removeRegimenItem(row.item, row.regimen))} />
|
||||
</div>;
|
||||
|
@ -142,3 +150,21 @@ const removeRegimenItem = (item: RegimenItem, r: TaggedRegimen) => {
|
|||
copy.body.regimen_items = r.body.regimen_items.filter(x => x !== item);
|
||||
return overwrite(r, copy.body);
|
||||
};
|
||||
|
||||
interface DisplayVarValueProps {
|
||||
row: RegimenItemCalendarRow;
|
||||
resources: ResourceIndex;
|
||||
}
|
||||
|
||||
const DisplayVarValue = (props: DisplayVarValueProps) => {
|
||||
const { variable, regimen } = props.row;
|
||||
if (variable) {
|
||||
const variableNode = reduceVariables(regimen.body.body)[variable];
|
||||
if (variableNode) {
|
||||
return <span className="regimen-event-variable">
|
||||
{withPrefix(determineDropdown(variableNode, props.resources).label)}
|
||||
</span>;
|
||||
}
|
||||
}
|
||||
return <span />;
|
||||
};
|
||||
|
|
|
@ -38,6 +38,8 @@ export interface RegimenItemCalendarRow {
|
|||
sortKey: number;
|
||||
day: number;
|
||||
dispatch: Function;
|
||||
/** Variable label. */
|
||||
variable: string | undefined;
|
||||
}
|
||||
|
||||
/** Used by UI widgets that modify a regimen */
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
findSequenceById,
|
||||
maybeGetTimeSettings
|
||||
} from "../resources/selectors";
|
||||
import { TaggedRegimen } from "farmbot";
|
||||
import { TaggedRegimen, TaggedSequence } from "farmbot";
|
||||
import moment from "moment";
|
||||
import { ResourceIndex, UUID, VariableNameSet } from "../resources/interfaces";
|
||||
import {
|
||||
|
@ -109,6 +109,7 @@ const createRows = (
|
|||
(item: RegimenItem): RegimenItemCalendarRow => {
|
||||
const uuid = findId(index, "Sequence", item.sequence_id);
|
||||
const sequence = findSequence(index, uuid);
|
||||
const variable = getParameterLabel(sequence);
|
||||
const { time_offset } = item;
|
||||
const d = moment.duration(time_offset);
|
||||
const { name } = sequence.body;
|
||||
|
@ -116,5 +117,13 @@ const createRows = (
|
|||
const FORMAT = timeFormatString(timeSettings);
|
||||
const hhmm = moment({ hour: d.hours(), minute: d.minutes() }).format(FORMAT);
|
||||
const day = Math.floor(moment.duration(time_offset).asDays()) + 1;
|
||||
return { name, hhmm, color, day, dispatch, regimen, item, sortKey: time_offset };
|
||||
return {
|
||||
name, hhmm, color, day, dispatch, regimen, item, variable,
|
||||
sortKey: time_offset
|
||||
};
|
||||
};
|
||||
|
||||
const getParameterLabel = (sequence: TaggedSequence): string | undefined =>
|
||||
(sequence.body.args.locals.body || [])
|
||||
.filter(variable => variable.kind === "parameter_declaration")
|
||||
.map(variable => variable.args.label)[0];
|
||||
|
|
|
@ -57,7 +57,9 @@ const maybeFindVariable = (
|
|||
): SequenceMeta | undefined =>
|
||||
uuid ? findVariableByName(resources, uuid, label) : undefined;
|
||||
|
||||
const withPrefix = (label: string) => `${t("Location Variable")} - ${label}`;
|
||||
/** Add "Location Variable - " prefix to string. */
|
||||
export const withPrefix = (label: string) =>
|
||||
`${t("Location Variable")} - ${label}`;
|
||||
|
||||
interface DetermineVarDDILabelProps {
|
||||
label: string;
|
||||
|
|
|
@ -51,7 +51,7 @@ export const addOrEditParamApps =
|
|||
};
|
||||
|
||||
/** Convert array to a dictionary. */
|
||||
const reduceVariables = <T extends VariableNode>(
|
||||
export const reduceVariables = <T extends VariableNode>(
|
||||
variables: T[]):
|
||||
Dictionary<T> => {
|
||||
const items: Dictionary<T> = {};
|
||||
|
|
Loading…
Reference in New Issue