fix offline overlay

pull/1110/head
gabrielburnworth 2019-02-10 21:10:58 -08:00
parent 4cd23253a7
commit ebf7fed7bf
11 changed files with 86 additions and 28 deletions

View File

@ -576,7 +576,9 @@ ul {
position: relative;
z-index: 10;
opacity: 0.40;
pointer-events: none;
* {
pointer-events: none;
}
&.banner {
&:after {
content: "Not available when device is offline.";

View File

@ -89,6 +89,9 @@
}
.farmware-button {
div {
float: right;
}
p {
float: right;
margin-top: 0.75rem;

View File

@ -1,6 +1,8 @@
import * as React from "react";
import { NetworkState } from "../connectivity/interfaces";
import { SyncStatus } from "farmbot";
import { t } from "i18next";
import { Content } from "../constants";
/** Properties for the <MustBeOnline/> element. */
export interface MBOProps {
@ -23,6 +25,10 @@ export function MustBeOnline(props: MBOProps) {
if ((botUp && netUp) || lockOpen) {
return <div> {children} </div>;
} else {
return <div className={`unavailable ${banner}`}> {children} </div>;
return <div
className={`unavailable ${banner}`}
title={t(Content.NOT_AVAILABLE_WHEN_OFFLINE)}>
{children}
</div>;
}
}

View File

@ -21,7 +21,7 @@ describe("mapStateToProps()", () => {
it("sync status unknown", () => {
const props = mapStateToProps(fakeState());
expect(props.botToMqttStatus).toEqual("up");
expect(props.botToMqttStatus).toEqual("down");
});
it("currentImage undefined", () => {
@ -129,6 +129,15 @@ describe("mapStateToProps()", () => {
const props = mapStateToProps(state);
expect(props.imageJobs).toEqual([]);
});
it("returns bot status", () => {
const state = fakeState();
state.bot.hardware.informational_settings.sync_status = "sync_now";
state.bot.connectivity["bot.mqtt"] = { state: "up", at: "" };
const props = mapStateToProps(state);
expect(props.syncStatus).toEqual("sync_now");
expect(props.botToMqttStatus).toEqual("up");
});
});
describe("saveOrEditFarmwareEnv()", () => {

View File

@ -28,11 +28,19 @@ export class CameraCalibration extends
render() {
return <div className="weed-detector">
<button
onClick={this.props.dispatch(calibrate)}
className="fb-button green farmware-button" >
{t("Calibrate")}
</button>
<div className="farmware-button">
<MustBeOnline
syncStatus={this.props.syncStatus}
networkState={this.props.botToMqttStatus}
hideBanner={true}
lockOpen={process.env.NODE_ENV !== "production"}>
<button
onClick={this.props.dispatch(calibrate)}
className="fb-button green farmware-button" >
{t("Calibrate")}
</button>
</MustBeOnline>
</div>
<Row>
<Col sm={12}>
<MustBeOnline

View File

@ -23,6 +23,8 @@ describe("<Photos/>", () => {
dispatch: jest.fn(),
timeOffset: 0,
imageJobs: [],
botToMqttStatus: "up",
syncStatus: "synced",
});
it("shows photo", () => {

View File

@ -1,4 +1,5 @@
import { TaggedImage, JobProgress } from "farmbot";
import { TaggedImage, JobProgress, SyncStatus } from "farmbot";
import { NetworkState } from "../../connectivity/interfaces";
export interface ImageFlipperProps {
onFlip(uuid: string | undefined): void;
@ -18,4 +19,14 @@ export interface PhotosProps {
currentImage: TaggedImage | undefined;
timeOffset: number;
imageJobs: JobProgress[];
botToMqttStatus: NetworkState;
syncStatus: SyncStatus | undefined;
}
export interface PhotoButtonsProps {
takePhoto: () => void,
deletePhoto: () => void,
imageJobs: JobProgress[],
botToMqttStatus: NetworkState;
syncStatus: SyncStatus | undefined;
}

View File

@ -3,7 +3,7 @@ import moment from "moment";
import { t } from "i18next";
import { success, error } from "farmbot-toastr";
import { ImageFlipper } from "./image_flipper";
import { PhotosProps } from "./interfaces";
import { PhotosProps, PhotoButtonsProps } from "./interfaces";
import { getDevice } from "../../device";
import { Content } from "../../constants";
import { selectImage } from "./actions";
@ -12,8 +12,9 @@ import { destroy } from "../../api/crud";
import {
downloadProgress
} from "../../devices/components/fbos_settings/os_update_button";
import { JobProgress, TaggedImage } from "farmbot";
import { TaggedImage } from "farmbot";
import { startCase } from "lodash";
import { MustBeOnline } from "../../devices/must_be_online";
interface MetaInfoProps {
/** Default conversion is `attr_name ==> Attr Name`.
@ -48,18 +49,20 @@ const PhotoMetaData = ({ image }: { image: TaggedImage | undefined }) =>
obj={{ image: t("No meta data.") }} />}
</div>;
const PhotoButtons = (props: {
takePhoto: () => void,
deletePhoto: () => void,
imageJobs: JobProgress[]
}) => {
const PhotoButtons = (props: PhotoButtonsProps) => {
const imageUploadJobProgress = downloadProgress(props.imageJobs[0]);
return <div className="farmware-button">
<button
className="fb-button green"
onClick={props.takePhoto}>
{t("Take Photo")}
</button>
<MustBeOnline
syncStatus={props.syncStatus}
networkState={props.botToMqttStatus}
hideBanner={true}
lockOpen={process.env.NODE_ENV !== "production"}>
<button
className="fb-button green"
onClick={props.takePhoto}>
{t("Take Photo")}
</button>
</MustBeOnline>
<button
className="fb-button red"
onClick={props.deletePhoto}>
@ -115,6 +118,8 @@ export class Photos extends React.Component<PhotosProps, {}> {
render() {
return <div className="photos">
<PhotoButtons
syncStatus={this.props.syncStatus}
botToMqttStatus={this.props.botToMqttStatus}
takePhoto={this.takePhoto}
deletePhoto={this.deletePhoto}
imageJobs={this.props.imageJobs} />

View File

@ -119,6 +119,8 @@ export class FarmwarePage extends React.Component<FarmwareProps, {}> {
case "take_photo":
case "photos":
return <Photos
syncStatus={this.props.syncStatus}
botToMqttStatus={this.props.botToMqttStatus}
timeOffset={this.props.timeOffset}
dispatch={this.props.dispatch}
images={this.props.images}

View File

@ -112,17 +112,21 @@ export function mapStateToProps(props: Everything): FarmwareProps {
.reverse()
.value();
const bot2mqtt = props.bot.connectivity["bot.mqtt"];
const botToMqttStatus = bot2mqtt ? bot2mqtt.state : "down";
const syncStatus = props.bot.hardware.informational_settings.sync_status;
return {
timeOffset: maybeGetTimeOffset(props.resources.index),
currentFarmware,
farmwares,
botToMqttStatus: "up",
botToMqttStatus,
env: prepopulateEnv(env),
user_env: env,
dispatch: props.dispatch,
currentImage,
images,
syncStatus: "synced",
syncStatus,
webAppConfig: conf ? conf.body : {},
firstPartyFarmwareNames,
shouldDisplay,

View File

@ -56,11 +56,17 @@ export class WeedDetector
render() {
return <div className="weed-detector">
<div className="farmware-button">
<button
onClick={this.props.dispatch(test)}
className="fb-button green">
{t("detect weeds")}
</button>
<MustBeOnline
syncStatus={this.props.syncStatus}
networkState={this.props.botToMqttStatus}
hideBanner={true}
lockOpen={process.env.NODE_ENV !== "production"}>
<button
onClick={this.props.dispatch(test)}
className="fb-button green">
{t("detect weeds")}
</button>
</MustBeOnline>
<button
onClick={this.clearWeeds}
className="fb-button red">