[UNSTABLE] Needs testing and QA

This commit is contained in:
Rick Carlino 2017-08-15 16:08:24 -05:00
parent 0a36e47ecb
commit f2e0fc9b3a
11 changed files with 23 additions and 25 deletions

View file

@ -12,6 +12,7 @@ import { SpacePanelHeader } from "./hardware_settings/space_panel_header";
import { import {
HomingAndCalibration HomingAndCalibration
} from "./hardware_settings/homing_and_calibration"; } from "./hardware_settings/homing_and_calibration";
import { SpecialStatus } from "../../resources/tagged_resources";
export class HardwareSettings extends export class HardwareSettings extends
React.Component<HardwareSettingsProps, {}> { React.Component<HardwareSettingsProps, {}> {
@ -26,6 +27,7 @@ export class HardwareSettings extends
status={bot.hardware.informational_settings.sync_status} status={bot.hardware.informational_settings.sync_status}
lockOpen={process.env.NODE_ENV !== "production"}> lockOpen={process.env.NODE_ENV !== "production"}>
<SaveBtn <SaveBtn
status={bot.isUpdating ? SpecialStatus.SAVING : undefined}
dirtyText={" "} dirtyText={" "}
savingText={"Updating..."} savingText={"Updating..."}
savedText={"saved"} savedText={"saved"}

View file

@ -26,7 +26,6 @@ describe("<FarmEventForm/>", () => {
it("sets defaults", () => { it("sets defaults", () => {
expect(context.form.state.fe).toMatchObject({}); expect(context.form.state.fe).toMatchObject({});
expect(context.form.state.localCopyDirty).toBeFalsy();
}); });
it("determines if it is a one time event", () => { it("determines if it is a one time event", () => {
@ -77,10 +76,8 @@ describe("<FarmEventForm/>", () => {
let p = props(); let p = props();
let i = instance(p); let i = instance(p);
i.forceUpdate(); i.forceUpdate();
expect(i.state.localCopyDirty).toBe(false);
i.executableSet({ value: "wow", label: "hey", headingId: "Sequence" }); i.executableSet({ value: "wow", label: "hey", headingId: "Sequence" });
i.forceUpdate(); i.forceUpdate();
expect(i.state.localCopyDirty).toBe(true);
expect(i.state.fe.executable_type).toEqual("Sequence"); expect(i.state.fe.executable_type).toEqual("Sequence");
expect(i.state.fe.executable_id).toEqual("wow"); expect(i.state.fe.executable_id).toEqual("wow");
}); });
@ -99,10 +96,8 @@ describe("<FarmEventForm/>", () => {
let p = props(); let p = props();
let i = instance(p); let i = instance(p);
i.forceUpdate(); i.forceUpdate();
expect(i.state.localCopyDirty).toBe(false);
i.fieldSet("repeat")(({ currentTarget: { value: "4" } } as any)); i.fieldSet("repeat")(({ currentTarget: { value: "4" } } as any));
i.forceUpdate(); i.forceUpdate();
expect(i.state.localCopyDirty).toBe(true);
expect(i.state.fe.repeat).toEqual("4"); expect(i.state.fe.repeat).toEqual("4");
}); });

View file

@ -3,7 +3,7 @@ import * as moment from "moment";
import * as _ from "lodash"; import * as _ from "lodash";
import { t } from "i18next"; import { t } from "i18next";
import { success, error } from "farmbot-toastr"; import { success, error } from "farmbot-toastr";
import { TaggedFarmEvent, SpecialStatus } from "../../resources/tagged_resources"; import { TaggedFarmEvent } from "../../resources/tagged_resources";
import { import {
TimeUnit, TimeUnit,
ExecutableQuery, ExecutableQuery,
@ -100,11 +100,10 @@ interface State {
* *
* Example: Navigating away from the page while editing will discard changes. * Example: Navigating away from the page while editing will discard changes.
*/ */
localCopySpecialStatus: SpecialStatus | undefined;
} }
export class EditFEForm extends React.Component<EditFEProps, State> { export class EditFEForm extends React.Component<EditFEProps, State> {
state: State = { fe: {}, localCopySpecialStatus: undefined }; state: State = { fe: {} };
get isOneTime() { return this.fieldGet("timeUnit") === NEVER; } get isOneTime() { return this.fieldGet("timeUnit") === NEVER; }
@ -259,6 +258,7 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
endTime={this.fieldGet("endTime")} endTime={this.fieldGet("endTime")}
/> />
<SaveBtn <SaveBtn
status={fe.specialStatus}
color="magenta" color="magenta"
onClick={this.commitViewModel} /> onClick={this.commitViewModel} />
<button className="fb-button red" <button className="fb-button red"

View file

@ -77,7 +77,7 @@ export class GardenMap extends
let p: TaggedPlantPointer = { let p: TaggedPlantPointer = {
kind: "points", kind: "points",
uuid: "--never", uuid: "--never",
dirty: true, specialStatus: undefined,
body: Plant({ body: Plant({
x, x,
y, y,

View file

@ -1,14 +1,14 @@
import * as React from "react"; import * as React from "react";
import { AddRegimenProps } from "../interfaces"; import { AddRegimenProps } from "../interfaces";
import { push } from "../../history"; import { push } from "../../history";
import { TaggedRegimen } from "../../resources/tagged_resources"; import { TaggedRegimen, SpecialStatus } from "../../resources/tagged_resources";
import { init } from "../../api/crud"; import { init } from "../../api/crud";
function emptyRegimen(length: number): TaggedRegimen { function emptyRegimen(length: number): TaggedRegimen {
return { return {
kind: "regimens", kind: "regimens",
uuid: "NEVER", uuid: "NEVER",
dirty: true, specialStatus: SpecialStatus.DIRTY,
body: { body: {
name: ("New regimen " + (length++)), name: ("New regimen " + (length++)),
color: "gray", color: "gray",

View file

@ -22,7 +22,7 @@ export function RegimenListItem({ regimen, dispatch }: RegimenListItemProps) {
className={style.join(" ")} className={style.join(" ")}
onClick={select(dispatch, regimen)} onClick={select(dispatch, regimen)}
> >
{name} {regimen.dirty && ("*")} {name} {regimen.specialStatus && ("*")}
</button> </button>
</Link>; </Link>;
} }

View file

@ -9,6 +9,7 @@ const TOOL_ID = 99;
const SLOT_ID = 100; const SLOT_ID = 100;
const fakeTool: TaggedTool = { const fakeTool: TaggedTool = {
kind: "tools", kind: "tools",
specialStatus: undefined,
uuid: generateUuid(TOOL_ID, "tools"), uuid: generateUuid(TOOL_ID, "tools"),
body: { body: {
name: "yadda yadda", name: "yadda yadda",
@ -17,6 +18,7 @@ const fakeTool: TaggedTool = {
}; };
const fakeSlot: TaggedToolSlotPointer = { const fakeSlot: TaggedToolSlotPointer = {
kind: "points", kind: "points",
specialStatus: undefined,
uuid: generateUuid(SLOT_ID, "points"), uuid: generateUuid(SLOT_ID, "points"),
body: { body: {
tool_id: TOOL_ID, tool_id: TOOL_ID,

View file

@ -6,6 +6,7 @@ describe("maybeTagSteps()", () => {
const UNTAGGED_SEQUENCE: TaggedSequence = { const UNTAGGED_SEQUENCE: TaggedSequence = {
"kind": "sequences", "kind": "sequences",
"uuid": "whatever", "uuid": "whatever",
"specialStatus": undefined,
"body": { "body": {
"id": 8, "id": 8,
"name": "Goto 0, 0, 0", "name": "Goto 0, 0, 0",

View file

@ -8,6 +8,7 @@ import { maybeTagSteps } from "../../resources/sequence_tagging";
describe("<AllSteps/>", () => { describe("<AllSteps/>", () => {
const TEST_CASE = { const TEST_CASE = {
"kind": "sequences", "kind": "sequences",
"specialStatus": undefined,
"body": { "body": {
"id": 8, "id": 8,
"name": "Goto 0, 0, 0", "name": "Goto 0, 0, 0",

View file

@ -24,7 +24,7 @@ let sequenceList = (dispatch: Function) =>
]; ];
lastUrlChunk() === urlFriendly(ts.body.name) && css.push("active"); lastUrlChunk() === urlFriendly(ts.body.name) && css.push("active");
let click = () => dispatch(selectSequence(ts.uuid)); let click = () => dispatch(selectSequence(ts.uuid));
let name = ts.body.name + (ts.dirty ? "*" : ""); let name = ts.body.name + (ts.specialStatus ? "*" : "");
let { uuid } = ts; let { uuid } = ts;
return <Link return <Link
to={`/app/sequences/${urlFriendly(ts.body.name) || ""}`} to={`/app/sequences/${urlFriendly(ts.body.name) || ""}`}
@ -65,6 +65,7 @@ export class SequencesList extends
return { return {
kind: "sequences", kind: "sequences",
uuid: "REDUCER_MUST_CHANGE_THIS", uuid: "REDUCER_MUST_CHANGE_THIS",
specialStatus: undefined,
body: { body: {
name: "new sequence " + (this.props.sequences.length), name: "new sequence " + (this.props.sequences.length),
args: { version: -999 }, args: { version: -999 },

View file

@ -10,7 +10,7 @@ import {
BlurableInput, BlurableInput,
SaveBtn SaveBtn
} from "../../ui"; } from "../../ui";
import { TaggedTool } from "../../resources/tagged_resources"; import { TaggedTool, getArrayStatus } from "../../resources/tagged_resources";
import { edit, destroy, init, saveAll } from "../../api/crud"; import { edit, destroy, init, saveAll } from "../../api/crud";
import { ToolTips } from "../../constants"; import { ToolTips } from "../../constants";
@ -18,6 +18,7 @@ export class ToolForm extends React.Component<ToolFormProps, {}> {
emptyTool = (): TaggedTool => { emptyTool = (): TaggedTool => {
return { return {
uuid: "ERROR: GENERATED BY REDUCER - UUID SHOULD BE UNSEEN", uuid: "ERROR: GENERATED BY REDUCER - UUID SHOULD BE UNSEEN",
specialStatus: undefined,
kind: "tools", kind: "tools",
body: { name: "Tool " + (this.props.tools.length + 1) } body: { name: "Tool " + (this.props.tools.length + 1) }
}; };
@ -26,25 +27,20 @@ export class ToolForm extends React.Component<ToolFormProps, {}> {
render() { render() {
let toggle = () => this.props.toggle(); let toggle = () => this.props.toggle();
let { dispatch, tools } = this.props; let { dispatch, tools } = this.props;
let specialStatus = getArrayStatus(tools);
let isSaving = tools && tools.filter(x => x.saving).length !== 0;
let isDirty = tools && tools.filter(x => x.dirty).length !== 0;
let isSaved = !isSaving && !isDirty;
return <Widget> return <Widget>
<WidgetHeader helpText={ToolTips.TOOL_LIST} title="Tools"> <WidgetHeader helpText={ToolTips.TOOL_LIST} title="Tools">
<button <button
className="fb-button gray" className="fb-button gray"
onClick={() => { toggle(); }} onClick={() => { toggle(); }}
hidden={!isSaved}> hidden={!!specialStatus}>
{t("Back")} {t("Back")}
</button> </button>
<SaveBtn <SaveBtn
isDirty={isDirty} status={specialStatus}
isSaving={isSaving} onClick={() => {
isSaved={isSaved} dispatch(saveAll(tools, () => { toggle(); }));
onClick={() => { dispatch(saveAll(tools, () => { toggle(); })) }} }} />
/>
<button <button
className="fb-button green" className="fb-button green"
onClick={() => { dispatch(init(this.emptyTool())); }}> onClick={() => { dispatch(init(this.emptyTool())); }}>