fix dropdown bug

pull/1422/head
gabrielburnworth 2019-09-09 14:18:22 -07:00
parent 437df4e4db
commit baed1f0664
5 changed files with 115 additions and 44 deletions

View File

@ -47,8 +47,13 @@ class User < ApplicationRecord
def self.refresh_everyones_ui
Rollbar.error("Global UI refresh triggered")
msg = {
"type" => "reload",
"commit" => (ENV["HEROKU_SLUG_COMMIT"] || "NONE").first(8)
}
Transport
.current
.raw_amqp_send({}.to_json, Api::RmqUtilsController::PUBLIC_BROADCAST)
.raw_amqp_send(msg.to_json, Api::RmqUtilsController::PUBLIC_BROADCAST)
end
end

View File

@ -1012,7 +1012,7 @@ ul {
background: $white;
.log-verbosity-saucer, .saucer {
float: left;
margin-right: 10px;
margin-right: 5px;
}
button {
float: none;

View File

@ -1,9 +1,13 @@
const mockEditStep = jest.fn();
jest.mock("../../../api/crud", () => ({ editStep: mockEditStep }));
import * as React from "react";
import { TileWritePin } from "../tile_write_pin";
import { mount } from "enzyme";
import { TileWritePin, WritePinStep } from "../tile_write_pin";
import { mount, shallow } from "enzyme";
import { fakeSequence } from "../../../__test_support__/fake_state/resources";
import { WritePin } from "farmbot/dist";
import { emptyState } from "../../../resources/reducer";
import { FBSelect } from "../../../ui";
describe("<TileWritePin/>", () => {
function fakeProps() {
@ -22,6 +26,8 @@ describe("<TileWritePin/>", () => {
index: 0,
resources: emptyState().index,
confirmStepDeletion: false,
shouldDisplay: () => false,
showPins: false,
};
}
@ -60,4 +66,28 @@ describe("<TileWritePin/>", () => {
expect(labels.at(2).text()).toEqual("set to");
expect(buttons.at(2).text()).toEqual("ON");
});
it("changes pin value", () => {
const p = fakeProps();
p.currentStep.args.pin_mode = 0;
p.currentStep.args.pin_value = 1;
const wrapper = mount<WritePinStep>(<WritePinStep {...p} />);
const pinValueSelect = shallow(
<div>{wrapper.instance().PinValueField()}</div>);
pinValueSelect.find(FBSelect).last().simulate("change", {
label: "123", value: 123
});
const step = p.currentStep;
mockEditStep.mock.calls[0][0].executor(step);
expect(step.args.pin_value).toEqual(123);
});
it("throws when not a WritePin step", () => {
console.error = jest.fn();
const p = fakeProps();
// tslint:disable-next-line:no-any
p.currentStep.kind = "wrong_step" as any;
expect(() => mount(<TileWritePin {...p} />))
.toThrow("Not a write_pin block.");
});
});

View File

@ -14,14 +14,55 @@ import {
} from "./pin_and_peripheral_support";
import { t } from "../../i18next_wrapper";
import { PinMode } from "./tile_read_pin";
import { WritePin, TaggedSequence } from "farmbot";
import { ResourceIndex } from "../../resources/interfaces";
import { ShouldDisplay } from "../../devices/interfaces";
export function TileWritePin(props: StepParams) {
const { dispatch, currentStep, index, currentSequence } = props;
/** Make sure the generic `currentStep` provided is a WritePin step. */
if (currentStep.kind !== "write_pin") { throw new Error("never"); }
export function TileWritePin(p: StepParams) {
if (p.currentStep.kind === "write_pin") {
return <WritePinStep currentStep={p.currentStep}
currentSequence={p.currentSequence}
index={p.index}
dispatch={p.dispatch}
resources={p.resources}
shouldDisplay={p.shouldDisplay}
confirmStepDeletion={p.confirmStepDeletion}
showPins={!!p.showPins} />;
} else {
throw new Error("Not a write_pin block.");
}
}
const PinValueField = (): JSX.Element =>
(!(currentStep.args.pin_mode === 0) || currentStep.args.pin_value > 1)
export interface WritePinStepParams {
currentStep: WritePin;
currentSequence: TaggedSequence;
dispatch: Function;
index: number;
resources: ResourceIndex;
shouldDisplay: ShouldDisplay | undefined;
confirmStepDeletion: boolean;
showPins: boolean;
}
export class WritePinStep extends React.Component<WritePinStepParams> {
PinSelect = (): JSX.Element => {
const { currentSequence, resources, showPins } = this.props;
const { pin_number } = this.props.currentStep.args;
return <Col xs={6} md={6}>
<label>{t("Peripheral")}</label>
<FBSelect
key={JSON.stringify(currentSequence)}
selectedItem={celery2DropDown(pin_number, resources)}
customNullLabel={t("Select a peripheral")}
onChange={setArgsDotPinNumber(this.props)}
list={pinsAsDropDownsWritePin(resources, !!showPins)} />
</Col>;
}
PinValueField = (): JSX.Element => {
const { dispatch, currentStep, index, currentSequence } = this.props;
return (!(currentStep.args.pin_mode === 0) || currentStep.args.pin_value > 1)
/** Analog pin mode: display number input for pin value. */
? <StepInputBox dispatch={dispatch}
step={currentStep}
@ -30,40 +71,33 @@ export function TileWritePin(props: StepParams) {
field="pin_value" />
/** Digital mode: replace pin value input with an ON/OFF dropdown. */
: <FBSelect
key={JSON.stringify(props.currentSequence)}
onChange={x => setPinValue(x, props)}
key={JSON.stringify(currentSequence)}
onChange={x => setPinValue(x, this.props)}
selectedItem={currentValueSelection(currentStep)}
list={PIN_VALUES()} />;
}
const className = "write-pin-step";
const { pin_number } = currentStep.args;
return <StepWrapper>
<StepHeader
className={className}
helpText={ToolTips.WRITE_PIN}
currentSequence={currentSequence}
currentStep={currentStep}
dispatch={dispatch}
index={index}
confirmStepDeletion={props.confirmStepDeletion} />
<StepContent className={className}>
<Row>
<Col xs={6} md={6}>
<label>{t("Peripheral")}</label>
<FBSelect
key={JSON.stringify(props.currentSequence)}
selectedItem={celery2DropDown(pin_number, props.resources)}
customNullLabel={t("Select a peripheral")}
onChange={setArgsDotPinNumber(props)}
list={pinsAsDropDownsWritePin(props.resources, !!props.showPins)} />
</Col>
<PinMode {...props} />
<Col xs={6} md={3}>
<label>{t("set to")}</label>
<PinValueField />
</Col>
</Row>
</StepContent>
</StepWrapper>;
render() {
const className = "write-pin-step";
return <StepWrapper>
<StepHeader
className={className}
helpText={ToolTips.WRITE_PIN}
currentSequence={this.props.currentSequence}
currentStep={this.props.currentStep}
dispatch={this.props.dispatch}
index={this.props.index}
confirmStepDeletion={this.props.confirmStepDeletion} />
<StepContent className={className}>
<Row>
<this.PinSelect />
<PinMode {...this.props} />
<Col xs={6} md={3}>
<label>{t("set to")}</label>
<this.PinValueField />
</Col>
</Row>
</StepContent>
</StepWrapper>;
}
}

View File

@ -17,7 +17,9 @@ describe User do
it "Sends a message over AMQP" do
expect(Rollbar).to receive(:error).with("Global UI refresh triggered")
get_msg = receive(:raw_amqp_send)
.with({}.to_json, Api::RmqUtilsController::PUBLIC_BROADCAST)
.with({
"type" => "reload", "commit" => "NONE"
}.to_json, Api::RmqUtilsController::PUBLIC_BROADCAST)
expect(Transport.current).to get_msg
User.refresh_everyones_ui
end