misc updates

pull/1157/head
gabrielburnworth 2019-04-16 10:00:00 -07:00
parent 6d68f73fbe
commit 08259b0ab1
11 changed files with 98 additions and 32 deletions

View File

@ -1,52 +1,60 @@
import * as React from "react";
import { mount } from "enzyme";
import { ToggleButton } from "../toggle_button";
import { ToggleButtonProps } from "../interfaces";
describe("<ToggleButton/>", function () {
const fakeProps = (): ToggleButtonProps => ({
toggleValue: 0,
toggleAction: jest.fn(),
});
it("calls toggle action", () => {
const toggle = jest.fn();
const toggleButton = mount(<ToggleButton
toggleValue={0}
toggleAction={() => toggle()} />);
const p = fakeProps();
const toggleButton = mount(<ToggleButton {...p} />);
toggleButton.simulate("click");
expect(toggle).toHaveBeenCalledTimes(1);
expect(p.toggleAction).toHaveBeenCalledTimes(1);
});
it("displays no", () => {
const toggleButton = mount(<ToggleButton
toggleValue={0}
toggleAction={jest.fn()} />);
const toggleButton = mount(<ToggleButton {...fakeProps()} />);
expect(toggleButton.text()).toBe("no");
});
it("displays yes", () => {
const toggleButton = mount(<ToggleButton
toggleValue={1}
toggleAction={jest.fn()} />);
const p = fakeProps();
p.toggleValue = 1;
const toggleButton = mount(<ToggleButton {...p} />);
expect(toggleButton.text()).toBe("yes");
});
it("displays off", () => {
const toggleButton = mount(<ToggleButton
toggleValue={0}
toggleAction={jest.fn()}
customText={{ textFalse: "off", textTrue: "on" }} />);
const p = fakeProps();
p.customText = { textFalse: "off", textTrue: "on" };
const toggleButton = mount(<ToggleButton {...p} />);
expect(toggleButton.text()).toEqual("off");
});
it("displays on", () => {
const toggleButton = mount(<ToggleButton
toggleValue={1}
toggleAction={jest.fn()}
customText={{ textFalse: "off", textTrue: "on" }} />);
const p = fakeProps();
p.toggleValue = 1;
p.customText = { textFalse: "off", textTrue: "on" };
const toggleButton = mount(<ToggleButton {...p} />);
expect(toggleButton.text()).toEqual("on");
});
it("displays 🚫", () => {
const toggleButton = mount(<ToggleButton
toggleValue={undefined}
toggleAction={jest.fn()}
customText={{ textFalse: "off", textTrue: "on" }} />);
const p = fakeProps();
p.toggleValue = undefined;
p.customText = { textFalse: "off", textTrue: "on" };
const toggleButton = mount(<ToggleButton {...p} />);
expect(toggleButton.text()).toEqual("🚫");
});
it("displays dim", () => {
const p = fakeProps();
p.dim = true;
const toggleButton = mount(<ToggleButton {...p} />);
expect(toggleButton.html()).toContain("dim");
});
});

View File

