Farmbot-Web-App/frontend/farmware/farmware_list.tsx

135 lines
4.5 KiB
TypeScript

import * as React from "react";
import { urlFriendly } from "../util";
import { Actions } from "../constants";
import { Farmwares } from "./interfaces";
import { getDevice } from "../device";
import { commandErr } from "../devices/actions";
import { FarmwareConfigMenu } from "./farmware_config_menu";
import { every, Dictionary } from "lodash";
import { Popover, Position } from "@blueprintjs/core";
import { Link } from "../link";
import { ShouldDisplay, Feature } from "../devices/interfaces";
import { initSave } from "../api/crud";
import { TaggedFarmwareInstallation } from "farmbot";
import { t } from "../i18next_wrapper";
import { getFormattedFarmwareName } from "./index";
const DISPLAY_NAMES: Dictionary<string> = {
"Photos": t("Photos"),
"Camera Calibration": t("Camera Calibration"),
"Weed Detector": t("Weed Detector"),
};
/** Farmware list links: selected or unselected. */
const farmwareListItem = (dispatch: Function, current: string | undefined) =>
(farmwareName: string) => {
const click = () => dispatch({
type: Actions.SELECT_FARMWARE,
payload: farmwareName
});
const selected = (farmwareName == getFormattedFarmwareName(current || ""))
|| (!current && farmwareName == "Photos")
? "selected" : "";
const displayName = Object.keys(DISPLAY_NAMES).includes(farmwareName)
? DISPLAY_NAMES[farmwareName]
: farmwareName;
return <Link
to={`/app/farmware/${urlFriendly(farmwareName)}`}
key={farmwareName}
onClick={click}>
<div className={`farmware-list-items ${selected}`}>
<p>{displayName}</p>
</div>
</Link>;
};
export interface FarmwareListProps {
current: string | undefined;
dispatch: Function;
farmwares: Farmwares;
showFirstParty: boolean;
firstPartyFarmwareNames: string[];
shouldDisplay: ShouldDisplay;
installations: TaggedFarmwareInstallation[];
}
interface FarmwareListState {
packageUrl: string;
}
export class FarmwareList
extends React.Component<FarmwareListProps, FarmwareListState> {
state: FarmwareListState = { packageUrl: "" };
clearUrl = () => this.setState({ packageUrl: "" });
install = () => {
const url = this.state.packageUrl;
if (url) {
this.props.shouldDisplay(Feature.api_farmware_installations)
? this.props.dispatch(initSave("FarmwareInstallation",
{ url, package: undefined, package_error: undefined }))
.then(this.clearUrl)
: getDevice()
.installFarmware(url)
.then(this.clearUrl)
.catch(commandErr("Farmware installation"));
} else {
alert(t("Enter a URL"));
}
}
firstPartyFarmwaresPresent = (firstPartyList: string[] | undefined) => {
const farmwareList = Object.values(this.props.farmwares).map(x => x.name);
const allPresent = every(firstPartyList, fw => farmwareList.includes(fw));
return allPresent;
}
render() {
const { current, dispatch, farmwares, showFirstParty, firstPartyFarmwareNames
} = this.props;
const listed1stPartyNames =
["take-photo", "camera-calibration", "plant-detection"];
const farmwareNames = Object.values(farmwares).map(fw => fw.name)
.filter(x => showFirstParty || !firstPartyFarmwareNames.includes(x))
.filter(x => !listed1stPartyNames.includes(x));
return <div className="farmware-list-panel-contents">
<div className="farmware-settings-menu">
<Popover position={Position.BOTTOM_RIGHT}>
<i className="fa fa-gear dark" />
<FarmwareConfigMenu
show={this.props.showFirstParty}
shouldDisplay={this.props.shouldDisplay}
dispatch={this.props.dispatch}
firstPartyFwsInstalled={
this.firstPartyFarmwaresPresent(
this.props.firstPartyFarmwareNames)} />
</Popover>
</div>
{Object.keys(DISPLAY_NAMES).map(farmwareListItem(dispatch, current))}
<hr />
<label>
{t("My Farmware")}
</label>
{farmwareNames.map(farmwareListItem(dispatch, current))}
<hr />
<label>
{t("Install new Farmware")}
</label>
<fieldset>
<input type="url" name="url"
placeholder={"https://...."}
value={this.state.packageUrl || ""}
onChange={e => this.setState({ packageUrl: e.currentTarget.value })} />
<button
className="fb-button green"
title={t("install Farmware")}
onClick={this.install}>
{t("Install")}
</button>
</fieldset>
</div>;
}
}