[UNSTABLE] Pull out more junk
parent
6a37826043
commit
47d924f8a9
|
@ -5,9 +5,6 @@ import {
|
|||
} from "../locals_list";
|
||||
import {
|
||||
VariableDeclaration,
|
||||
ParameterDeclaration,
|
||||
Tool,
|
||||
Point,
|
||||
Coordinate
|
||||
} from "farmbot";
|
||||
import {
|
||||
|
@ -23,12 +20,7 @@ import {
|
|||
InputBox, generateList, handleSelect
|
||||
} from "../step_tiles/tile_move_absolute/index";
|
||||
import {
|
||||
extractParent,
|
||||
setParent,
|
||||
guessFromDataType,
|
||||
guessVecFromLabel,
|
||||
ParentVariableFormProps,
|
||||
PARENT,
|
||||
LocalsListProps,
|
||||
} from "../locals_list_support";
|
||||
import { DELETE_ME_LATER } from "../../resources/interfaces";
|
||||
|
@ -36,7 +28,6 @@ import { DELETE_ME_LATER } from "../../resources/interfaces";
|
|||
const coord: Coordinate = { kind: "coordinate", args: { x: 1, y: 2, z: 3 } };
|
||||
const t = fakeTool();
|
||||
t.body.id = 5;
|
||||
const tool: Tool = { kind: "tool", args: { tool_id: t.body.id } };
|
||||
const mrGoodVar: VariableDeclaration = {
|
||||
// https://en.wikipedia.org/wiki/Mr._Goodbar
|
||||
kind: "variable_declaration",
|
||||
|
@ -53,162 +44,10 @@ const fakeProps = (): LocalsListProps => {
|
|||
};
|
||||
};
|
||||
|
||||
describe("extractParent()", () => {
|
||||
const irrelevant: VariableDeclaration = {
|
||||
kind: "variable_declaration",
|
||||
args: { label: "nope", data_value: coord }
|
||||
};
|
||||
|
||||
const paramDeclr: ParameterDeclaration = {
|
||||
kind: "parameter_declaration",
|
||||
args: { label: "parent", data_type: "coordinate" }
|
||||
};
|
||||
|
||||
it("returns undefined on empty arrays", () => {
|
||||
expect(extractParent([])).toBeUndefined();
|
||||
expect(extractParent()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns undefined on arrays that don't have a parent", () => {
|
||||
expect(extractParent([irrelevant])).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns parent if it is a PARAMETER declaration.", () => {
|
||||
const result = extractParent([paramDeclr]);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toBe(paramDeclr);
|
||||
});
|
||||
|
||||
it("returns the first result found", () => {
|
||||
const paramIsFirst = [paramDeclr, mrGoodVar, irrelevant];
|
||||
const r1 = extractParent(paramIsFirst);
|
||||
if (r1) {
|
||||
expect(r1.kind).toBe("parameter_declaration");
|
||||
expect(r1.args.label).toBe("parent");
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
|
||||
const varIsFirst = [irrelevant, mrGoodVar, paramDeclr];
|
||||
const r2 = extractParent(varIsFirst);
|
||||
if (r2) {
|
||||
expect(r2.kind).toBe("variable_declaration");
|
||||
expect(r2.args.label).toBe("parent");
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("setParent()", () => {
|
||||
const point: Point = {
|
||||
kind: "point",
|
||||
args: { pointer_type: "point", pointer_id: 5 }
|
||||
};
|
||||
|
||||
it("deals with parameter declarations", () => {
|
||||
const data_value: ParameterDeclaration = {
|
||||
kind: "parameter_declaration", args: { label: "---", data_type: "point" }
|
||||
};
|
||||
const sequence = fakeSequence();
|
||||
const expected = {
|
||||
kind: "scope_declaration",
|
||||
args: {},
|
||||
body: [{
|
||||
kind: "parameter_declaration",
|
||||
args: { label: "parent", data_type: "point" }
|
||||
}]
|
||||
};
|
||||
const result = setParent(sequence, data_value);
|
||||
const actual = result.args.locals;
|
||||
|
||||
expect(actual.args).toEqual(expected.args);
|
||||
expect(actual.body).toEqual(expected.body);
|
||||
expect(actual.kind).toEqual(expected.kind);
|
||||
});
|
||||
|
||||
it("crashes on `identifier` nodes (no re-binding of vars yet)", () => {
|
||||
const seq = fakeSequence();
|
||||
const cb = () =>
|
||||
setParent(seq, { kind: "identifier", args: { label: "foo" } });
|
||||
expect(cb).toThrow();
|
||||
});
|
||||
|
||||
it("sets tools, points and coordinates as new `parent` var", () => {
|
||||
const seq = fakeSequence();
|
||||
[tool, point, coord].map(item => {
|
||||
const result = setParent(seq, item).args.locals.body || [];
|
||||
expect(result.length).toEqual(1);
|
||||
const parent = result[0];
|
||||
expect(parent.args.label).toEqual("parent");
|
||||
expect(parent.kind).toEqual("variable_declaration");
|
||||
(parent.kind === "variable_declaration") &&
|
||||
expect(parent.args.data_value).toBe(item);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("guessFromDataType()", () => {
|
||||
it("returns undefined if not coord", () => {
|
||||
expect(guessFromDataType(tool)).toBe(undefined);
|
||||
});
|
||||
|
||||
it("returns coord.args", () => {
|
||||
expect(guessFromDataType(coord)).toBe(coord.args);
|
||||
});
|
||||
});
|
||||
|
||||
describe("guessVecFromLabel()", () => {
|
||||
it("returns undefined on malformed strings", () => {
|
||||
[
|
||||
"",
|
||||
"))((1,(),2,3)",
|
||||
" ()()()",
|
||||
"Alphabetical (a, b, c)",
|
||||
"tool 1,2,3",
|
||||
"Something else (test123)",
|
||||
"Tool_1512679072 ",
|
||||
"Tool"
|
||||
].map(bad => {
|
||||
expect(guessVecFromLabel(bad)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
it("returns vec3 on well formed strings", () => {
|
||||
[
|
||||
{
|
||||
string: "Point_1512679072 (20, 50, 0)",
|
||||
expectation: { x: 20, y: 50, z: 0 }
|
||||
},
|
||||
{
|
||||
string: "carrot (360, 290, 0)",
|
||||
expectation: { x: 360, y: 290, z: 0 }
|
||||
},
|
||||
{
|
||||
string: "Safe-Remove Weed (633, 450, 0)",
|
||||
expectation: { x: 633, y: 450, z: 0 }
|
||||
},
|
||||
{
|
||||
string: "Point_1512679072 (0, 100, 0)",
|
||||
expectation: { x: 0, y: 100, z: 0 }
|
||||
}
|
||||
].map(xmp => {
|
||||
const result = guessVecFromLabel(xmp.string);
|
||||
if (result) {
|
||||
expect(result.x).toBe(xmp.expectation.x);
|
||||
expect(result.y).toBe(xmp.expectation.y);
|
||||
expect(result.y).toBe(xmp.expectation.y);
|
||||
} else {
|
||||
fail("No result obtained.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("<ParentVariableForm/>", () => {
|
||||
it("renders correct UI components", () => {
|
||||
const props: ParentVariableFormProps = {
|
||||
betterParent: DELETE_ME_LATER,
|
||||
deprecatedParent: mrGoodVar,
|
||||
parent: DELETE_ME_LATER,
|
||||
sequence: fakeSequence(),
|
||||
resources: buildResourceIndex().index,
|
||||
onChange: jest.fn()
|
||||
|
@ -221,7 +60,7 @@ describe("<ParentVariableForm/>", () => {
|
|||
expect(selects.length).toBe(1);
|
||||
const p = selects.first().props();
|
||||
expect(p.allowEmpty).toBe(true);
|
||||
const choices = generateList(props.resources, [PARENT]);
|
||||
const choices = generateList(props.resources, []);
|
||||
expect(p.list).toEqual(choices);
|
||||
const choice = choices[1];
|
||||
p.onChange(choice);
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import * as React from "react";
|
||||
import {
|
||||
ParentVariableFormProps,
|
||||
PARENT,
|
||||
LocalsListProps
|
||||
} from "./locals_list_support";
|
||||
import { Row, Col, FBSelect } from "../ui";
|
||||
import { t } from "i18next";
|
||||
import {
|
||||
generateList
|
||||
} from "./step_tiles/tile_move_absolute/generate_list";
|
||||
import { InputBox } from "./step_tiles/tile_move_absolute/input_box";
|
||||
import { handleSelect } from "./step_tiles/tile_move_absolute/handle_select";
|
||||
import { ParentVariableFormProps, LocalsListProps, PARENT } from "./locals_list_support";
|
||||
|
||||
const REWRITE_THIS = () => {
|
||||
console.error("Re write this callback, OK? RC");
|
||||
|
@ -19,9 +16,9 @@ const REWRITE_THIS = () => {
|
|||
* Allows the user to chose the value of the `parent` variable, etc. */
|
||||
export const ParentVariableForm =
|
||||
(props: ParentVariableFormProps) => {
|
||||
const { sequence, resources } = props;
|
||||
const { x, y, z } = props.betterParent.location;
|
||||
const isDisabled = !props.betterParent.editable;
|
||||
const { sequence, resources, onChange } = props;
|
||||
const { x, y, z } = props.parent.location;
|
||||
const isDisabled = !props.parent.editable;
|
||||
|
||||
return <div className="parent-variable-form">
|
||||
<Row>
|
||||
|
@ -31,11 +28,12 @@ export const ParentVariableForm =
|
|||
key={JSON.stringify(sequence)}
|
||||
allowEmpty={true}
|
||||
list={generateList(resources, [PARENT])}
|
||||
selectedItem={props.betterParent.dropdown}
|
||||
onChange={(x) => {
|
||||
console.log("REIMPLEMENT ME:");
|
||||
console.dir(x);
|
||||
} />
|
||||
selectedItem={props.parent.dropdown}
|
||||
onChange={(ddi) => {
|
||||
console.error("FINISH ME");
|
||||
handleSelect(props.resources, ddi);
|
||||
onChange({ x: -23, y: -23, z: -23 });
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
|
@ -73,11 +71,10 @@ export const ParentVariableForm =
|
|||
/** List of local variable declarations for a sequence. If no variables are
|
||||
* found, shows nothing. */
|
||||
export const LocalsList = (props: LocalsListProps) => {
|
||||
const betterParent = props.variableData["parent"];
|
||||
return betterParent
|
||||
const parent = props.variableData["parent"];
|
||||
return parent
|
||||
? <ParentVariableForm
|
||||
betterParent={betterParent}
|
||||
deprecatedParent={betterParent.celeryNode}
|
||||
parent={parent}
|
||||
sequence={props.deprecatedSequence}
|
||||
resources={props.deprecatedResources}
|
||||
onChange={REWRITE_THIS} />
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
import {
|
||||
ParameterDeclaration,
|
||||
VariableDeclaration,
|
||||
TaggedSequence,
|
||||
Vector3,
|
||||
ScopeDeclarationBodyItem
|
||||
} from "farmbot";
|
||||
import { ResourceIndex, VariableNameSet } from "../resources/interfaces";
|
||||
import { CeleryVariable } from "./step_tiles/tile_move_absolute/index";
|
||||
import { TaggedSequence } from "farmbot";
|
||||
import { defensiveClone } from "../util";
|
||||
import { isNaN } from "lodash";
|
||||
import { SequenceMeta } from "../resources/sequence_meta";
|
||||
|
||||
type OnChange = (data_type: Vector3) => void;
|
||||
type DataValue = VariableDeclaration["args"]["data_value"];
|
||||
|
||||
export interface LocalsListProps {
|
||||
variableData: VariableNameSet;
|
||||
|
@ -22,8 +15,7 @@ export interface LocalsListProps {
|
|||
}
|
||||
|
||||
export interface ParentVariableFormProps {
|
||||
betterParent: SequenceMeta;
|
||||
deprecatedParent: VariableDeclaration | ParameterDeclaration;
|
||||
parent: SequenceMeta;
|
||||
sequence: TaggedSequence;
|
||||
resources: ResourceIndex;
|
||||
onChange: OnChange;
|
||||
|
@ -32,88 +24,7 @@ export interface ParentVariableFormProps {
|
|||
export const PARENT =
|
||||
({ value: "parent", label: "Parent", headingId: "parameter" });
|
||||
|
||||
const KINDS = ["parameter_declaration", "variable_declaration"];
|
||||
/** Given an array of variable declarations (or undefined), finds the "parent"
|
||||
* special identifier */
|
||||
export const extractParent =
|
||||
(list?: ScopeDeclarationBodyItem[]): ScopeDeclarationBodyItem | undefined => {
|
||||
const p = (list ? list : []).filter(x => {
|
||||
const isParent = x.args.label === "parent";
|
||||
const isVar = KINDS.includes(x.kind);
|
||||
return isVar && isParent;
|
||||
})[0];
|
||||
switch (p && p.kind) {
|
||||
case "variable_declaration":
|
||||
case "parameter_declaration":
|
||||
return p;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/** Takes a sequence and data_value. Turn the data_value into the sequence's new
|
||||
* `parent` variable. This is a _pure function_. */
|
||||
export const setParent =
|
||||
(sequence: TaggedSequence, data_value: CeleryVariable) => {
|
||||
const nextSeq: typeof sequence.body = defensiveClone(sequence.body);
|
||||
switch (data_value.kind) {
|
||||
case "tool":
|
||||
case "point":
|
||||
case "coordinate":
|
||||
nextSeq.args.locals = {
|
||||
kind: "scope_declaration",
|
||||
args: {},
|
||||
body: [
|
||||
{
|
||||
kind: "variable_declaration",
|
||||
args: {
|
||||
label: "parent",
|
||||
data_value
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
break;
|
||||
case "parameter_declaration":
|
||||
nextSeq.args.locals = {
|
||||
kind: "scope_declaration",
|
||||
args: {},
|
||||
body: [{
|
||||
kind: "parameter_declaration",
|
||||
args: { label: "parent", data_type: "point" }
|
||||
}]
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error("Bad kind in setParent(): " + data_value.kind);
|
||||
}
|
||||
return nextSeq;
|
||||
};
|
||||
|
||||
/** If variable is a coordinate, just use the coordinates. */
|
||||
export const guessFromDataType =
|
||||
(x: DataValue): Vector3 | undefined => (x.kind === "coordinate") ?
|
||||
x.args : undefined;
|
||||
|
||||
/** GLORIOUS hack: We spend a *lot* of time in the sequence editor looking up
|
||||
* resource x/y/z. It's resource intensive and often hard to understand.
|
||||
* Instead of adding more selectors and complexity, we make a "best effort"
|
||||
* attempt to read the resource's `x`, `y`, `z` that are cached (as strings)
|
||||
* in the drop down label.
|
||||
*
|
||||
* String manipulation is bad, but I think it is warranted here: */
|
||||
export const guessVecFromLabel =
|
||||
(label: string): Vector3 | undefined => {
|
||||
const step1 = label
|
||||
.trim()
|
||||
.replace(")", "")
|
||||
.replace(/^\s+|\s+$/g, "")
|
||||
.split(/\(|\,/);
|
||||
const vec = step1
|
||||
.slice(Math.max(step1.length - 3, 1))
|
||||
.map(x => parseInt(x, 10))
|
||||
.filter(x => !isNaN(x));
|
||||
|
||||
return (vec.length === 3) ?
|
||||
{ x: vec[0], y: vec[1], z: vec[2] } : undefined;
|
||||
(i: ResourceIndex, uuid: string): SequenceMeta | undefined => {
|
||||
return (i.sequenceMetas[uuid] || {}).parent;
|
||||
};
|
||||
|
|
|
@ -96,11 +96,12 @@ const SequenceHeader = (props: SequenceHeaderProps) => {
|
|||
export class SequenceEditorMiddleActive extends
|
||||
React.Component<ActiveMiddleProps, {}> {
|
||||
get stepSectionHeight() {
|
||||
const { resources, sequence } = this.props;
|
||||
const variable = this.props.shouldDisplay(Feature.variables)
|
||||
? !!extractParent(this.props.sequence.body.args.locals.body)
|
||||
: false;
|
||||
? !!extractParent(resources, sequence.uuid) : false;
|
||||
return `calc(100vh - ${variable ? "38" : "25"}rem)`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { dispatch, sequence } = this.props;
|
||||
return <div className="sequence-editor-content">
|
||||
|
|
Loading…
Reference in New Issue