214 lines
7.4 KiB
TypeScript
214 lines
7.4 KiB
TypeScript
import * as React from "react";
|
|
import { cloneDeep, capitalize } from "lodash";
|
|
import { Row, Col, FBSelect, DropDownItem } from "../../../ui";
|
|
import {
|
|
AddEqCriteria, toggleEqCriteria, editCriteria, AddNumberCriteria,
|
|
POINTER_TYPE_DDI_LOOKUP, AddStringCriteria,
|
|
CRITERIA_TYPE_DDI_LOOKUP, toggleStringCriteria
|
|
} from ".";
|
|
import {
|
|
EqCriteriaSelectionProps, NumberCriteriaProps,
|
|
CriteriaSelectionProps, LocationSelectionProps, GroupCriteriaProps,
|
|
AddCriteriaState,
|
|
DEFAULT_CRITERIA
|
|
} from "./interfaces";
|
|
import { t } from "../../../i18next_wrapper";
|
|
import { PointGroup } from "farmbot/dist/resources/api_resources";
|
|
import { PLANT_STAGE_DDI_LOOKUP } from "../../plants/edit_plant_status";
|
|
|
|
export class EqCriteriaSelection<T extends string | number>
|
|
extends React.Component<EqCriteriaSelectionProps<T>> {
|
|
render() {
|
|
const { criteriaField, criteriaKey, group, dispatch } = this.props;
|
|
return <div className={`${this.props.type}-eq-criteria`}>
|
|
<AddEqCriteria<T> group={group} dispatch={dispatch}
|
|
type={this.props.type} criteriaField={criteriaField}
|
|
criteriaKey={criteriaKey} />
|
|
{criteriaField && Object.entries(criteriaField)
|
|
.map(([key, values]: [string, T[]], keyIndex) =>
|
|
values && values.length > 0 &&
|
|
<div key={keyIndex}>
|
|
<label>{key}</label>
|
|
{values.map((value, valueIndex) =>
|
|
<Row key={"" + keyIndex + valueIndex}>
|
|
<Col xs={9}>
|
|
<input
|
|
disabled={true}
|
|
value={value} />
|
|
</Col>
|
|
<Col xs={2}>
|
|
<button className="fb-button red" onClick={() => {
|
|
const tempCriteriaField = cloneDeep(criteriaField);
|
|
toggleEqCriteria<T>(tempCriteriaField)(key, value);
|
|
dispatch(editCriteria(group, {
|
|
[criteriaKey]: tempCriteriaField
|
|
}));
|
|
}}>
|
|
<i className="fa fa-minus" />
|
|
</button>
|
|
</Col>
|
|
</Row>)}
|
|
</div>)}
|
|
</div>;
|
|
}
|
|
}
|
|
|
|
export const NumberCriteriaSelection = (props: NumberCriteriaProps) => {
|
|
const criteriaField = props.criteria[props.criteriaKey];
|
|
return <div className={"number-gt-lt-criteria"}>
|
|
<AddNumberCriteria {...props} />
|
|
{criteriaField && Object.entries(criteriaField)
|
|
.map(([key, value], keyIndex) =>
|
|
<div key={keyIndex}>
|
|
<Row>
|
|
<Col xs={4}>
|
|
<p>{key}</p>
|
|
</Col>
|
|
<Col xs={1}>
|
|
{props.criteriaKey == "number_gt" ? ">" : "<"}
|
|
</Col>
|
|
<Col xs={4}>
|
|
<input key={"" + keyIndex}
|
|
disabled={true}
|
|
value={value} />
|
|
</Col>
|
|
<Col xs={2}>
|
|
<button className="fb-button red" onClick={() => {
|
|
const tempNumberCriteria = cloneDeep(criteriaField);
|
|
delete tempNumberCriteria[key];
|
|
props.dispatch(editCriteria(props.group, {
|
|
[props.criteriaKey]: tempNumberCriteria
|
|
}));
|
|
}}>
|
|
<i className="fa fa-minus" />
|
|
</button>
|
|
</Col>
|
|
</Row>
|
|
</div>)}
|
|
</div>;
|
|
};
|
|
|
|
const DAY_OPERATOR_DDI_LOOKUP = (): { [x: string]: DropDownItem } => ({
|
|
["<"]: { label: t("less than"), value: "<" },
|
|
[">"]: { label: t("greater than"), value: ">" },
|
|
});
|
|
|
|
export const DaySelection = (props: CriteriaSelectionProps) => {
|
|
const { group, criteria, dispatch } = props;
|
|
const dayCriteria = criteria.day || cloneDeep(DEFAULT_CRITERIA.day);
|
|
return <div className="day-criteria">
|
|
<label>{t("Age selection")}</label>
|
|
<Row>
|
|
<Col xs={5}>
|
|
<FBSelect key={JSON.stringify(criteria)}
|
|
list={[DAY_OPERATOR_DDI_LOOKUP()["<"],
|
|
DAY_OPERATOR_DDI_LOOKUP()[">"]]}
|
|
selectedItem={DAY_OPERATOR_DDI_LOOKUP()[dayCriteria.op]}
|
|
onChange={ddi => dispatch(editCriteria(group, {
|
|
day: {
|
|
days_ago: dayCriteria.days_ago,
|
|
op: ddi.value as PointGroup["criteria"]["day"]["op"]
|
|
}
|
|
}))} />
|
|
</Col>
|
|
<Col xs={3}>
|
|
<input type="number" value={dayCriteria.days_ago} onChange={e => {
|
|
const { op } = dayCriteria;
|
|
const days_ago = parseInt(e.currentTarget.value);
|
|
dispatch(editCriteria(group, { day: { days_ago, op } }));
|
|
}} />
|
|
</Col>
|
|
<Col xs={4}>
|
|
<p>{t("days old")}</p>
|
|
</Col>
|
|
</Row>
|
|
</div>;
|
|
};
|
|
|
|
export const LocationSelection = (props: LocationSelectionProps) => {
|
|
const { group, criteria, dispatch } = props;
|
|
const gtCriteria = criteria.number_gt || {};
|
|
const ltCriteria = criteria.number_lt || {};
|
|
return <div className="location-criteria">
|
|
<label>{t("Location selection")}</label>
|
|
{["x", "y"].map(axis =>
|
|
<Row key={axis}>
|
|
<Col xs={4}>
|
|
<input key={JSON.stringify(gtCriteria)}
|
|
type="number"
|
|
defaultValue={gtCriteria[axis]}
|
|
onBlur={e => {
|
|
const tempGtCriteria = cloneDeep(gtCriteria);
|
|
tempGtCriteria[axis] = parseInt(e.currentTarget.value);
|
|
dispatch(editCriteria(group, { number_gt: tempGtCriteria }));
|
|
}} />
|
|
</Col>
|
|
<Col xs={1}>
|
|
<p>{"<"}</p>
|
|
</Col>
|
|
<Col xs={1}>
|
|
<label>{axis}</label>
|
|
</Col>
|
|
<Col xs={1}>
|
|
<p>{"<"}</p>
|
|
</Col>
|
|
<Col xs={4}>
|
|
<input key={JSON.stringify(ltCriteria)}
|
|
type="number"
|
|
defaultValue={ltCriteria[axis]}
|
|
onBlur={e => {
|
|
const tempLtCriteria = cloneDeep(ltCriteria);
|
|
tempLtCriteria[axis] = parseInt(e.currentTarget.value);
|
|
dispatch(editCriteria(group, { number_lt: tempLtCriteria }));
|
|
}} />
|
|
</Col>
|
|
</Row>)}
|
|
</div>;
|
|
};
|
|
|
|
export class AddCriteria
|
|
extends React.Component<GroupCriteriaProps, AddCriteriaState> {
|
|
|
|
labelLookup = (key: string, value: string) => {
|
|
switch (key) {
|
|
case "openfarm_slug":
|
|
return capitalize(value);
|
|
case "pointer_type":
|
|
return POINTER_TYPE_DDI_LOOKUP()[value].label;
|
|
case "plant_stage":
|
|
return PLANT_STAGE_DDI_LOOKUP()[value].label;
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const { props } = this;
|
|
const stringCriteria = this.props.group.body.criteria?.string_eq || {};
|
|
const displayedCriteria = Object.entries(stringCriteria)
|
|
.filter(([key, _values]) =>
|
|
["openfarm_slug", "pointer_type", "plant_stage"].includes(key));
|
|
return <div className={"add-criteria"}>
|
|
<AddStringCriteria
|
|
group={props.group} dispatch={props.dispatch} slugs={props.slugs} />
|
|
{displayedCriteria.map(([key, values]) =>
|
|
values && values.map((value, index) =>
|
|
<div key={key + index} className={"criteria-string"}>
|
|
<Row>
|
|
<Col xs={5}>
|
|
<input value={CRITERIA_TYPE_DDI_LOOKUP()[key].label}
|
|
disabled={true} />
|
|
</Col>
|
|
<Col xs={5}>
|
|
<input value={this.labelLookup(key, value)} disabled={true} />
|
|
</Col>
|
|
<Col xs={2}>
|
|
<button className="fb-button red" onClick={() => props.dispatch(
|
|
toggleStringCriteria(props.group, key, value))}>
|
|
<i className="fa fa-minus" />
|
|
</button>
|
|
</Col>
|
|
</Row>
|
|
</div>))}
|
|
</div>;
|
|
}
|
|
}
|