2019-01-13 17:16:22 -07:00
|
|
|
import * as React from "react";
|
2019-06-04 16:07:52 -06:00
|
|
|
import { Row, Col, FBSelect, BlurableInput, DropDownItem } from "../../ui";
|
2019-01-16 18:51:25 -07:00
|
|
|
import { locationFormList, NO_VALUE_SELECTED_DDI } from "./location_form_list";
|
2019-02-22 19:09:40 -07:00
|
|
|
import { convertDDItoVariable } from "../locals_list/handle_select";
|
2019-01-13 17:16:22 -07:00
|
|
|
import {
|
2019-02-22 19:09:40 -07:00
|
|
|
LocationFormProps, PARENT, AllowedVariableNodes, VariableNode,
|
2019-01-13 17:16:22 -07:00
|
|
|
} from "../locals_list/locals_list_support";
|
|
|
|
import { defensiveClone } from "../../util/util";
|
2019-02-22 19:09:40 -07:00
|
|
|
import { Xyz } from "farmbot";
|
2019-01-13 17:16:22 -07:00
|
|
|
import {
|
|
|
|
determineVector, determineDropdown, determineEditable, SequenceMeta
|
|
|
|
} from "../../resources/sequence_meta";
|
|
|
|
import { ResourceIndex, UUID } from "../../resources/interfaces";
|
|
|
|
import { Feature } from "../../devices/interfaces";
|
2019-02-22 19:09:40 -07:00
|
|
|
import { DefaultValueForm } from "./default_value_form";
|
2019-04-02 13:59:37 -06:00
|
|
|
import { t } from "../../i18next_wrapper";
|
2019-01-13 17:16:22 -07:00
|
|
|
|
|
|
|
/** For LocationForm coordinate input boxes. */
|
|
|
|
export interface AxisEditProps {
|
|
|
|
axis: Xyz;
|
2019-02-22 19:09:40 -07:00
|
|
|
onChange: (sd: VariableNode) => void;
|
|
|
|
editableVariable: VariableNode;
|
2019-01-13 17:16:22 -07:00
|
|
|
}
|
|
|
|
|
2019-02-22 19:09:40 -07:00
|
|
|
/** Update a ParameterApplication coordinate. */
|
2019-01-13 17:16:22 -07:00
|
|
|
export const manuallyEditAxis = (props: AxisEditProps) =>
|
|
|
|
(e: React.SyntheticEvent<HTMLInputElement>) => {
|
2019-02-22 19:09:40 -07:00
|
|
|
const { axis, onChange, editableVariable } = props;
|
2019-01-13 17:16:22 -07:00
|
|
|
const num = parseFloat(e.currentTarget.value);
|
2019-02-22 19:09:40 -07:00
|
|
|
if (editableVariable.kind !== "parameter_declaration" &&
|
|
|
|
editableVariable.args.data_value.kind === "coordinate") {
|
|
|
|
editableVariable.args.data_value.args[axis] = num;
|
|
|
|
!isNaN(num) && onChange(editableVariable);
|
2019-01-13 17:16:22 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2019-02-22 19:09:40 -07:00
|
|
|
* If a variable with a matching label exists in local parameter applications
|
2019-01-13 17:16:22 -07:00
|
|
|
* (step body, etc.), use it instead of the one in scope declarations.
|
|
|
|
*/
|
2019-02-22 19:09:40 -07:00
|
|
|
const maybeUseStepData = ({ resources, bodyVariables, variable, uuid }: {
|
2019-01-13 17:16:22 -07:00
|
|
|
resources: ResourceIndex,
|
2019-02-22 19:09:40 -07:00
|
|
|
bodyVariables: VariableNode[] | undefined,
|
2019-01-13 17:16:22 -07:00
|
|
|
variable: SequenceMeta,
|
|
|
|
uuid: UUID,
|
|
|
|
}): SequenceMeta => {
|
2019-02-22 19:09:40 -07:00
|
|
|
if (bodyVariables) {
|
|
|
|
const executeStepData = bodyVariables
|
2019-01-13 17:16:22 -07:00
|
|
|
.filter(v => v.args.label === variable.celeryNode.args.label)[0];
|
|
|
|
if (executeStepData) {
|
|
|
|
return {
|
|
|
|
celeryNode: executeStepData,
|
|
|
|
vector: determineVector(executeStepData, resources, uuid),
|
2019-06-04 16:07:52 -06:00
|
|
|
dropdown: determineDropdown(executeStepData, resources, uuid),
|
2019-01-13 17:16:22 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return variable;
|
|
|
|
};
|
|
|
|
|
2019-06-04 16:07:52 -06:00
|
|
|
const listLabelDDI = (ddi: DropDownItem) => {
|
|
|
|
const newDDI = Object.assign({}, ddi);
|
|
|
|
newDDI.label = ddi.isNull ? t("Location Variable - Add new") : newDDI.label;
|
|
|
|
return newDDI;
|
|
|
|
};
|
|
|
|
|
|
|
|
const selectedLabelDDI = (ddi: DropDownItem, override?: string) => {
|
|
|
|
const newDDI = Object.assign({}, ddi);
|
|
|
|
newDDI.label = (ddi.value === "parameter_declaration" && override)
|
|
|
|
? override : newDDI.label;
|
|
|
|
return newDDI;
|
|
|
|
};
|
|
|
|
|
2019-01-13 17:16:22 -07:00
|
|
|
/**
|
|
|
|
* Form with an "import from" dropdown and coordinate display/input boxes.
|
|
|
|
* Can be used to set a specific value, import a value, or declare a variable.
|
|
|
|
*/
|
|
|
|
export const LocationForm =
|
|
|
|
(props: LocationFormProps) => {
|
|
|
|
const {
|
2019-02-22 19:09:40 -07:00
|
|
|
sequenceUuid, resources, onChange, bodyVariables, variable,
|
2019-06-04 16:07:52 -06:00
|
|
|
locationDropdownKey, allowedVariableNodes, disallowGroups, listVarLabel
|
2019-01-13 17:16:22 -07:00
|
|
|
} = props;
|
|
|
|
const { celeryNode, dropdown, vector } =
|
|
|
|
maybeUseStepData({
|
2019-02-22 19:09:40 -07:00
|
|
|
resources, bodyVariables, variable, uuid: sequenceUuid
|
2019-01-13 17:16:22 -07:00
|
|
|
});
|
|
|
|
/** For disabling coordinate input boxes when using external data. */
|
|
|
|
const isDisabled = !determineEditable(celeryNode);
|
|
|
|
const variableListItems = (props.shouldDisplay(Feature.variables) &&
|
2019-06-04 16:07:52 -06:00
|
|
|
allowedVariableNodes !== AllowedVariableNodes.variable)
|
|
|
|
? [PARENT(listVarLabel || listLabelDDI(dropdown).label)]
|
|
|
|
: [];
|
2019-03-13 13:05:54 -06:00
|
|
|
const displayGroups = props.shouldDisplay(Feature.loops) && !disallowGroups;
|
|
|
|
const list = locationFormList(resources, variableListItems, displayGroups);
|
2019-01-13 17:16:22 -07:00
|
|
|
/** Variable name. */
|
|
|
|
const { label } = celeryNode.args;
|
2019-02-22 19:09:40 -07:00
|
|
|
const editableVariable = defensiveClone(celeryNode);
|
|
|
|
const axisPartialProps = { onChange, editableVariable };
|
|
|
|
const formTitleWithType =
|
|
|
|
props.hideVariableLabel ? t("Location") : `${label} (${t("Location")})`;
|
|
|
|
const formTitle = props.hideTypeLabel ? label : formTitleWithType;
|
2019-01-13 17:16:22 -07:00
|
|
|
return <div className="location-form">
|
2019-04-09 19:32:18 -06:00
|
|
|
<div className="location-form-header">
|
|
|
|
<label>{formTitle}</label>
|
|
|
|
{props.collapsible &&
|
|
|
|
<i className={`fa fa-caret-${props.collapsed ? "down" : "up"}`}
|
|
|
|
onClick={props.toggleVarShow} />}
|
|
|
|
</div>
|
|
|
|
{!props.collapsed &&
|
|
|
|
<div className="location-form-content">
|
|
|
|
<Row>
|
|
|
|
<Col xs={12}>
|
|
|
|
<FBSelect
|
|
|
|
key={locationDropdownKey}
|
|
|
|
list={list}
|
2019-06-04 16:07:52 -06:00
|
|
|
selectedItem={selectedLabelDDI(dropdown, listVarLabel)}
|
2019-04-09 19:32:18 -06:00
|
|
|
customNullLabel={NO_VALUE_SELECTED_DDI().label}
|
|
|
|
onChange={ddi => onChange(convertDDItoVariable({
|
|
|
|
label, allowedVariableNodes
|
|
|
|
})(ddi))} />
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
{vector &&
|
|
|
|
<Row>
|
|
|
|
{["x", "y", "z"].map((axis: Xyz) =>
|
|
|
|
<Col xs={props.width || 4} key={axis}>
|
|
|
|
<label>
|
|
|
|
{t("{{axis}} (mm)", { axis })}
|
|
|
|
</label>
|
|
|
|
<BlurableInput type="number"
|
|
|
|
disabled={isDisabled}
|
|
|
|
onCommit={manuallyEditAxis({ ...axisPartialProps, axis })}
|
|
|
|
name={`location-${axis}`}
|
|
|
|
value={"" + vector[axis]} />
|
|
|
|
</Col>)}
|
|
|
|
</Row>}
|
|
|
|
<DefaultValueForm
|
|
|
|
variableNode={celeryNode}
|
|
|
|
resources={resources}
|
|
|
|
onChange={onChange} />
|
|
|
|
</div>}
|
2019-01-13 17:16:22 -07:00
|
|
|
</div>;
|
|
|
|
};
|