2017-08-30 23:12:11 -06:00
|
|
|
import * as React from "react";
|
|
|
|
import { t } from "i18next";
|
2017-07-06 21:26:37 -06:00
|
|
|
import { connect } from "react-redux";
|
2019-02-01 10:35:03 -07:00
|
|
|
import _ from "lodash";
|
2017-07-06 21:26:37 -06:00
|
|
|
import { init, error } from "farmbot-toastr";
|
|
|
|
import { NavBar } from "./nav";
|
2018-05-17 14:12:33 -06:00
|
|
|
import { Everything } from "./interfaces";
|
2017-10-04 23:02:38 -06:00
|
|
|
import { LoadingPlant } from "./loading_plant";
|
2018-01-10 13:08:56 -07:00
|
|
|
import { BotState, Xyz } from "./devices/interfaces";
|
2017-12-28 13:48:03 -07:00
|
|
|
import {
|
2018-05-17 14:12:33 -06:00
|
|
|
ResourceName, TaggedUser, TaggedLog
|
2018-08-01 07:03:35 -06:00
|
|
|
} from "farmbot";
|
2018-05-17 14:12:33 -06:00
|
|
|
import {
|
2017-12-28 13:48:03 -07:00
|
|
|
maybeFetchUser,
|
2018-03-09 02:34:24 -07:00
|
|
|
maybeGetTimeOffset,
|
2017-12-28 13:48:03 -07:00
|
|
|
} from "./resources/selectors";
|
2017-07-06 21:26:37 -06:00
|
|
|
import { HotKeys } from "./hotkeys";
|
2017-07-07 22:23:25 -06:00
|
|
|
import { ControlsPopup } from "./controls_popup";
|
2017-08-30 23:12:11 -06:00
|
|
|
import { Content } from "./constants";
|
2018-04-02 07:17:15 -06:00
|
|
|
import { validBotLocationData, validFwConfig } from "./util";
|
2018-01-10 13:08:56 -07:00
|
|
|
import { BooleanSetting } from "./session_keys";
|
2018-01-20 07:46:44 -07:00
|
|
|
import { getPathArray } from "./history";
|
2018-08-30 19:25:58 -06:00
|
|
|
import { getWebAppConfigValue, GetWebAppConfigValue } from "./config_storage/actions";
|
2018-05-17 14:12:33 -06:00
|
|
|
import { takeSortedLogs } from "./logs/state_to_props";
|
2018-10-22 09:35:44 -06:00
|
|
|
import { FirmwareConfig } from "farmbot/dist/resources/configs/firmware";
|
2018-11-20 10:40:07 -07:00
|
|
|
import { getFirmwareConfig } from "./resources/getters";
|
2017-06-29 12:54:02 -06:00
|
|
|
|
2017-08-30 23:12:11 -06:00
|
|
|
/** Remove 300ms delay on touch devices - https://github.com/ftlabs/fastclick */
|
2019-01-28 09:07:26 -07:00
|
|
|
// const fastClick = require("fastclick");
|
|
|
|
// fastClick.attach(document.body);
|
2017-06-29 12:54:02 -06:00
|
|
|
|
2017-08-30 23:12:11 -06:00
|
|
|
/** For the logger module */
|
2017-06-29 12:54:02 -06:00
|
|
|
init();
|
|
|
|
|
2017-09-08 12:38:46 -06:00
|
|
|
export interface AppProps {
|
2017-06-29 12:54:02 -06:00
|
|
|
dispatch: Function;
|
|
|
|
loaded: ResourceName[];
|
2018-05-17 14:12:33 -06:00
|
|
|
logs: TaggedLog[];
|
2017-06-29 12:54:02 -06:00
|
|
|
user: TaggedUser | undefined;
|
|
|
|
bot: BotState;
|
2017-11-13 10:52:32 -07:00
|
|
|
consistent: boolean;
|
2017-12-28 13:28:44 -07:00
|
|
|
timeOffset: number;
|
2018-01-10 13:08:56 -07:00
|
|
|
axisInversion: Record<Xyz, boolean>;
|
2018-04-12 17:55:38 -06:00
|
|
|
xySwap: boolean;
|
2018-03-09 02:34:24 -07:00
|
|
|
firmwareConfig: FirmwareConfig | undefined;
|
2018-08-08 08:44:12 -06:00
|
|
|
animate: boolean;
|
2018-08-30 19:25:58 -06:00
|
|
|
getConfigValue: GetWebAppConfigValue;
|
2018-10-15 17:23:58 -06:00
|
|
|
tour: string | undefined;
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
|
2017-07-06 21:26:37 -06:00
|
|
|
function mapStateToProps(props: Everything): AppProps {
|
2018-08-08 08:44:12 -06:00
|
|
|
const webAppConfigValue = getWebAppConfigValue(() => props);
|
2017-07-06 21:26:37 -06:00
|
|
|
return {
|
2017-12-28 13:48:03 -07:00
|
|
|
timeOffset: maybeGetTimeOffset(props.resources.index),
|
2017-06-29 12:54:02 -06:00
|
|
|
dispatch: props.dispatch,
|
|
|
|
user: maybeFetchUser(props.resources.index),
|
|
|
|
bot: props.bot,
|
2018-05-17 14:12:33 -06:00
|
|
|
logs: takeSortedLogs(250, props.resources.index),
|
2017-11-13 10:52:32 -07:00
|
|
|
loaded: props.resources.loaded,
|
2017-11-20 12:44:46 -07:00
|
|
|
consistent: !!(props.bot || {}).consistent,
|
2018-01-10 13:08:56 -07:00
|
|
|
axisInversion: {
|
2018-08-08 08:44:12 -06:00
|
|
|
x: !!webAppConfigValue(BooleanSetting.x_axis_inverted),
|
|
|
|
y: !!webAppConfigValue(BooleanSetting.y_axis_inverted),
|
|
|
|
z: !!webAppConfigValue(BooleanSetting.z_axis_inverted),
|
2018-03-09 02:34:24 -07:00
|
|
|
},
|
2018-08-08 08:44:12 -06:00
|
|
|
xySwap: !!webAppConfigValue(BooleanSetting.xy_swap),
|
|
|
|
firmwareConfig: validFwConfig(getFirmwareConfig(props.resources.index)),
|
|
|
|
animate: !webAppConfigValue(BooleanSetting.disable_animations),
|
2018-08-30 19:25:58 -06:00
|
|
|
getConfigValue: webAppConfigValue,
|
2018-10-15 17:23:58 -06:00
|
|
|
tour: props.resources.consumers.help.currentTour,
|
2017-06-29 12:54:02 -06:00
|
|
|
};
|
|
|
|
}
|
2017-09-28 06:23:02 -06:00
|
|
|
/** Time at which the app gives up and asks the user to refresh */
|
|
|
|
const LOAD_TIME_FAILURE_MS = 25000;
|
2017-06-29 12:54:02 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Relational resources that *must* load before app starts.
|
|
|
|
* App will crash at load time if they are not pre-loaded.
|
|
|
|
*/
|
|
|
|
const MUST_LOAD: ResourceName[] = [
|
2017-10-27 07:31:25 -06:00
|
|
|
"Sequence",
|
|
|
|
"Regimen",
|
|
|
|
"FarmEvent",
|
2018-11-05 10:53:08 -07:00
|
|
|
"Point",
|
|
|
|
"Tool" // Sequence editor needs this for rendering.
|
2017-06-29 12:54:02 -06:00
|
|
|
];
|
|
|
|
|
|
|
|
@connect(mapStateToProps)
|
2017-08-29 12:14:53 -06:00
|
|
|
export class App extends React.Component<AppProps, {}> {
|
2018-03-02 08:25:15 -07:00
|
|
|
private get isLoaded() {
|
2017-06-29 12:54:02 -06:00
|
|
|
return (MUST_LOAD.length ===
|
2017-07-06 21:26:37 -06:00
|
|
|
_.intersection(this.props.loaded, MUST_LOAD).length);
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
|
2017-08-30 23:12:11 -06:00
|
|
|
/**
|
|
|
|
* If the sync object takes more than 10s to load, the user will be granted
|
|
|
|
* access into the app, but still warned.
|
|
|
|
*/
|
2017-07-06 21:26:37 -06:00
|
|
|
componentDidMount() {
|
2017-06-29 12:54:02 -06:00
|
|
|
setTimeout(() => {
|
2017-07-06 21:26:37 -06:00
|
|
|
if (!this.isLoaded) {
|
2017-08-30 23:12:11 -06:00
|
|
|
error(t(Content.APP_LOAD_TIMEOUT_MESSAGE), t("Warning"));
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
2017-09-28 06:23:02 -06:00
|
|
|
}, LOAD_TIME_FAILURE_MS);
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
|
2017-07-06 21:26:37 -06:00
|
|
|
render() {
|
2017-08-29 12:14:53 -06:00
|
|
|
const syncLoaded = this.isLoaded;
|
2018-01-20 07:46:44 -07:00
|
|
|
const currentPage = getPathArray()[2];
|
2018-01-23 16:21:44 -07:00
|
|
|
const { location_data, mcu_params } = this.props.bot.hardware;
|
2017-06-29 12:54:02 -06:00
|
|
|
return <div className="app">
|
2017-07-07 00:00:20 -06:00
|
|
|
<HotKeys dispatch={this.props.dispatch} />
|
2017-06-29 12:54:02 -06:00
|
|
|
<NavBar
|
2017-12-28 13:28:44 -07:00
|
|
|
timeOffset={this.props.timeOffset}
|
2017-11-13 10:52:32 -07:00
|
|
|
consistent={this.props.consistent}
|
2017-06-29 12:54:02 -06:00
|
|
|
user={this.props.user}
|
|
|
|
bot={this.props.bot}
|
|
|
|
dispatch={this.props.dispatch}
|
2018-08-30 19:25:58 -06:00
|
|
|
logs={this.props.logs}
|
2018-10-15 17:23:58 -06:00
|
|
|
getConfigValue={this.props.getConfigValue}
|
|
|
|
tour={this.props.tour} />
|
2018-08-08 08:44:12 -06:00
|
|
|
{!syncLoaded && <LoadingPlant animate={this.props.animate} />}
|
2017-07-06 21:26:37 -06:00
|
|
|
{syncLoaded && this.props.children}
|
2018-01-20 07:46:44 -07:00
|
|
|
{!(["controls", "account", "regimens"].includes(currentPage)) &&
|
2017-09-08 12:38:46 -06:00
|
|
|
<ControlsPopup
|
|
|
|
dispatch={this.props.dispatch}
|
2018-01-17 18:13:02 -07:00
|
|
|
axisInversion={this.props.axisInversion}
|
2018-01-23 16:21:44 -07:00
|
|
|
botPosition={validBotLocationData(location_data).position}
|
2018-04-12 19:27:06 -06:00
|
|
|
firmwareSettings={this.props.firmwareConfig || mcu_params}
|
|
|
|
xySwap={this.props.xySwap}
|
|
|
|
arduinoBusy={!!this.props.bot.hardware.informational_settings.busy}
|
|
|
|
stepSize={this.props.bot.stepSize} />}
|
2017-06-29 12:54:02 -06:00
|
|
|
</div>;
|
|
|
|
}
|
|
|
|
}
|