os update updates

pull/1050/head
gabrielburnworth 2018-11-26 19:39:35 -08:00
parent c7e4ee3a0e
commit 654533ae4b
10 changed files with 122 additions and 23 deletions

View File

@ -53,7 +53,7 @@
"css-loader": "^1.0.1",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",
"farmbot": "^6.6.0-rc1",
"farmbot": "^6.6.0",
"farmbot-toastr": "^1.0.3",
"fastclick": "^1.0.6",
"file-loader": "2.0.0",

View File

@ -146,6 +146,7 @@ export class FarmbotOsSettings
osReleaseNotes={this.state.osReleaseNotes}
dispatch={this.props.dispatch}
sourceFbosConfig={sourceFbosConfig}
shouldDisplay={this.props.shouldDisplay}
botOnline={botOnline} />
<AutoUpdateRow
dispatch={this.props.dispatch}

View File

@ -15,6 +15,7 @@ describe("<FarmbotOsRow/>", () => {
sourceFbosConfig: (x) => {
return { value: bot.hardware.configuration[x], consistent: true };
},
shouldDisplay: () => false,
botOnline: false
};
};

View File

@ -6,7 +6,7 @@ jest.mock("../../../../device", () => ({
}));
import * as React from "react";
import { FbosDetails, colorFromTemp } from "../fbos_details";
import { FbosDetails, colorFromTemp, betaReleaseOptIn } from "../fbos_details";
import { shallow, mount } from "enzyme";
import { bot } from "../../../../__test_support__/fake_state/bot";
import { FbosDetailsProps } from "../interfaces";
@ -17,6 +17,7 @@ describe("<FbosDetails/>", () => {
return {
botInfoSettings: bot.hardware.informational_settings,
dispatch: jest.fn(x => x(jest.fn(), fakeState)),
shouldDisplay: () => false,
sourceFbosConfig: x =>
({ value: bot.hardware.configuration[x], consistent: true }),
};
@ -148,6 +149,56 @@ describe("<FbosDetails/>", () => {
});
});
describe("betaReleaseOptIn()", () => {
it("uses `beta_opt_in`: beta enabled", () => {
const result = betaReleaseOptIn({
sourceFbosConfig: () => ({ value: true, consistent: true }),
shouldDisplay: () => false
});
expect(result).toEqual({
betaOptIn: { consistent: true, value: true },
betaOptInValue: true,
update: { beta_opt_in: false }
});
});
it("uses `beta_opt_in`: beta disabled", () => {
const result = betaReleaseOptIn({
sourceFbosConfig: () => ({ value: false, consistent: true }),
shouldDisplay: () => false
});
expect(result).toEqual({
betaOptIn: { consistent: true, value: false },
betaOptInValue: false,
update: { beta_opt_in: true }
});
});
it("uses `update_channel`: beta enabled", () => {
const result = betaReleaseOptIn({
sourceFbosConfig: () => ({ value: "beta", consistent: true }),
shouldDisplay: () => true
});
expect(result).toEqual({
betaOptIn: { consistent: true, value: true },
betaOptInValue: true,
update: { update_channel: "stable" }
});
});
it("uses `update_channel`: beta disabled", () => {
const result = betaReleaseOptIn({
sourceFbosConfig: () => ({ value: "stable", consistent: true }),
shouldDisplay: () => true
});
expect(result).toEqual({
betaOptIn: { consistent: true, value: false },
betaOptInValue: false,
update: { update_channel: "beta" }
});
});
});
describe("colorFromTemp()", () => {
it("temperature is good or none", () => {
expect(colorFromTemp(30)).toEqual("green");

View File

@ -33,6 +33,7 @@ describe("<OsUpdateButton/>", () => {
availableBetaCommit: string | undefined;
betaOptIn: boolean | undefined;
onBeta: boolean | undefined;
update_available?: boolean | undefined;
}
const defaultTestProps = (): TestProps => ({
@ -88,12 +89,15 @@ describe("<OsUpdateButton/>", () => {
testProps: TestProps,
expected: Results) => {
const {
installedVersion, installedCommit, onBeta,
installedVersion, installedCommit, onBeta, update_available,
availableVersion, availableBetaVersion, availableBetaCommit, betaOptIn
} = testProps;
bot.hardware.informational_settings.controller_version = installedVersion;
bot.hardware.informational_settings.commit = installedCommit;
bot.hardware.informational_settings.currently_on_beta = onBeta;
// tslint:disable-next-line:no-any // TODO: fix FBJS
(bot.hardware.informational_settings as any).update_available =
update_available || false;
bot.currentOSVersion = availableVersion;
bot.currentBetaOSVersion = availableBetaVersion;
bot.currentBetaOSCommit = availableBetaCommit;
@ -242,6 +246,14 @@ describe("<OsUpdateButton/>", () => {
testButtonState(testProps, expectedResults);
});
it("handles FBOS update available override", () => {
const testProps = defaultTestProps();
testProps.installedVersion = "3.1.6";
testProps.update_available = true;
const expectedResults = updateNeeded("3.1.6");
testButtonState(testProps, expectedResults);
});
it("calls checkUpdates", () => {
const buttons = mount(<OsUpdateButton {...fakeProps()} />);
const osUpdateButton = buttons.find("button").first();

View File

@ -30,6 +30,7 @@ export function FarmbotOsRow(props: FarmbotOsRowProps) {
<FbosDetails
botInfoSettings={bot.hardware.informational_settings}
dispatch={dispatch}
shouldDisplay={props.shouldDisplay}
sourceFbosConfig={sourceFbosConfig} />
</Popover>
</Col>

View File

@ -6,7 +6,8 @@ import { updateConfig } from "../../actions";
import { last, isNumber } from "lodash";
import { Content } from "../../../constants";
import { FbosDetailsProps } from "./interfaces";
import { SourceFbosConfig } from "../../interfaces";
import { SourceFbosConfig, ShouldDisplay, Feature } from "../../interfaces";
import { ConfigurationName } from "farmbot";
/** Return an indicator color for the given temperature (C). */
export const colorFromTemp = (temp: number | undefined): string => {
@ -99,24 +100,48 @@ const UptimeDisplay = ({ uptime_sec }: { uptime_sec: number }): JSX.Element => {
return <p><b>{t("Uptime")}: </b>{convertUptime(uptime_sec)}</p>;
};
/** Label and toggle button for opting in to FBOS beta releases. */
const BetaReleaseOptInButton = ({ dispatch, sourceFbosConfig }: {
dispatch: Function, sourceFbosConfig: SourceFbosConfig
}): JSX.Element => {
const betaOptIn = sourceFbosConfig("beta_opt_in");
return <fieldset>
<label style={{ marginTop: "0.75rem" }}>
{t("Beta release Opt-In")}
</label>
<ToggleButton
toggleValue={betaOptIn.value}
dim={!betaOptIn.consistent}
toggleAction={() =>
(betaOptIn.value || confirm(Content.OS_BETA_RELEASES)) &&
dispatch(updateConfig({ beta_opt_in: !betaOptIn.value }))} />
</fieldset>;
export const betaReleaseOptIn = ({ sourceFbosConfig, shouldDisplay }: {
sourceFbosConfig: SourceFbosConfig, shouldDisplay: ShouldDisplay
}) => {
if (shouldDisplay(Feature.use_update_channel)) {
const betaOptIn = sourceFbosConfig("update_channel" as ConfigurationName);
const betaOptInValue = betaOptIn.value !== "stable";
return {
betaOptIn: { value: betaOptInValue, consistent: true }, betaOptInValue,
update: { update_channel: betaOptInValue ? "stable" : "beta" }
};
} else {
const betaOptIn = sourceFbosConfig("beta_opt_in");
const betaOptInValue = betaOptIn.value;
return {
betaOptIn, betaOptInValue,
update: { beta_opt_in: !betaOptInValue }
};
}
};
/** Label and toggle button for opting in to FBOS beta releases. */
const BetaReleaseOptInButton =
({ dispatch, sourceFbosConfig, shouldDisplay }: {
dispatch: Function,
sourceFbosConfig: SourceFbosConfig,
shouldDisplay: ShouldDisplay,
}): JSX.Element => {
const { betaOptIn, betaOptInValue, update } =
betaReleaseOptIn({ sourceFbosConfig, shouldDisplay });
return <fieldset>
<label style={{ marginTop: "0.75rem" }}>
{t("Beta release Opt-In")}
</label>
<ToggleButton
toggleValue={betaOptInValue}
dim={!betaOptIn.consistent}
toggleAction={() =>
(betaOptInValue || confirm(Content.OS_BETA_RELEASES)) &&
dispatch(updateConfig(update))} />
</fieldset>;
};
/** Current technical information about FarmBot OS running on the device. */
export function FbosDetails(props: FbosDetailsProps) {
const {
@ -139,6 +164,7 @@ export function FbosDetails(props: FbosDetailsProps) {
<WiFiStrengthDisplay wifiStrength={wifi_level} />
<BetaReleaseOptInButton
dispatch={props.dispatch}
shouldDisplay={props.shouldDisplay}
sourceFbosConfig={props.sourceFbosConfig} />
</div>;
}

View File

@ -53,12 +53,14 @@ export interface FarmbotOsRowProps {
osReleaseNotes: string;
dispatch: Function;
sourceFbosConfig: SourceFbosConfig;
shouldDisplay: ShouldDisplay;
botOnline: boolean;
}
export interface FbosDetailsProps {
botInfoSettings: InformationalSettings;
dispatch: Function;
shouldDisplay: ShouldDisplay;
sourceFbosConfig: SourceFbosConfig;
}

View File

@ -118,7 +118,10 @@ const buttonVersionStatus =
const { currentOSVersion, currentBetaOSVersion, currentBetaOSCommit } = bot;
// Currently installed FBOS version data.
const botInfo = bot.hardware.informational_settings;
const { controller_version, commit, currently_on_beta } = botInfo;
const {
controller_version, commit, currently_on_beta, update_available
// tslint:disable-next-line:no-any // TODO: fix FBJS
} = botInfo as any;
/** Newest release version, given settings and data available. */
const latestReleaseV =
@ -135,8 +138,9 @@ const buttonVersionStatus =
/** `1.0.0-beta vs 1.0.0-beta`: installed beta is older. */
const oldBetaCommit = (latestReleaseV === currentBetaOSVersion) &&
!betaCommitsAreEqual(commit, currentBetaOSCommit);
/** Button status modification required for beta release edge cases. */
const updateStatusOverride = uncertainty && oldBetaCommit;
/** Button status modification required for release edge cases. */
const updateStatusOverride = update_available
|| (uncertainty && oldBetaCommit);
return buttonProps(
updateStatusOverride ? UpdateButton.needsUpdate : btnStatus,

View File

@ -76,6 +76,7 @@ export enum Feature {
firmware_restart = "firmware_restart",
api_farmware_installations = "api_farmware_installations",
api_farmware_env = "api_farmware_env",
use_update_channel = "use_update_channel",
}
/** Object fetched from FEATURE_MIN_VERSIONS_URL. */
export type MinOsFeatureLookup = Partial<Record<Feature, string>>;