Merge pull request #987 from gabrielburnworth/staging

Misc
pull/988/head
Rick Carlino 2018-09-14 15:46:10 -05:00 committed by GitHub
commit 76606073b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 60 additions and 38 deletions

View File

@ -37,7 +37,8 @@ export namespace ToolTips {
few sequences to verify that everything works as expected.`); few sequences to verify that everything works as expected.`);
export const PIN_BINDINGS = export const PIN_BINDINGS =
trim(`Assign a sequence to execute when a Raspberry Pi GPIO pin is activated.`); trim(`Assign a sequence to execute when a Raspberry Pi GPIO pin is
activated.`);
export const PIN_BINDING_WARNING = export const PIN_BINDING_WARNING =
trim(`Warning: Binding to a pin without a physical button and trim(`Warning: Binding to a pin without a physical button and
@ -49,10 +50,10 @@ export namespace ToolTips {
// Hardware Settings: Homing and Calibration // Hardware Settings: Homing and Calibration
export const HOMING = export const HOMING =
trim(`(Alpha) If encoders or end-stops are enabled, home axis (find zero).`); trim(`If encoders or end-stops are enabled, home axis (find zero).`);
export const CALIBRATION = export const CALIBRATION =
trim(`(Alpha) If encoders or end-stops are enabled, home axis and determine trim(`If encoders or end-stops are enabled, home axis and determine
maximum.`); maximum.`);
export const SET_ZERO_POSITION = export const SET_ZERO_POSITION =
@ -107,8 +108,8 @@ export namespace ToolTips {
trim(`The number of motor steps required to move the axis one millimeter.`); trim(`The number of motor steps required to move the axis one millimeter.`);
export const ALWAYS_POWER_MOTORS = export const ALWAYS_POWER_MOTORS =
trim(`Keep power applied to motors. Prevents slipping from gravity in certain trim(`Keep power applied to motors. Prevents slipping from gravity in
situations.`); certain situations.`);
export const INVERT_MOTORS = export const INVERT_MOTORS =
trim(`Invert direction of motor during calibration.`); trim(`Invert direction of motor during calibration.`);
@ -118,23 +119,23 @@ export namespace ToolTips {
// Hardware Settings: Encoders and Endstops // Hardware Settings: Encoders and Endstops
export const ENABLE_ENCODERS = export const ENABLE_ENCODERS =
trim(`(Alpha) Enable use of rotary encoders during calibration and homing.`); trim(`Enable use of rotary encoders during calibration and homing.`);
export const ENCODER_POSITIONING = export const ENCODER_POSITIONING =
trim(`[EXPERIMENTAL] Use encoders for positioning.`); trim(`Use encoders for positioning.`);
export const INVERT_ENCODERS = export const INVERT_ENCODERS =
trim(`(Alpha) Reverse the direction of encoder position reading.`); trim(`Reverse the direction of encoder position reading.`);
export const MAX_MISSED_STEPS = export const MAX_MISSED_STEPS =
trim(`(Alpha) Number of steps missed (determined by encoder) before motor is trim(`Number of steps missed (determined by encoder) before motor is
considered to have stalled.`); considered to have stalled.`);
export const ENCODER_MISSED_STEP_DECAY = export const ENCODER_MISSED_STEP_DECAY =
trim(`(Alpha) Reduction to missed step total for every good step.`); trim(`Reduction to missed step total for every good step.`);
export const ENCODER_SCALING = export const ENCODER_SCALING =
trim(`(Alpha) encoder scaling factor = 10000 * (motor resolution * microsteps) trim(`encoder scaling factor = 10000 * (motor resolution * microsteps)
/ (encoder resolution).`); / (encoder resolution).`);
export const ENABLE_ENDSTOPS = export const ENABLE_ENDSTOPS =
@ -254,6 +255,12 @@ export namespace ToolTips {
trim(`Snaps a photo using the device camera. Select the camera type on the trim(`Snaps a photo using the device camera. Select the camera type on the
Device page.`); Device page.`);
export const MARK_AS =
trim(`The Mark As step allows FarmBot to programmatically edit the
properties of the UTM, plants, and weeds from within a sequence.
For example, you can mark a plant as "planted" during a seeding
sequence or delete a weed after removing it.`);
// Regimens // Regimens
export const BULK_SCHEDULER = export const BULK_SCHEDULER =
trim(`Add sequences to your regimen by selecting a sequence from the trim(`Add sequences to your regimen by selecting a sequence from the
@ -522,8 +529,8 @@ export namespace Content {
click "+" in the Regimens panel to create a new one.`); click "+" in the Regimens panel to create a new one.`);
export const NO_PARAMETERS = trim(`Can't directly use this sequence in a export const NO_PARAMETERS = trim(`Can't directly use this sequence in a
regimen. Consider wrapping it in a parent sequence that calls it via "execute" regimen. Consider wrapping it in a parent sequence that calls it via
instead."`); "execute" instead.`);
// Farm Designer // Farm Designer
export const OUTSIDE_PLANTING_AREA = export const OUTSIDE_PLANTING_AREA =
@ -538,6 +545,10 @@ export namespace Content {
trim(`Click and drag to draw a point or use the inputs and press trim(`Click and drag to draw a point or use the inputs and press
update. Press CREATE POINT to save, or the back arrow to exit.`); update. Press CREATE POINT to save, or the back arrow to exit.`);
export const BOX_SELECT_DESCRIPTION =
trim(`Drag a box around the plants you would like to select.
Press the back arrow to exit.`);
// Farm Events // Farm Events
export const REGIMEN_TODAY_SKIPPED_ITEM_RISK = export const REGIMEN_TODAY_SKIPPED_ITEM_RISK =
trim(`You are scheduling a regimen to run today. Be aware that trim(`You are scheduling a regimen to run today. Be aware that

View File

@ -97,7 +97,7 @@ export class Peripherals extends React.Component<PeripheralsProps, PeripheralSta
<button <button
className="fb-button gray" className="fb-button gray"
onClick={this.toggle} onClick={this.toggle}
hidden={!!status && isEditing}> disabled={!!status && isEditing}>
{!isEditing && t("Edit")} {!isEditing && t("Edit")}
{isEditing && t("Back")} {isEditing && t("Back")}
</button> </button>

View File

@ -85,7 +85,7 @@ export class Sensors extends React.Component<SensorsProps, SensorState> {
<button <button
className="fb-button gray" className="fb-button gray"
onClick={this.toggle} onClick={this.toggle}
hidden={!!status && isEditing}> disabled={!!status && isEditing}>
{!isEditing && t("Edit")} {!isEditing && t("Edit")}
{isEditing && t("Back")} {isEditing && t("Back")}
</button> </button>

View File

@ -27,7 +27,7 @@ describe("<WebcamPanel/>", () => {
wrapper.setState({ activeMenu: "edit" }); wrapper.setState({ activeMenu: "edit" });
const text = allButtonText(wrapper); const text = allButtonText(wrapper);
expect(text.toLowerCase()).not.toContain("edit"); expect(text.toLowerCase()).not.toContain("edit");
clickButton(wrapper, 2, "view"); clickButton(wrapper, 0, "back");
expect(wrapper.instance().state.activeMenu).toEqual("show"); expect(wrapper.instance().state.activeMenu).toEqual("show");
}); });
}); });

View File

@ -30,9 +30,10 @@ export function Edit(props: WebcamPanelProps) {
return <Widget> return <Widget>
<WidgetHeader title="Edit" helpText={ToolTips.WEBCAM}> <WidgetHeader title="Edit" helpText={ToolTips.WEBCAM}>
<button <button
className="fb-button green" className="fb-button gray"
onClick={props.init}> disabled={unsaved.length > 0}
<i className="fa fa-plus" /> onClick={props.onToggle}>
{t("Back")}
</button> </button>
<button <button
className="fb-button green" className="fb-button green"
@ -40,9 +41,9 @@ export function Edit(props: WebcamPanelProps) {
{t("Save")}{unsaved.length > 0 ? "*" : ""} {t("Save")}{unsaved.length > 0 ? "*" : ""}
</button> </button>
<button <button
className="fb-button gray" className="fb-button green"
onClick={props.onToggle}> onClick={props.init}>
{t("View")} <i className="fa fa-plus" />
</button> </button>
</WidgetHeader> </WidgetHeader>
<div className="widget-body"> <div className="widget-body">

View File

@ -194,6 +194,9 @@ a {
cursor: pointer !important; cursor: pointer !important;
&.fa-gear { &.fa-gear {
color: $white; color: $white;
&.dark {
color: $dark_gray;
}
} }
} }
@ -808,7 +811,8 @@ ul {
max-width: 250px; max-width: 250px;
h1 { h1 {
font-weight: 300; font-weight: 300;
font-size: 1.5rem; font-size: 1.4rem;
line-height: 2rem;
} }
li:before { li:before {
content: ""; content: "";

View File

@ -50,8 +50,10 @@ describe("<FarmbotOsSettings/>", () => {
{...fakeProps()} />); {...fakeProps()} />);
await expect(axios.get).toHaveBeenCalledWith( await expect(axios.get).toHaveBeenCalledWith(
expect.stringContaining("RELEASE_NOTES.md")); expect.stringContaining("RELEASE_NOTES.md"));
expect(osSettings.instance().state.osReleaseNotesHeading)
.toEqual("FarmBot OS v6");
expect(osSettings.instance().state.osReleaseNotes) expect(osSettings.instance().state.osReleaseNotes)
.toEqual("# FarmBot OS v6\n* note"); .toEqual("* note");
}); });
it("doesn't fetch OS release notes", async () => { it("doesn't fetch OS release notes", async () => {

View File

@ -37,7 +37,7 @@ const OS_RELEASE_NOTES_URL =
export class FarmbotOsSettings export class FarmbotOsSettings
extends React.Component<FarmbotOsProps, FarmbotOsState> { extends React.Component<FarmbotOsProps, FarmbotOsState> {
state = { osReleaseNotes: "" }; state = { osReleaseNotesHeading: "", osReleaseNotes: "" };
componentDidMount() { componentDidMount() {
this.fetchReleaseNotes(OS_RELEASE_NOTES_URL, this.fetchReleaseNotes(OS_RELEASE_NOTES_URL,
@ -49,12 +49,12 @@ export class FarmbotOsSettings
axios axios
.get<string>(url) .get<string>(url)
.then(resp => { .then(resp => {
const notes = resp.data const osReleaseNotes = resp.data
.split("# v") .split("# v")
.filter(x => x.startsWith(osMajorVersion))[0] .filter(x => x.startsWith(osMajorVersion))[0]
.split("\n\n").join("\n"); .split("\n\n").slice(1).join("\n");
const osReleaseNotes = "# FarmBot OS v" + notes; const osReleaseNotesHeading = "FarmBot OS v" + osMajorVersion;
this.setState({ osReleaseNotes }); this.setState({ osReleaseNotesHeading, osReleaseNotes });
}) })
.catch(() => .catch(() =>
this.setState({ osReleaseNotes: "Could not get release notes." })); this.setState({ osReleaseNotes: "Could not get release notes." }));
@ -142,6 +142,7 @@ export class FarmbotOsSettings
|| this.props.isValidFbosConfig}> || this.props.isValidFbosConfig}>
<FarmbotOsRow <FarmbotOsRow
bot={this.props.bot} bot={this.props.bot}
osReleaseNotesHeading={this.state.osReleaseNotesHeading}
osReleaseNotes={this.state.osReleaseNotes} osReleaseNotes={this.state.osReleaseNotes}
dispatch={this.props.dispatch} dispatch={this.props.dispatch}
sourceFbosConfig={sourceFbosConfig} sourceFbosConfig={sourceFbosConfig}

View File

@ -9,6 +9,7 @@ describe("<FarmbotOsRow/>", () => {
const fakeProps = (): FarmbotOsRowProps => { const fakeProps = (): FarmbotOsRowProps => {
return { return {
bot, bot,
osReleaseNotesHeading: "",
osReleaseNotes: "", osReleaseNotes: "",
dispatch: jest.fn(x => x(jest.fn(), fakeState)), dispatch: jest.fn(x => x(jest.fn(), fakeState)),
sourceFbosConfig: (x) => { sourceFbosConfig: (x) => {

View File

@ -40,6 +40,7 @@ export function FarmbotOsRow(props: FarmbotOsRowProps) {
<i className="fa fa-caret-down" /> <i className="fa fa-caret-down" />
</p> </p>
<div className="release-notes"> <div className="release-notes">
<h1>{props.osReleaseNotesHeading}</h1>
<Markdown> <Markdown>
{osReleaseNotes} {osReleaseNotes}
</Markdown> </Markdown>

View File

@ -45,6 +45,7 @@ export interface FactoryResetRowProps {
export interface FarmbotOsRowProps { export interface FarmbotOsRowProps {
bot: BotState; bot: BotState;
osReleaseNotesHeading: string;
osReleaseNotes: string; osReleaseNotes: string;
dispatch: Function; dispatch: Function;
sourceFbosConfig: SourceFbosConfig; sourceFbosConfig: SourceFbosConfig;

View File

@ -160,6 +160,7 @@ export interface FarmbotOsProps {
} }
export interface FarmbotOsState { export interface FarmbotOsState {
osReleaseNotesHeading: string;
osReleaseNotes: string; osReleaseNotes: string;
} }

View File

@ -7,7 +7,7 @@ import { PlantInventoryItem } from "./plant_inventory_item";
import { destroy } from "../../api/crud"; import { destroy } from "../../api/crud";
import { BackArrow } from "../../ui/index"; import { BackArrow } from "../../ui/index";
import { unselectPlant } from "../actions"; import { unselectPlant } from "../actions";
import { Actions } from "../../constants"; import { Actions, Content } from "../../constants";
import { TaggedPlant } from "../map/interfaces"; import { TaggedPlant } from "../map/interfaces";
import { getPlants } from "../state_to_props"; import { getPlants } from "../state_to_props";
@ -113,8 +113,7 @@ export class SelectPlants
</div> </div>
<div className="panel-header-description"> <div className="panel-header-description">
{t("Drag a box around the plants you would like to select. " + {t(Content.BOX_SELECT_DESCRIPTION)}
"Press the back arrow to exit.")}
</div> </div>
</div> </div>

View File

@ -91,7 +91,7 @@ export class FarmwareList
return <div> return <div>
<div className="farmware-settings-menu"> <div className="farmware-settings-menu">
<Popover position={Position.BOTTOM_RIGHT}> <Popover position={Position.BOTTOM_RIGHT}>
<i className="fa fa-gear" /> <i className="fa fa-gear dark" />
<FarmwareConfigMenu <FarmwareConfigMenu
show={this.props.showFirstParty} show={this.props.showFirstParty}
dispatch={this.props.dispatch} dispatch={this.props.dispatch}

View File

@ -121,7 +121,7 @@ export function CreateAccount(props: CreateAccountProps) {
const RelevantForm = props.sent ? DidRegister : MustRegister; const RelevantForm = props.sent ? DidRegister : MustRegister;
return <Col xs={12} sm={5}> return <Col xs={12} sm={5}>
<Widget> <Widget>
<WidgetHeader title={"Create An Account"} /> <WidgetHeader title={t("Create An Account")} />
<RelevantForm {...props} /> <RelevantForm {...props} />
</Widget> </Widget>
</Col>; </Col>;

View File

@ -35,7 +35,7 @@ export class MarkAs extends React.Component<StepParams, MarkAsState> {
return <StepWrapper> return <StepWrapper>
<StepHeader <StepHeader
className={this.className} className={this.className}
helpText={ToolTips.WAIT} helpText={ToolTips.MARK_AS}
currentSequence={this.props.currentSequence} currentSequence={this.props.currentSequence}
currentStep={this.props.currentStep} currentStep={this.props.currentStep}
dispatch={this.props.dispatch} dispatch={this.props.dispatch}

View File

@ -101,7 +101,7 @@ export class TosUpdate extends React.Component<Props, Partial<State>> {
logInit(); logInit();
const body = t("Before logging in, you must agree to our latest Terms" + const body = t("Before logging in, you must agree to our latest Terms" +
" of Service and Privacy Policy"); " of Service and Privacy Policy");
log(body, "New Terms of Service"); log(body, t("New Terms of Service"));
} }
render() { render() {
@ -110,8 +110,8 @@ export class TosUpdate extends React.Component<Props, Partial<State>> {
<Widget> <Widget>
<WidgetHeader title={ <WidgetHeader title={
this.tosLoadOk this.tosLoadOk
? "Agree to Terms of Service" ? t("Agree to Terms of Service")
: "Problem Loading Terms of Service"} /> : t("Problem Loading Terms of Service")} />
<WidgetBody> <WidgetBody>
{this.tosForm()} {this.tosForm()}
</WidgetBody> </WidgetBody>