114 lines
3.8 KiB
TypeScript
114 lines
3.8 KiB
TypeScript
import * as React from "react";
|
|
import { Col, BlurableInput } from "../ui/index";
|
|
import { Pair, FarmwareConfig } from "farmbot";
|
|
import { getDevice } from "../device";
|
|
import {
|
|
ShouldDisplay, Feature, SaveFarmwareEnv, UserEnv
|
|
} from "../devices/interfaces";
|
|
import { kebabCase, toString, snakeCase } from "lodash";
|
|
import { FarmwareManifestInfo } from "./interfaces";
|
|
import { t } from "../i18next_wrapper";
|
|
|
|
export interface FarmwareFormProps {
|
|
farmware: FarmwareManifestInfo;
|
|
user_env: UserEnv;
|
|
shouldDisplay: ShouldDisplay;
|
|
saveFarmwareEnv: SaveFarmwareEnv;
|
|
dispatch: Function;
|
|
botOnline: boolean;
|
|
}
|
|
|
|
/** Namespace a Farmware config with the Farmware name. */
|
|
export function getConfigEnvName(farmwareName: string, configName: string) {
|
|
return `${snakeCase(farmwareName)}_${configName}`;
|
|
}
|
|
|
|
/** Farmware description and version info for help text contents. */
|
|
export function farmwareHelpText(farmware: FarmwareManifestInfo | undefined):
|
|
string {
|
|
if (farmware) {
|
|
const description = farmware.meta.description;
|
|
const versionString = " (version: " + farmware.meta.version + ")";
|
|
return description + versionString;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/** Return a div that includes all Farmware input fields. */
|
|
export function ConfigFields(props: {
|
|
farmware: FarmwareManifestInfo,
|
|
getValue: (farmwareName: string, currentConfig: FarmwareConfig) => string,
|
|
shouldDisplay: ShouldDisplay,
|
|
saveFarmwareEnv: SaveFarmwareEnv,
|
|
dispatch: Function,
|
|
}): JSX.Element {
|
|
|
|
/** Set a Farmware input value on FBOS. */
|
|
function inputChange(key: string) {
|
|
return (e: React.SyntheticEvent<HTMLInputElement>) => {
|
|
const value = e.currentTarget.value;
|
|
props.shouldDisplay(Feature.api_farmware_env)
|
|
? props.dispatch(props.saveFarmwareEnv(key, value))
|
|
: getDevice().setUserEnv({ [key]: value }).catch(() => { });
|
|
};
|
|
}
|
|
|
|
const { farmware, getValue } = props;
|
|
return <div>
|
|
{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. */
|
|
function getValue(farmwareName: string, currentConfig: FarmwareConfig) {
|
|
return (user_env[getConfigEnvName(farmwareName, currentConfig.name)]
|
|
|| toString(currentConfig.value));
|
|
}
|
|
|
|
/** Execute a Farmware using the provided inputs. */
|
|
function run(farmwareName: string, config: FarmwareConfig[]) {
|
|
const pairs = config.map<Pair>((x) => {
|
|
const label = getConfigEnvName(farmwareName, x.name);
|
|
const value = getValue(farmwareName, x);
|
|
return { kind: "pair", args: { value, label } };
|
|
});
|
|
getDevice().execScript(farmwareName, pairs).catch(() => { });
|
|
}
|
|
|
|
const { farmware, user_env } = props;
|
|
return <Col key={farmware.name}>
|
|
<div className={kebabCase(farmware.name)}>
|
|
<button
|
|
className="fb-button green farmware-button"
|
|
disabled={!props.botOnline}
|
|
onClick={() => run(farmware.name, farmware.config)}>
|
|
{t("Run")}
|
|
</button>
|
|
<ConfigFields
|
|
farmware={farmware}
|
|
getValue={getValue}
|
|
shouldDisplay={props.shouldDisplay}
|
|
saveFarmwareEnv={props.saveFarmwareEnv}
|
|
dispatch={props.dispatch} />
|
|
</div>
|
|
</Col>;
|
|
}
|
|
|
|
/** Determine if a Farmware has requested inputs. */
|
|
export function needsFarmwareForm(farmware: FarmwareManifestInfo): Boolean {
|
|
const needsWidget = farmware.config && farmware.config.length > 0;
|
|
return needsWidget;
|
|
}
|