Merge pull request #1285 from gabrielburnworth/staging
Prevent saving of empty Farm Eventspull/1286/head
commit
8bc3849e6c
|
@ -23,16 +23,15 @@ import { isString, isFunction } from "lodash";
|
|||
import { repeatOptions } from "../map_state_to_props_add_edit";
|
||||
import { SpecialStatus, ParameterApplication } from "farmbot";
|
||||
import moment from "moment";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { history } from "../../../history";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { fakeVariableNameSet } from "../../../__test_support__/fake_variables";
|
||||
import { clickButton } from "../../../__test_support__/helpers";
|
||||
import { destroy } from "../../../api/crud";
|
||||
import { destroy, save } from "../../../api/crud";
|
||||
import { fakeTimeSettings } from "../../../__test_support__/fake_time_settings";
|
||||
import { error, success, warning } from "../../../toast/toast";
|
||||
import { error, success } from "../../../toast/toast";
|
||||
|
||||
const mockSequence = fakeSequence();
|
||||
|
||||
|
@ -275,10 +274,14 @@ describe("<FarmEventForm/>", () => {
|
|||
|
||||
it("warns about missed regimen items", async () => {
|
||||
const p = props();
|
||||
const state = fakeState();
|
||||
state.resources.index.references = { [p.farmEvent.uuid]: p.farmEvent };
|
||||
p.dispatch = jest.fn(x => { isFunction(x) && x(); return Promise.resolve(); });
|
||||
p.farmEvent.body.executable_type = "Regimen";
|
||||
const regimen = fakeRegimen();
|
||||
regimen.body.regimen_items = [
|
||||
{ sequence_id: -1, time_offset: 0 },
|
||||
{ sequence_id: -1, time_offset: 1000000000 },
|
||||
];
|
||||
p.findExecutable = () => regimen;
|
||||
p.dispatch = jest.fn(x => { isFunction(x) && x(); return Promise.resolve(); });
|
||||
p.farmEvent.body.start_time = "2017-05-22T05:00:00.000Z";
|
||||
p.farmEvent.body.end_time = "2017-05-22T06:00:00.000Z";
|
||||
const i = instance(p);
|
||||
|
@ -334,14 +337,15 @@ describe("<FarmEventForm/>", () => {
|
|||
expectStartTimeToBeRejected();
|
||||
});
|
||||
|
||||
it("doesn't display error message on edit: start time has passed", () => {
|
||||
it("displays error message on edit: start time has passed", () => {
|
||||
const p = props();
|
||||
p.title = "edit";
|
||||
p.farmEvent.body.start_time = "2017-05-22T05:00:00.000Z";
|
||||
p.farmEvent.body.end_time = "2017-05-22T06:00:00.000Z";
|
||||
const i = instance(p);
|
||||
i.commitViewModel(moment("2017-06-22T05:00:00.000Z"));
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
expect(error).toHaveBeenCalledWith(expect.stringContaining(
|
||||
"Nothing to run."), "Unable to save event.");
|
||||
});
|
||||
|
||||
it("displays error message on save: no items", async () => {
|
||||
|
@ -351,8 +355,22 @@ describe("<FarmEventForm/>", () => {
|
|||
p.farmEvent.body.end_time = "2017-05-22T06:00:00.000Z";
|
||||
const i = instance(p);
|
||||
await i.commitViewModel(moment("2017-06-22T05:00:00.000Z"));
|
||||
expect(warning).toHaveBeenCalledWith(expect.stringContaining(
|
||||
"Nothing to run."));
|
||||
expect(error).toHaveBeenCalledWith(expect.stringContaining(
|
||||
"Nothing to run."), "Unable to save event.");
|
||||
});
|
||||
|
||||
it("displays error message on save: save error", async () => {
|
||||
const p = props();
|
||||
p.dispatch = jest.fn()
|
||||
.mockResolvedValueOnce("")
|
||||
.mockRejectedValueOnce("error");
|
||||
p.shouldDisplay = () => true;
|
||||
p.farmEvent.body.start_time = "2017-07-22T05:00:00.000Z";
|
||||
p.farmEvent.body.end_time = "2017-07-22T06:00:00.000Z";
|
||||
const i = instance(p);
|
||||
await i.commitViewModel(moment("2017-06-22T05:00:00.000Z"));
|
||||
await expect(save).toHaveBeenCalled();
|
||||
expect(error).toHaveBeenCalledWith("Unable to save event.");
|
||||
});
|
||||
|
||||
it("allows start time: edit with unsupported OS", () => {
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { maybeWarnAboutMissedTasks } from "../util";
|
||||
import { fakeFarmEvent } from "../../../__test_support__/fake_state/resources";
|
||||
import moment from "moment";
|
||||
import { ExecutableType } from "farmbot/dist/resources/api_resources";
|
||||
|
||||
describe("maybeWarnAboutMissedTasks()", () => {
|
||||
function testWarn(time: string): () => void {
|
||||
function testWarn(
|
||||
time: string, executableType: ExecutableType = "Regimen"
|
||||
): () => void {
|
||||
const callback = jest.fn();
|
||||
const fe = fakeFarmEvent("Regimen", 1);
|
||||
const fe = fakeFarmEvent(executableType, 1);
|
||||
fe.body.start_time = "2017-05-21T22:00:00.000";
|
||||
maybeWarnAboutMissedTasks(fe,
|
||||
() => callback("missed event warning"),
|
||||
|
@ -21,4 +24,9 @@ describe("maybeWarnAboutMissedTasks()", () => {
|
|||
const cb = testWarn("2017-05-01T22:00:00.000");
|
||||
expect(cb).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("doesn't warn when not a regimen", () => {
|
||||
const cb = testWarn("2017-05-21T22:00:00.000", "Sequence");
|
||||
expect(cb).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react";
|
||||
import moment from "moment";
|
||||
import { success, error, warning } from "../../toast/toast";
|
||||
import { success, error } from "../../toast/toast";
|
||||
import {
|
||||
TaggedFarmEvent, SpecialStatus, TaggedSequence, TaggedRegimen,
|
||||
ParameterApplication
|
||||
|
@ -94,6 +94,13 @@ const startTimeWarning = () => {
|
|||
error(message, title);
|
||||
};
|
||||
|
||||
const nothingToRunWarning = () => {
|
||||
const message =
|
||||
t("All items scheduled before the start time. Nothing to run.");
|
||||
const title = t("Unable to save event.");
|
||||
error(message, title);
|
||||
};
|
||||
|
||||
type RecombineOptions = { forceRegimensToMidnight: boolean };
|
||||
|
||||
/** Take a FormViewModel and recombine the fields into a FarmEvent
|
||||
|
@ -323,9 +330,8 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
|
|||
return recombine(vm, opts);
|
||||
}
|
||||
|
||||
/** Use the next item run time to display toast messages and return to
|
||||
* the form if necessary. */
|
||||
nextRunTimeActions = (now = moment()): boolean => {
|
||||
/** Use the next item run time to display toast messages. */
|
||||
nextRunTimeActions = (now = moment()) => {
|
||||
const nextRun = this.nextItemTime(this.props.farmEvent.body, now);
|
||||
if (nextRun) {
|
||||
const nextRunText = this.props.autoSyncEnabled
|
||||
|
@ -335,10 +341,6 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
|
|||
you must first SYNC YOUR DEVICE. If you do not sync, the event will
|
||||
not run.`.replace(/\s+/g, " "), { timeFromNow: nextRun.from(now) });
|
||||
success(nextRunText);
|
||||
return true;
|
||||
} else {
|
||||
warning(t("All items scheduled before the start time. Nothing to run."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,24 +348,27 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
|
|||
* - Regimen Farm Event:
|
||||
* * If scheduled for today, warn about the possibility of missing tasks.
|
||||
* * Display the start time difference from now and maybe prompt to sync.
|
||||
* * Return to calendar view if items exist to be run past the start time.
|
||||
* * Return to calendar view.
|
||||
* - Sequence Farm Event:
|
||||
* * Determine the time for the next item to be run.
|
||||
* * If auto-sync is disabled, prompt the user to sync.
|
||||
* * Return to calendar view only if more items exist to be run.
|
||||
* * Return to calendar view.
|
||||
*/
|
||||
commitViewModel = (now = moment()) => {
|
||||
if (this.maybeRejectStartTime(this.updatedFarmEvent)) {
|
||||
return startTimeWarning();
|
||||
}
|
||||
if (!this.nextItemTime(this.updatedFarmEvent, now)) {
|
||||
return nothingToRunWarning();
|
||||
}
|
||||
this.dispatch(overwrite(this.props.farmEvent, this.updatedFarmEvent));
|
||||
this.dispatch(save(this.props.farmEvent.uuid))
|
||||
.then(() => {
|
||||
this.setState({ specialStatusLocal: SpecialStatus.SAVED });
|
||||
this.dispatch(maybeWarnAboutMissedTasks(this.props.farmEvent,
|
||||
() => alert(t(Content.REGIMEN_TODAY_SKIPPED_ITEM_RISK)), now));
|
||||
const itemsScheduled = this.nextRunTimeActions(now);
|
||||
if (itemsScheduled) { history.push("/app/designer/events"); }
|
||||
this.nextRunTimeActions(now);
|
||||
history.push("/app/designer/events");
|
||||
})
|
||||
.catch(() => {
|
||||
error(t("Unable to save event."));
|
||||
|
|
Loading…
Reference in New Issue