2017-10-05 04:21:06 -06:00
|
|
|
import * as React from "react";
|
2018-06-21 15:04:21 -06:00
|
|
|
import { Col, BlurableInput } from "../ui/index";
|
2019-03-20 14:18:19 -06:00
|
|
|
import { Pair, FarmwareConfig } from "farmbot";
|
2017-10-10 11:59:08 -06:00
|
|
|
import { getDevice } from "../device";
|
2018-11-01 11:17:18 -06:00
|
|
|
import {
|
2020-02-28 09:35:32 -07:00
|
|
|
ShouldDisplay, Feature, SaveFarmwareEnv, UserEnv,
|
2018-11-01 11:17:18 -06:00
|
|
|
} from "../devices/interfaces";
|
2019-02-04 07:32:26 -07:00
|
|
|
import { kebabCase, toString, snakeCase } from "lodash";
|
2019-03-20 14:18:19 -06:00
|
|
|
import { FarmwareManifestInfo } from "./interfaces";
|
2019-04-02 13:59:37 -06:00
|
|
|
import { t } from "../i18next_wrapper";
|
2017-10-05 04:21:06 -06:00
|
|
|
|
2018-06-21 15:04:21 -06:00
|
|
|
export interface FarmwareFormProps {
|
2019-03-20 14:18:19 -06:00
|
|
|
farmware: FarmwareManifestInfo;
|
2019-12-27 11:37:54 -07:00
|
|
|
env: UserEnv;
|
2018-11-01 11:17:18 -06:00
|
|
|
shouldDisplay: ShouldDisplay;
|
|
|
|
saveFarmwareEnv: SaveFarmwareEnv;
|
|
|
|
dispatch: Function;
|
2019-04-09 19:15:50 -06:00
|
|
|
botOnline: boolean;
|
2017-10-05 04:21:06 -06:00
|
|
|
}
|
|
|
|
|
2018-05-18 16:34:12 -06:00
|
|
|
/** Namespace a Farmware config with the Farmware name. */
|
|
|
|
export function getConfigEnvName(farmwareName: string, configName: string) {
|
2019-02-04 07:32:26 -07:00
|
|
|
return `${snakeCase(farmwareName)}_${configName}`;
|
2018-05-18 16:34:12 -06:00
|
|
|
}
|
2017-10-10 22:29:12 -06:00
|
|
|
|
2018-06-21 15:04:21 -06:00
|
|
|
/** Farmware description and version info for help text contents. */
|
2019-09-23 12:56:35 -06:00
|
|
|
export function farmwareHelpText(farmware: FarmwareManifestInfo | undefined):
|
|
|
|
string {
|
2018-06-21 15:04:21 -06:00
|
|
|
if (farmware) {
|
|
|
|
const description = farmware.meta.description;
|
|
|
|
const versionString = " (version: " + farmware.meta.version + ")";
|
|
|
|
return description + versionString;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2017-10-10 22:29:12 -06:00
|
|
|
|
2018-06-21 15:04:21 -06:00
|
|
|
/** Return a div that includes all Farmware input fields. */
|
|
|
|
export function ConfigFields(props: {
|
2019-03-20 14:18:19 -06:00
|
|
|
farmware: FarmwareManifestInfo,
|
2018-11-01 11:17:18 -06:00
|
|
|
getValue: (farmwareName: string, currentConfig: FarmwareConfig) => string,
|
|
|
|
shouldDisplay: ShouldDisplay,
|
|
|
|
saveFarmwareEnv: SaveFarmwareEnv,
|
|
|
|
dispatch: Function,
|
2018-06-21 15:04:21 -06:00
|
|
|
}): JSX.Element {
|
|
|
|
|
|
|
|
/** Set a Farmware input value on FBOS. */
|
2018-05-18 16:34:12 -06:00
|
|
|
function inputChange(key: string) {
|
|
|
|
return (e: React.SyntheticEvent<HTMLInputElement>) => {
|
|
|
|
const value = e.currentTarget.value;
|
2018-11-01 11:17:18 -06:00
|
|
|
props.shouldDisplay(Feature.api_farmware_env)
|
|
|
|
? props.dispatch(props.saveFarmwareEnv(key, value))
|
|
|
|
: getDevice().setUserEnv({ [key]: value }).catch(() => { });
|
2018-05-18 16:34:12 -06:00
|
|
|
};
|
2017-10-10 22:29:12 -06:00
|
|
|
}
|
|
|
|
|
2018-06-21 15:04:21 -06:00
|
|
|
const { farmware, getValue } = props;
|
2020-02-28 09:34:28 -07:00
|
|
|
return <div className={"farmware-config-fields"}>
|
2018-06-21 15:04:21 -06:00
|
|
|
{farmware.config.map(config => {
|
|
|
|
const configEnvName =
|
|
|
|
getConfigEnvName(farmware.name, config.name);
|
|
|
|
return <div key={config.name} id={config.name}>
|
|
|
|
<label>{config.label}</label>
|
|
|
|
<BlurableInput type="text"
|
|
|
|
onCommit={inputChange(configEnvName)}
|
|
|
|
value={getValue(farmware.name, config)} />
|
|
|
|
</div>;
|
|
|
|
})}
|
|
|
|
</div>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Render a form with Farmware input fields. */
|
|
|
|
export function FarmwareForm(props: FarmwareFormProps): JSX.Element {
|
|
|
|
|
|
|
|
/** Get a Farmware input value from FBOS. */
|
2017-10-10 22:29:12 -06:00
|
|
|
function getValue(farmwareName: string, currentConfig: FarmwareConfig) {
|
2019-12-27 11:37:54 -07:00
|
|
|
return (env[getConfigEnvName(farmwareName, currentConfig.name)]
|
2019-02-04 07:32:26 -07:00
|
|
|
|| toString(currentConfig.value));
|
2017-10-10 22:29:12 -06:00
|
|
|
}
|
|
|
|
|
2018-06-21 15:04:21 -06:00
|
|
|
/** Execute a Farmware using the provided inputs. */
|
2017-10-10 22:29:12 -06:00
|
|
|
function run(farmwareName: string, config: FarmwareConfig[]) {
|
|
|
|
const pairs = config.map<Pair>((x) => {
|
2018-05-18 16:34:12 -06:00
|
|
|
const label = getConfigEnvName(farmwareName, x.name);
|
2017-10-10 22:29:12 -06:00
|
|
|
const value = getValue(farmwareName, x);
|
|
|
|
return { kind: "pair", args: { value, label } };
|
|
|
|
});
|
2018-04-03 12:24:25 -06:00
|
|
|
getDevice().execScript(farmwareName, pairs).catch(() => { });
|
2017-10-10 22:29:12 -06:00
|
|
|
}
|
|
|
|
|
2019-12-27 11:37:54 -07:00
|
|
|
const { farmware, env } = props;
|
2018-06-21 15:04:21 -06:00
|
|
|
return <Col key={farmware.name}>
|
2019-02-04 07:32:26 -07:00
|
|
|
<div className={kebabCase(farmware.name)}>
|
2018-06-21 15:04:21 -06:00
|
|
|
<button
|
|
|
|
className="fb-button green farmware-button"
|
2019-04-09 19:15:50 -06:00
|
|
|
disabled={!props.botOnline}
|
2020-02-28 09:34:28 -07:00
|
|
|
title={t("Run Farmware")}
|
2018-06-21 15:04:21 -06:00
|
|
|
onClick={() => run(farmware.name, farmware.config)}>
|
|
|
|
{t("Run")}
|
|
|
|
</button>
|
|
|
|
<ConfigFields
|
|
|
|
farmware={farmware}
|
2018-11-01 11:17:18 -06:00
|
|
|
getValue={getValue}
|
|
|
|
shouldDisplay={props.shouldDisplay}
|
|
|
|
saveFarmwareEnv={props.saveFarmwareEnv}
|
|
|
|
dispatch={props.dispatch} />
|
2018-06-21 15:04:21 -06:00
|
|
|
</div>
|
|
|
|
</Col>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Determine if a Farmware has requested inputs. */
|
2019-03-20 14:18:19 -06:00
|
|
|
export function needsFarmwareForm(farmware: FarmwareManifestInfo): Boolean {
|
2020-01-03 13:04:45 -07:00
|
|
|
const needsWidget = farmware.config?.length > 0;
|
2018-06-21 15:04:21 -06:00
|
|
|
return needsWidget;
|
2017-10-05 04:21:06 -06:00
|
|
|
}
|