@ -23,7 +23,6 @@ export class ToggleButton extends React.Component<ToggleButtonProps, {}> {
css() {
const css = "fb-toggle-button fb-button ";
if (this.props.disabled) { return css + "gray"; }
const greenCSS = css + "green";
const redCSS = css + "red";
const yellowCSS = css + "yellow";

View File

@ -293,6 +293,10 @@
&.grayscale {
filter: grayscale(100%);
}
&.disabled,
&:disabled {
background: $medium_light_gray !important;
}
}
.front-page-button {

View File

@ -572,6 +572,12 @@
opacity: 0;
}
}
.map-rotate-button {
text-align: center;
.fb-button {
float: none;
}
}
}
.map-points-submenu {

View File

@ -58,7 +58,7 @@
box-shadow: none;
color: $dark_gray;
font-weight: bold;
min-width: 30%;
min-width: 130px;
}
p {
font-size: 1rem;

View File

@ -382,8 +382,25 @@ describe("getGardenCoordinates()", () => {
});
describe("mapPanelClassName()", () => {
it("returns correct panel status", () => {
it("returns correct panel status: short panel", () => {
Object.defineProperty(window, "innerWidth", {
value: 400,
configurable: true
});
mockPath = "/app/designer/move_to";
expect(mapPanelClassName()).toEqual("short-panel");
mockPath = "/app/designer/plants/crop_search/mint/add";
expect(mapPanelClassName()).toEqual("short-panel");
});
it("returns correct panel status: panel open", () => {
Object.defineProperty(window, "innerWidth", {
value: 500,
configurable: true
});
mockPath = "/app/designer/move_to";
expect(mapPanelClassName()).toEqual("panel-open");
mockPath = "/app/designer/plants/crop_search/mint/add";
expect(mapPanelClassName()).toEqual("panel-open");
});
});

View File

@ -22,7 +22,7 @@ jest.mock("../../../../account/dev/dev_support", () => ({
import * as React from "react";
import { shallow, mount } from "enzyme";
import {
GardenMapLegend, ZoomControls, PointsSubMenu
GardenMapLegend, ZoomControls, PointsSubMenu, RotationSelector
} from "../garden_map_legend";
import { GardenMapLegendProps } from "../../interfaces";
import { clickButton } from "../../../../__test_support__/helpers";
@ -114,3 +114,19 @@ describe("<PointsSubMenu />", () => {
expect(toggle).toHaveBeenCalledWith(BooleanSetting.show_historic_points);
});
});
describe("<RotationSelector />", () => {
it("swaps map x&y", () => {
const dispatch = jest.fn();
const wrapper = mount(<RotationSelector
dispatch={dispatch} value={false} />);
wrapper.find("button").simulate("click");
expect(dispatch).toHaveBeenCalled();
});
it("shows correct status", () => {
const wrapper = mount(<RotationSelector
dispatch={jest.fn()} value={true} />);
expect(wrapper.find("button").hasClass("green")).toBeTruthy();
});
});

View File

@ -8,7 +8,9 @@ import { BugsControls } from "../easter_eggs/bugs";
import { BotOriginQuadrant, State } from "../../interfaces";
import { MoveModeLink } from "../../move_to";
import { SavedGardensLink } from "../../saved_gardens/saved_gardens";
import { GetWebAppConfigValue } from "../../../config_storage/actions";
import {
GetWebAppConfigValue, setWebAppConfigValue
} from "../../../config_storage/actions";
import { BooleanSetting } from "../../../session_keys";
import { DevSettings } from "../../../account/dev/dev_support";
import { t } from "../../../i18next_wrapper";
@ -30,6 +32,16 @@ const OriginSelector = ({ quadrant, update }: {
</div>
</div>;
export const RotationSelector = ({ dispatch, value }:
{ dispatch: Function, value: boolean }) => {
const classNames = `fb-button fb-toggle-button ${value ? "green" : "red"}`;
return <div className={"map-rotate-button"}>
<label>{t("rotate")}</label>
<button className={classNames} onClick={() =>
dispatch(setWebAppConfigValue(BooleanSetting.xy_swap, !value))} />
</div>;
};
export const ZoomControls = ({ zoom, getConfigValue }: {
zoom: (value: number) => () => void,
getConfigValue: GetWebAppConfigValue
@ -127,6 +139,8 @@ export function GardenMapLegend(props: GardenMapLegendProps) {
<OriginSelector
quadrant={props.botOriginQuadrant}
update={props.updateBotOriginQuadrant} />
<RotationSelector dispatch={props.dispatch}
value={!!props.getConfigValue(BooleanSetting.xy_swap)} />
<MoveModeLink />
<SavedGardensLink />
<BugsControls />

View File

@ -63,7 +63,8 @@ export const getPanelStatus = (): MapPanelStatus => {
return MapPanelStatus.closed;
}
const mode = getMode();
if (mode === Mode.moveTo || mode === Mode.clickToAdd) {
if (window.innerWidth <= 450 &&
(mode === Mode.moveTo || mode === Mode.clickToAdd)) {
return MapPanelStatus.short;
}
return MapPanelStatus.open;

View File

@ -57,7 +57,7 @@ const getfirstTickerLog = (getConfigValue: GetWebAppConfigValue) =>
/** Format a single log for display in the ticker. */
const Ticker = (log: TaggedLog, timeSettings: TimeSettings) => {
const { message, type, created_at } = log.body;
const time = formatLogTime(created_at || NaN, timeSettings);
const time = created_at ? formatLogTime(created_at, timeSettings) : "";
return <div key={log.uuid} className="status-ticker-wrapper">
<div className={`saucer ${type}`} />
<label className="status-ticker-message">

View File

@ -1,6 +1,5 @@
import * as React from "react";
import axios from "axios";
import { error as log, init as logInit } from "farmbot-toastr";
import { prettyPrintApiErrors } from "../util";
import { API } from "../api";
@ -76,7 +75,9 @@ export class PasswordReset extends React.Component<Props, State> {
<Row>
<Col xs={12} sm={6} className="col-sm-push-3">
<Widget>
<WidgetHeader title={"Reset Password"} />
<WidgetHeader
title={"Reset Password"}
helpText={t("Password must be 8 or more characters.")} />
<WidgetBody>
<form onSubmit={this.submit.bind(this)}>
<label>