mobile sequence step reorder controls
This commit is contained in:
parent
1c05dde5fe
commit
73b37cc0b5
|
@ -108,6 +108,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
.step-up-down-arrows {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.step-control {
|
||||
margin-top: 0.3rem;
|
||||
margin-left: 2rem;
|
||||
|
|
52
webpack/sequences/__tests__/step_icon_group_test.tsx
Normal file
52
webpack/sequences/__tests__/step_icon_group_test.tsx
Normal file
|
@ -0,0 +1,52 @@
|
|||
jest.mock("../step_tiles", () => ({
|
||||
splice: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
move: jest.fn(),
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { StepIconGroup, StepIconBarProps } from "../step_icon_group";
|
||||
import { fakeSequence } from "../../__test_support__/fake_state/resources";
|
||||
import { splice, remove, move } from "../step_tiles";
|
||||
|
||||
describe("<StepIconGroup />", () => {
|
||||
const fakeProps = (): StepIconBarProps => ({
|
||||
index: 0,
|
||||
dispatch: jest.fn(),
|
||||
step: { kind: "wait", args: { milliseconds: 100 } },
|
||||
sequence: fakeSequence(),
|
||||
helpText: "helpful text",
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<StepIconGroup {...fakeProps()} />);
|
||||
expect(wrapper.find("i").length).toEqual(4);
|
||||
});
|
||||
|
||||
it("deletes step", () => {
|
||||
const wrapper = mount(<StepIconGroup {...fakeProps()} />);
|
||||
wrapper.find("i").at(2).simulate("click");
|
||||
expect(remove).toHaveBeenCalledWith(expect.objectContaining({ index: 0 }));
|
||||
});
|
||||
|
||||
it("duplicates step", () => {
|
||||
const wrapper = mount(<StepIconGroup {...fakeProps()} />);
|
||||
wrapper.find("i").at(1).simulate("click");
|
||||
expect(splice).toHaveBeenCalledWith(expect.objectContaining({
|
||||
index: 0,
|
||||
step: fakeProps().step
|
||||
}));
|
||||
});
|
||||
|
||||
it("moves step", () => {
|
||||
const wrapper = shallow(<StepIconGroup {...fakeProps()} />);
|
||||
// tslint:disable-next-line:no-any
|
||||
(wrapper.find("StepUpDownButtonPopover").props() as any).onMove(-1)();
|
||||
expect(move).toHaveBeenCalledWith(expect.objectContaining({
|
||||
from: 0,
|
||||
to: 0,
|
||||
step: fakeProps().step
|
||||
}));
|
||||
});
|
||||
});
|
|
@ -1,17 +1,40 @@
|
|||
import * as React from "react";
|
||||
import { Help } from "../ui/help";
|
||||
import { Popover, Position } from "@blueprintjs/core";
|
||||
import { SequenceBodyItem, TaggedSequence } from "farmbot";
|
||||
import { splice, remove, move } from "./step_tiles";
|
||||
|
||||
interface StepIconBarProps {
|
||||
onClone(): void;
|
||||
onTrash(): void;
|
||||
export interface StepIconBarProps {
|
||||
index: number;
|
||||
dispatch: Function;
|
||||
step: SequenceBodyItem;
|
||||
sequence: TaggedSequence;
|
||||
helpText: string;
|
||||
}
|
||||
|
||||
export function StepUpDownButtonPopover(
|
||||
{ onMove }: { onMove: (d: number) => () => void }) {
|
||||
return <Popover position={Position.TOP} usePortal={false}>
|
||||
<i className="fa fa-arrows-v step-control" />
|
||||
<div className={"step-up-down-arrows"}>
|
||||
<i className="fa fa-arrow-circle-up" onClick={onMove(-1)} />
|
||||
<i className="fa fa-arrow-circle-down" onClick={onMove(2)} />
|
||||
</div>
|
||||
</Popover>;
|
||||
}
|
||||
|
||||
export function StepIconGroup(props: StepIconBarProps) {
|
||||
const { onClone, onTrash, helpText } = props;
|
||||
const { index, dispatch, step, sequence, helpText } = props;
|
||||
|
||||
const onClone = () => dispatch(splice({ step, index, sequence }));
|
||||
const onTrash = () => remove({ dispatch, index, sequence });
|
||||
const onMove = (delta: number) => () => {
|
||||
const to = Math.max(index + delta, 0);
|
||||
dispatch(move({ step, sequence, from: index, to }));
|
||||
};
|
||||
|
||||
return <span>
|
||||
<i className="fa fa-arrows-v step-control" />
|
||||
<StepUpDownButtonPopover onMove={onMove} />
|
||||
<i className="fa fa-clone step-control" onClick={onClone} />
|
||||
<i className="fa fa-trash step-control" onClick={onTrash} />
|
||||
<Help text={helpText} />
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Row, Col } from "../../ui/index";
|
|||
import { TaggedSequence, SequenceBodyItem } from "farmbot";
|
||||
import { StepTitleBar } from "../step_tiles/step_title_bar";
|
||||
import { StepIconGroup } from "../step_icon_group";
|
||||
import { splice, remove } from "../step_tiles/index";
|
||||
|
||||
export interface StepHeaderProps {
|
||||
children?: React.ReactNode;
|
||||
|
@ -34,13 +33,10 @@ export function StepHeader(props: StepHeaderProps) {
|
|||
step={currentStep}
|
||||
sequence={currentSequence} />
|
||||
<StepIconGroup
|
||||
onClone={() => dispatch(splice({
|
||||
step: currentStep,
|
||||
index,
|
||||
sequence: currentSequence
|
||||
}))}
|
||||
onTrash={() =>
|
||||
remove({ dispatch, index, sequence: currentSequence })}
|
||||
index={index}
|
||||
dispatch={dispatch}
|
||||
step={currentStep}
|
||||
sequence={currentSequence}
|
||||
helpText={t(helpText)} />
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue