show hidden and empty items in calendar
This commit is contained in:
parent
7a88a1f900
commit
2ddc5b16e8
|
@ -9,6 +9,8 @@ import {
|
|||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import * as moment from "moment";
|
||||
import { countBy } from "lodash";
|
||||
import { TimeUnit } from "../../interfaces";
|
||||
|
||||
describe("mapStateToProps()", () => {
|
||||
function testState(time: number) {
|
||||
|
@ -108,15 +110,24 @@ describe("mapStateToProps()", () => {
|
|||
});
|
||||
|
||||
describe("mapResourcesToCalendar(): sequence farm events", () => {
|
||||
function fakeSeqFEResources() {
|
||||
interface EventData {
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
repeat?: number;
|
||||
time_unit?: TimeUnit;
|
||||
}
|
||||
|
||||
function fakeSeqFEResources(props: EventData) {
|
||||
const sequence = fakeSequence();
|
||||
sequence.body.id = 1;
|
||||
sequence.body.body = [{ kind: "take_photo", args: {} }];
|
||||
|
||||
const sequenceFarmEvent = fakeFarmEvent("Sequence", 1);
|
||||
sequenceFarmEvent.body.id = 1;
|
||||
sequenceFarmEvent.body.start_time = "2017-12-20T01:02:00.000Z";
|
||||
sequenceFarmEvent.body.end_time = "2017-12-20T01:05:00.000Z";
|
||||
sequenceFarmEvent.body.start_time = props.start_time;
|
||||
sequenceFarmEvent.body.end_time = props.end_time;
|
||||
sequenceFarmEvent.body.repeat = props.repeat || 1;
|
||||
sequenceFarmEvent.body.time_unit = props.time_unit || "never";
|
||||
|
||||
return buildResourceIndex([sequence, sequenceFarmEvent]);
|
||||
}
|
||||
|
@ -136,12 +147,47 @@ describe("mapResourcesToCalendar(): sequence farm events", () => {
|
|||
year: 17
|
||||
}];
|
||||
|
||||
it("returns calendar rows", () => {
|
||||
it("returns calendar rows: single event", () => {
|
||||
const eventData: EventData = {
|
||||
start_time: "2017-12-20T01:02:00.000Z",
|
||||
end_time: "2017-12-20T01:05:00.000Z"
|
||||
};
|
||||
const testTime = moment("2017-12-15T01:00:00.000Z");
|
||||
const calendar = mapResourcesToCalendar(
|
||||
fakeSeqFEResources().index, testTime);
|
||||
fakeSeqFEResources(eventData).index, testTime);
|
||||
expect(calendar.getAll()).toEqual(fakeSequenceFE);
|
||||
});
|
||||
|
||||
it("returns calendar rows: hidden items", () => {
|
||||
const eventData: EventData = {
|
||||
start_time: "2017-12-20T01:02:00.000Z",
|
||||
end_time: "2017-12-20T04:05:00.000Z",
|
||||
repeat: 1,
|
||||
time_unit: "minutely"
|
||||
};
|
||||
const testTime = moment("2017-12-15T01:00:00.000Z");
|
||||
const calendar = mapResourcesToCalendar(
|
||||
fakeSeqFEResources(eventData).index, testTime);
|
||||
const dayOneItems = calendar.getAll()[0].items;
|
||||
expect(countBy(dayOneItems, "heading")).toEqual({
|
||||
"fake": 59,
|
||||
"+ 123 more: fake": 1
|
||||
});
|
||||
});
|
||||
|
||||
it("returns calendar rows: empty", () => {
|
||||
const eventData: EventData = {
|
||||
start_time: "2017-12-20T01:02:00.000Z",
|
||||
end_time: "2019-12-20T01:05:00.000Z",
|
||||
repeat: 100,
|
||||
time_unit: "yearly"
|
||||
};
|
||||
const testTime = moment("2017-12-30T01:00:00.000Z");
|
||||
const calendar = mapResourcesToCalendar(
|
||||
fakeSeqFEResources(eventData).index, testTime);
|
||||
const dayOneItems = calendar.getAll()[0].items;
|
||||
expect(countBy(dayOneItems, "heading")).toEqual({ "*Empty*": 1 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapResourcesToCalendar(): regimen farm events", () => {
|
||||
|
|
|
@ -15,4 +15,17 @@ describe("occurrence", () => {
|
|||
expect(t.heading).toBe(fe.executable.name);
|
||||
expect(t.id).toBe(fe.id);
|
||||
});
|
||||
|
||||
it("builds entry with modified heading: hidden items", () => {
|
||||
const fe = fakeFarmEventWithExecutable();
|
||||
fe.executable.name = "Fake Sequence";
|
||||
const t = occurrence(TIME.MONDAY, fe, 0, { numHidden: 10 });
|
||||
expect(t.heading).toBe("+ 10 more: Fake Sequence");
|
||||
});
|
||||
|
||||
it("builds entry with modified heading: no items", () => {
|
||||
const fe = fakeFarmEventWithExecutable();
|
||||
const t = occurrence(TIME.MONDAY, fe, 0, { empty: true });
|
||||
expect(t.heading).toBe("*Empty*");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -30,9 +30,9 @@ describe("scheduler", () => {
|
|||
startTime: tuesday,
|
||||
endTime: thursday
|
||||
});
|
||||
expect(result1[0].format("dd")).toEqual("Tu");
|
||||
expect(result1[0].hour()).toEqual(4);
|
||||
expect(result1.length).toEqual(16);
|
||||
expect(result1.items[0].format("dd")).toEqual("Tu");
|
||||
expect(result1.items[0].hour()).toEqual(4);
|
||||
expect(result1.items.length).toEqual(16);
|
||||
const EXPECTED = [
|
||||
"04:00am Tu",
|
||||
"08:00am Tu",
|
||||
|
@ -51,156 +51,197 @@ describe("scheduler", () => {
|
|||
"12:00pm Th",
|
||||
"04:00pm Th"
|
||||
];
|
||||
const REALITY = result1.map(x => x.format("hh:mma dd"));
|
||||
const REALITY = result1.items.map(x => x.format("hh:mma dd"));
|
||||
EXPECTED.map(x => expect(REALITY).toContain(x));
|
||||
});
|
||||
});
|
||||
|
||||
function testSchedule(
|
||||
description: string,
|
||||
fakeEvent: TimeLine,
|
||||
timeNow: Moment,
|
||||
expected: Moment[]) {
|
||||
describe("scheduleForFarmEvent", () => {
|
||||
interface TestScheduleProps {
|
||||
description: string;
|
||||
fakeEvent: TimeLine;
|
||||
timeNow: Moment;
|
||||
expected: Moment[];
|
||||
shortenedBy: number;
|
||||
}
|
||||
|
||||
function testSchedule(props: TestScheduleProps) {
|
||||
const { description, fakeEvent, timeNow, expected, shortenedBy } = props;
|
||||
it(description, () => {
|
||||
const result = scheduleForFarmEvent(fakeEvent, timeNow);
|
||||
expect(result.length).toEqual(expected.length);
|
||||
expect(result.items.length).toEqual(expected.length);
|
||||
expected.map((expectation, index) => {
|
||||
expect(result[index]).toBeSameTimeAs(expectation);
|
||||
expect(result.items[index]).toBeSameTimeAs(expectation);
|
||||
});
|
||||
expect(result.shortenedBy).toEqual(shortenedBy);
|
||||
});
|
||||
}
|
||||
|
||||
const singleFarmEvent: TimeLine = {
|
||||
"start_time": "2017-08-01T17:00:00.000Z",
|
||||
"end_time": "2017-08-01T18:00:00.000Z",
|
||||
"repeat": 1,
|
||||
"time_unit": "never"
|
||||
start_time: "2017-08-01T17:00:00.000Z",
|
||||
end_time: "2017-08-01T18:00:00.000Z",
|
||||
repeat: 1,
|
||||
time_unit: "never"
|
||||
};
|
||||
|
||||
testSchedule("schedules a FarmEvent",
|
||||
const scheduleTestData: TestScheduleProps[] = [
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-07T05:00:00.000Z",
|
||||
"repeat": 2,
|
||||
"time_unit": "daily"
|
||||
description: "schedules a FarmEvent",
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-07T05:00:00.000Z",
|
||||
repeat: 2,
|
||||
time_unit: "daily"
|
||||
},
|
||||
timeNow: moment("2017-08-01T16:30:00.000Z"),
|
||||
expected: [
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-03T17:30:00.000Z"),
|
||||
moment("2017-08-05T17:30:00.000Z")
|
||||
],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-01T16:30:00.000Z"),
|
||||
[
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-03T17:30:00.000Z"),
|
||||
moment("2017-08-05T17:30:00.000Z")
|
||||
]);
|
||||
|
||||
testSchedule("handles 0 as a repeat value",
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-07T05:00:00.000Z",
|
||||
"repeat": 0,
|
||||
"time_unit": "daily"
|
||||
description: "handles 0 as a repeat value",
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-07T05:00:00.000Z",
|
||||
repeat: 0,
|
||||
time_unit: "daily"
|
||||
},
|
||||
timeNow: moment("2017-08-01T16:30:00.000Z"),
|
||||
expected: [moment("2017-08-01T17:30:00.000Z")],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-01T16:30:00.000Z"),
|
||||
[moment("2017-08-01T17:30:00.000Z")]);
|
||||
|
||||
testSchedule("handles start_time in the past",
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-09T05:00:00.000Z",
|
||||
"repeat": 2,
|
||||
"time_unit": "daily"
|
||||
description: "handles start_time in the past",
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-09T05:00:00.000Z",
|
||||
repeat: 2,
|
||||
time_unit: "daily"
|
||||
},
|
||||
timeNow: moment("2017-08-03T18:30:00.000Z"),
|
||||
expected: [
|
||||
moment("2017-08-05T17:30:00.000Z"),
|
||||
moment("2017-08-07T17:30:00.000Z")
|
||||
],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-03T18:30:00.000Z"),
|
||||
[
|
||||
moment("2017-08-05T17:30:00.000Z"),
|
||||
moment("2017-08-07T17:30:00.000Z")
|
||||
]);
|
||||
|
||||
testSchedule("handles start_time in the past: no repeat",
|
||||
singleFarmEvent,
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
[moment("2017-08-01T17:00:00.000Z")]);
|
||||
|
||||
testSchedule(`uses grace period (${gracePeriodSeconds}s)`,
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-02T05:00:00.000Z",
|
||||
"repeat": 4,
|
||||
"time_unit": "hourly"
|
||||
description: "handles start_time in the past: no repeat",
|
||||
fakeEvent: singleFarmEvent,
|
||||
timeNow: moment("2017-08-01T17:30:00.000Z"),
|
||||
expected: [moment("2017-08-01T17:00:00.000Z")],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-01T17:30:00.000Z").add(gracePeriodSeconds / 2, "seconds"),
|
||||
[
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z"),
|
||||
moment("2017-08-02T01:30:00.000Z")
|
||||
]);
|
||||
|
||||
testSchedule(`uses grace period (${gracePeriodSeconds}s): no repeat`,
|
||||
singleFarmEvent,
|
||||
moment("2017-08-01T17:00:00.000Z").add(gracePeriodSeconds / 2, "seconds"),
|
||||
[moment("2017-08-01T17:00:00.000Z")]);
|
||||
|
||||
testSchedule("farm event over",
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-02T05:00:00.000Z",
|
||||
"repeat": 4,
|
||||
"time_unit": "hourly"
|
||||
description: `uses grace period (${gracePeriodSeconds}s)`,
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-02T05:00:00.000Z",
|
||||
repeat: 4,
|
||||
time_unit: "hourly"
|
||||
},
|
||||
timeNow: moment("2017-08-01T17:30:00.000Z")
|
||||
.add(gracePeriodSeconds / 2, "seconds"),
|
||||
expected: [
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z"),
|
||||
moment("2017-08-02T01:30:00.000Z")
|
||||
],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-03T17:30:30.000Z"),
|
||||
[]);
|
||||
|
||||
testSchedule("farm event over: no repeat",
|
||||
singleFarmEvent,
|
||||
moment("2017-08-01T19:00:00.000Z"),
|
||||
[]);
|
||||
|
||||
testSchedule(`first ${maxDisplayItems} items`,
|
||||
{
|
||||
"start_time": "2017-08-02T17:00:00.000Z",
|
||||
"end_time": "2017-08-02T19:00:00.000Z",
|
||||
"repeat": 1,
|
||||
"time_unit": "minutely"
|
||||
description: `uses grace period (${gracePeriodSeconds}s): no repeat`,
|
||||
fakeEvent: singleFarmEvent,
|
||||
timeNow: moment("2017-08-01T17:00:00.000Z")
|
||||
.add(gracePeriodSeconds / 2, "seconds"),
|
||||
expected: [moment("2017-08-01T17:00:00.000Z")],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-01T15:30:00.000Z"),
|
||||
range(0, maxDisplayItems)
|
||||
.map((x: number) =>
|
||||
moment(`2017-08-02T17:${padStart("" + x, 2, "0")}:00.000Z`)));
|
||||
|
||||
testSchedule(`only ${maxDisplayItems} items`,
|
||||
{
|
||||
"start_time": "2017-08-02T16:00:00.000Z",
|
||||
"end_time": "2017-08-02T21:00:00.000Z",
|
||||
"repeat": 1,
|
||||
"time_unit": "minutely"
|
||||
description: "farm event over",
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-02T05:00:00.000Z",
|
||||
repeat: 4,
|
||||
time_unit: "hourly"
|
||||
},
|
||||
timeNow: moment("2017-08-03T17:30:30.000Z"),
|
||||
expected: [],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-02T17:00:00.000Z").add(gracePeriodSeconds, "seconds"),
|
||||
range(0, maxDisplayItems)
|
||||
.map((x: number) =>
|
||||
moment(`2017-08-02T17:${padStart("" + x, 2, "0")}:00.000Z`)));
|
||||
|
||||
testSchedule("item at end time is not rendered",
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-02T01:30:00.000Z",
|
||||
"repeat": 4,
|
||||
"time_unit": "hourly"
|
||||
description: "farm event over: no repeat",
|
||||
fakeEvent: singleFarmEvent,
|
||||
timeNow: moment("2017-08-01T19:00:00.000Z"),
|
||||
expected: [],
|
||||
shortenedBy: 0
|
||||
},
|
||||
moment("2017-08-01T16:30:00.000Z"),
|
||||
[
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z")
|
||||
]);
|
||||
|
||||
testSchedule(`renders item at grace period (${gracePeriodSeconds}s) cutoff`,
|
||||
{
|
||||
"start_time": "2017-08-01T17:30:00.000Z",
|
||||
"end_time": "2017-08-02T01:30:00.000Z",
|
||||
"repeat": 4,
|
||||
"time_unit": "hourly"
|
||||
description: `first ${maxDisplayItems} items`,
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-02T17:00:00.000Z",
|
||||
end_time: "2017-08-02T19:00:00.000Z",
|
||||
repeat: 1,
|
||||
time_unit: "minutely"
|
||||
},
|
||||
timeNow: moment("2017-08-01T15:30:00.000Z"),
|
||||
expected: range(0, maxDisplayItems)
|
||||
.map((x: number) =>
|
||||
moment(`2017-08-02T17:${padStart("" + x, 2, "0")}:00.000Z`)),
|
||||
shortenedBy: 120 - maxDisplayItems
|
||||
},
|
||||
moment("2017-08-01T17:30:00.000Z").add(gracePeriodSeconds, "seconds"),
|
||||
[
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z")
|
||||
]);
|
||||
{
|
||||
description: `only ${maxDisplayItems} items`,
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-02T16:00:00.000Z",
|
||||
end_time: "2017-08-02T21:00:00.000Z",
|
||||
repeat: 1,
|
||||
time_unit: "minutely"
|
||||
},
|
||||
timeNow: moment("2017-08-02T17:00:00.000Z")
|
||||
.add(gracePeriodSeconds, "seconds"),
|
||||
expected: range(0, maxDisplayItems)
|
||||
.map((x: number) =>
|
||||
moment(`2017-08-02T17:${padStart("" + x, 2, "0")}:00.000Z`)),
|
||||
shortenedBy: 240 - maxDisplayItems
|
||||
},
|
||||
{
|
||||
description: "item at end time is not rendered",
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-02T01:30:00.000Z",
|
||||
repeat: 4,
|
||||
time_unit: "hourly"
|
||||
},
|
||||
timeNow: moment("2017-08-01T16:30:00.000Z"),
|
||||
expected: [
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z")
|
||||
],
|
||||
shortenedBy: 0
|
||||
},
|
||||
{
|
||||
description: `shows item at grace period (${gracePeriodSeconds}s) cutoff`,
|
||||
fakeEvent: {
|
||||
start_time: "2017-08-01T17:30:00.000Z",
|
||||
end_time: "2017-08-02T01:30:00.000Z",
|
||||
repeat: 4,
|
||||
time_unit: "hourly"
|
||||
},
|
||||
timeNow: moment("2017-08-01T17:30:00.000Z")
|
||||
.add(gracePeriodSeconds, "seconds"),
|
||||
expected: [
|
||||
moment("2017-08-01T17:30:00.000Z"),
|
||||
moment("2017-08-01T21:30:00.000Z")
|
||||
],
|
||||
shortenedBy: 0
|
||||
},
|
||||
];
|
||||
|
||||
scheduleTestData.map(testCaseData => testSchedule(testCaseData));
|
||||
});
|
||||
|
||||
describe("farmEventIntervalSeconds", () => {
|
||||
|
|
|
@ -6,15 +6,27 @@ import { Calendar } from "./index";
|
|||
/** An occurrence is a single event on the calendar, usually rendered as a
|
||||
* little white square on the farm event UI. This is the data representation for
|
||||
* single calendar entries. */
|
||||
export function occurrence(m: moment.Moment,
|
||||
export function occurrence(
|
||||
m: moment.Moment,
|
||||
fe: FarmEventWithExecutable,
|
||||
utcOffset: number):
|
||||
utcOffset: number,
|
||||
modifiers?: { numHidden?: number, empty?: boolean }):
|
||||
CalendarOccurrence {
|
||||
const normalHeading = fe.executable.name || fe.executable_type;
|
||||
const heading = () => {
|
||||
if (modifiers && modifiers.empty) {
|
||||
return "*Empty*";
|
||||
}
|
||||
if (modifiers && modifiers.numHidden) {
|
||||
return `+ ${modifiers.numHidden} more: ` + normalHeading;
|
||||
}
|
||||
return normalHeading;
|
||||
};
|
||||
return {
|
||||
mmddyy: m.format(Calendar.DATE_FORMAT),
|
||||
sortKey: m.unix(),
|
||||
timeStr: m.clone().utcOffset(utcOffset).format("hh:mma"),
|
||||
heading: fe.executable.name || fe.executable_type,
|
||||
heading: heading(),
|
||||
executableId: fe.executable_id || 0,
|
||||
id: fe.id || 0,
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ export function scheduler({
|
|||
currentTime,
|
||||
endTime,
|
||||
intervalSeconds
|
||||
}: SchedulerProps): Moment[] {
|
||||
}: SchedulerProps): { items: Moment[], shortenedBy: number } {
|
||||
// Convert from Moment to seconds.
|
||||
const eventStartTime = startTime.unix();
|
||||
const eventEndTime = endTime.unix();
|
||||
|
@ -44,10 +44,16 @@ export function scheduler({
|
|||
? itemEndTime
|
||||
: eventEndTime;
|
||||
|
||||
// Calculate the number of future items hidden from the calendar.
|
||||
const shortenedBy = Math.ceil(
|
||||
Math.abs(eventEndTime - lastItemTime) / intervalSeconds);
|
||||
|
||||
/** Generate the list of Farm Event items to display
|
||||
* and convert from seconds back to Moment. */
|
||||
return range(nextItemTime, lastItemTime, intervalSeconds)
|
||||
const items = range(nextItemTime, lastItemTime, intervalSeconds)
|
||||
.map(x => moment.unix(x));
|
||||
|
||||
return { items, shortenedBy };
|
||||
}
|
||||
|
||||
/** Translate farmbot interval names to momentjs interval names */
|
||||
|
@ -88,12 +94,14 @@ export interface TimeLine {
|
|||
/** Takes a subset of FarmEvent<Sequence> data and generates a list of dates. */
|
||||
export function scheduleForFarmEvent(
|
||||
{ start_time, end_time, repeat, time_unit }: TimeLine, timeNow = moment()
|
||||
): Moment[] {
|
||||
): { items: Moment[], shortenedBy: number } {
|
||||
const interval = repeat && farmEventIntervalSeconds(repeat, time_unit);
|
||||
const gracePeriod = timeNow.clone().subtract(gracePeriodSeconds, "seconds");
|
||||
|
||||
// Farm event is over.
|
||||
if (moment(end_time).isBefore(gracePeriod)) { return []; }
|
||||
if (moment(end_time).isBefore(gracePeriod)) {
|
||||
return { items: [], shortenedBy: 0 };
|
||||
}
|
||||
|
||||
if (interval && (time_unit !== NEVER)) {
|
||||
// Repeating event.
|
||||
|
@ -103,9 +111,9 @@ export function scheduleForFarmEvent(
|
|||
endTime: end_time ? moment(end_time) : nextYear(),
|
||||
intervalSeconds: interval
|
||||
});
|
||||
return schedule;
|
||||
return { items: schedule.items, shortenedBy: schedule.shortenedBy };
|
||||
} else {
|
||||
// Non-repeating event.
|
||||
return [moment(start_time)];
|
||||
return { items: [moment(start_time)], shortenedBy: 0 };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
|
|||
this.setState({ specialStatusLocal: SpecialStatus.SAVED });
|
||||
history.push("/app/designer/farm_events");
|
||||
const frmEvnt = this.props.farmEvent;
|
||||
const nextRun = _.first(scheduleForFarmEvent(frmEvnt.body));
|
||||
const nextRun = _.first(scheduleForFarmEvent(frmEvnt.body).items);
|
||||
if (nextRun) {
|
||||
// TODO: Internationalizing this will be a challenge.
|
||||
success(`This Farm Event will run ${nextRun.fromNow()}, but
|
||||
|
|
|
@ -76,6 +76,21 @@ export let regimenCalendarAdder = (index: ResourceIndex) =>
|
|||
|
||||
export let addSequenceToCalendar =
|
||||
(f: FarmEventWithSequence, c: Calendar, now = moment(), offset: number) => {
|
||||
scheduleForFarmEvent(f, now)
|
||||
.map(m => c.insert(occurrence(m, f, offset)));
|
||||
const schedule = scheduleForFarmEvent(f, now);
|
||||
// Display empty calendars in UI so that they can be edited or deleted.
|
||||
if (f.end_time && schedule.items.length === 0) {
|
||||
c.insert(occurrence(moment(f.end_time), f, offset, { empty: true }));
|
||||
}
|
||||
// Separate the last item from the calendar.
|
||||
const lastItem = schedule.items.pop();
|
||||
// Add all other items.
|
||||
schedule.items.map(m => c.insert(occurrence(m, f, offset)));
|
||||
if (schedule.shortenedBy > 0) {
|
||||
// Indicate that not all items are displayed in the final item.
|
||||
lastItem && c.insert(occurrence(
|
||||
lastItem, f, offset, { numHidden: schedule.shortenedBy }));
|
||||
} else {
|
||||
// Add the final item. All items are displayed.
|
||||
lastItem && c.insert(occurrence(lastItem, f, offset));
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue