import * as React from "react"; import { connect } from "react-redux"; import { GardenMap } from "./map/garden_map"; import { Props, State, BotOriginQuadrant, isBotOriginQuadrant } from "./interfaces"; import { mapStateToProps } from "./state_to_props"; import { Plants } from "./plants/plant_inventory"; import { GardenMapLegend } from "./map/legend/garden_map_legend"; import { NumericSetting, BooleanSetting } from "../session_keys"; import { isUndefined, last, isFinite } from "lodash"; import { AxisNumberProperty, BotSize } from "./map/interfaces"; import { getBotSize, round, getPanelStatus, MapPanelStatus, mapPanelClassName, getMapPadding, } from "./map/util"; import { calcZoomLevel, getZoomLevelIndex, saveZoomLevelIndex } from "./map/zoom"; import moment from "moment"; import { DesignerNavTabs } from "./panel_header"; import { setWebAppConfigValue, GetWebAppConfigValue } from "../config_storage/actions"; import { SavedGardenHUD } from "./saved_gardens/saved_gardens"; export const getDefaultAxisLength = (getConfigValue: GetWebAppConfigValue): AxisNumberProperty => { const mapSizeX = parseInt("" + getConfigValue(NumericSetting.map_size_x)); const mapSizeY = parseInt("" + getConfigValue(NumericSetting.map_size_y)); if (isFinite(mapSizeX) && isFinite(mapSizeY)) { return { x: mapSizeX, y: mapSizeY }; } return { x: 2900, y: 1400 }; }; export const getGridSize = (getConfigValue: GetWebAppConfigValue, botSize: BotSize) => { if (getConfigValue(BooleanSetting.dynamic_map)) { // Render the map size according to device axis length. return { x: round(botSize.x.value), y: round(botSize.y.value) }; } // Use a default map size. return getDefaultAxisLength(getConfigValue); }; export const gridOffset: AxisNumberProperty = { x: 50, y: 50 }; export class RawFarmDesigner extends React.Component> { initializeSetting = (key: keyof State, defaultValue: boolean): boolean => { const currentValue = this.props.getConfigValue(key); if (isUndefined(currentValue)) { this.props.dispatch(setWebAppConfigValue(key, defaultValue)); return defaultValue; } else { return !!currentValue; } } getBotOriginQuadrant = (): BotOriginQuadrant => { const value = this.props.getConfigValue(NumericSetting.bot_origin_quadrant); return isBotOriginQuadrant(value) ? value : 2; } getState(): State { const init = this.initializeSetting; return { legend_menu_open: init(BooleanSetting.legend_menu_open, false), show_plants: init(BooleanSetting.show_plants, true), show_points: init(BooleanSetting.show_points, true), show_spread: init(BooleanSetting.show_spread, false), show_farmbot: init(BooleanSetting.show_farmbot, true), show_images: init(BooleanSetting.show_images, false), show_zones: init(BooleanSetting.show_zones, false), show_sensor_readings: init(BooleanSetting.show_sensor_readings, false), bot_origin_quadrant: this.getBotOriginQuadrant(), zoom_level: calcZoomLevel(getZoomLevelIndex(this.props.getConfigValue)), }; } state: State = this.getState(); componentDidMount() { this.updateBotOriginQuadrant(this.state.bot_origin_quadrant)(); this.updateZoomLevel(0)(); } toggle = (key: keyof State) => () => { const newValue = !this.state[key]; this.props.dispatch(setWebAppConfigValue(key, newValue)); this.setState({ [key]: newValue }); } updateBotOriginQuadrant = (payload: BotOriginQuadrant) => () => { this.setState({ bot_origin_quadrant: payload }); this.props.dispatch(setWebAppConfigValue( NumericSetting.bot_origin_quadrant, payload)); } updateZoomLevel = (zoomIncrement: number) => () => { const newIndex = getZoomLevelIndex(this.props.getConfigValue) + zoomIncrement; this.setState({ zoom_level: calcZoomLevel(newIndex) }); saveZoomLevelIndex(this.props.dispatch, newIndex); } childComponent(props: Props) { return this.props.children || React.createElement(Plants, props); } get mapPanelClassName() { return mapPanelClassName(); } render() { const { legend_menu_open, show_plants, show_points, show_spread, show_farmbot, show_images, show_zones, show_sensor_readings, zoom_level } = this.state; const botSize = getBotSize( this.props.botMcuParams, this.props.stepsPerMmXY, getDefaultAxisLength(this.props.getConfigValue)); const stopAtHome = { x: !!this.props.botMcuParams.movement_stop_at_home_x, y: !!this.props.botMcuParams.movement_stop_at_home_y }; const newestImage = this.props.latestImages[0]; const oldestImage = last(this.props.latestImages); const newestDate = newestImage ? newestImage.body.created_at : ""; const toOldest = oldestImage && newestDate ? Math.abs(moment(oldestImage.body.created_at) .diff(moment(newestDate).clone(), "days")) : 1; const imageAgeInfo = { newestDate, toOldest }; const mapPadding = getMapPadding(getPanelStatus()); const padHeightOffset = mapPadding.top - mapPadding.top / zoom_level; return
0} dispatch={this.props.dispatch} timeSettings={this.props.timeSettings} getConfigValue={this.props.getConfigValue} imageAgeInfo={imageAgeInfo} />
; } } export const FarmDesigner = connect(mapStateToProps)(RawFarmDesigner);