Skip to content

Commit 20e4044

Browse files
✨ Feat(web): Add migrate forward/backward functionality if a someday event is focused (#601)
* feat(web): Add migrate forward/backward functionality if a someday event is focused * chore(web): Add TODO for date validation in SomedayEventContainer tests
1 parent 637da24 commit 20e4044

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

packages/web/src/views/Calendar/components/Sidebar/SomedayTab/SomedayEvents/SomedayEventContainer/SomedayEventContainer.test.tsx

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,130 @@ describe("SomedayEventContainer keyboard interactions", () => {
8484
Categories_Event.SOMEDAY_WEEK,
8585
);
8686
});
87+
88+
it("migrates event to Someday Week when Meta+Ctrl+ArrowUp is pressed", async () => {
89+
const onSubmit = jest.fn();
90+
const contextValue = {
91+
state: {
92+
draft: null,
93+
isDrafting: false,
94+
isOverGrid: false,
95+
isSomedayFormOpen: false,
96+
} as any,
97+
setters: {
98+
setIsSomedayFormOpen: jest.fn(),
99+
} as any,
100+
actions: {
101+
onDraft: jest.fn(),
102+
onMigrate: jest.fn(),
103+
discard: jest.fn(),
104+
reset: jest.fn(),
105+
closeForm: jest.fn(),
106+
close: jest.fn(),
107+
onSubmit,
108+
} as any,
109+
};
110+
111+
const weekViewRange = { startDate: "2020-01-05", endDate: "2020-01-11" };
112+
113+
render(
114+
<SidebarDraftContext.Provider value={contextValue as any}>
115+
<SomedayEventContainer
116+
category={Categories_Event.SOMEDAY_MONTH}
117+
event={LEARN_CHINESE}
118+
isDrafting={false}
119+
isDragging={false}
120+
isOverGrid={false}
121+
onSubmit={onSubmit}
122+
provided={
123+
{
124+
draggableProps: {
125+
"data-rfd-draggable-context-id": "mock-context",
126+
"data-rfd-draggable-id": "mock-id",
127+
style: {},
128+
},
129+
dragHandleProps: null,
130+
innerRef: jest.fn(),
131+
} as DraggableProvided
132+
}
133+
snapshot={{ isDragging: false } as DraggableStateSnapshot}
134+
setEvent={jest.fn()}
135+
weekViewRange={weekViewRange}
136+
/>
137+
</SidebarDraftContext.Provider>,
138+
);
139+
140+
const btn = document.querySelector(
141+
`[data-event-id="${LEARN_CHINESE._id}"]`,
142+
)! as HTMLElement;
143+
btn.focus();
144+
fireEvent.keyDown(btn, { key: "ArrowUp", metaKey: true, ctrlKey: true });
145+
146+
expect(onSubmit).toHaveBeenCalledTimes(1);
147+
148+
// TODO: Do a date validation
149+
});
150+
151+
it("migrates event to Someday Month when Meta+Ctrl+ArrowDown is pressed", async () => {
152+
const onSubmit = jest.fn();
153+
const contextValue = {
154+
state: {
155+
draft: null,
156+
isDrafting: false,
157+
isOverGrid: false,
158+
isSomedayFormOpen: false,
159+
} as any,
160+
setters: {
161+
setIsSomedayFormOpen: jest.fn(),
162+
} as any,
163+
actions: {
164+
onDraft: jest.fn(),
165+
onMigrate: jest.fn(),
166+
discard: jest.fn(),
167+
reset: jest.fn(),
168+
closeForm: jest.fn(),
169+
close: jest.fn(),
170+
onSubmit,
171+
} as any,
172+
};
173+
174+
const weekViewRange = { startDate: "2020-01-01", endDate: "2020-01-07" };
175+
176+
render(
177+
<SidebarDraftContext.Provider value={contextValue as any}>
178+
<SomedayEventContainer
179+
category={Categories_Event.SOMEDAY_WEEK}
180+
event={LEARN_CHINESE}
181+
isDrafting={false}
182+
isDragging={false}
183+
isOverGrid={false}
184+
onSubmit={onSubmit}
185+
provided={
186+
{
187+
draggableProps: {
188+
"data-rfd-draggable-context-id": "mock-context",
189+
"data-rfd-draggable-id": "mock-id",
190+
style: {},
191+
},
192+
dragHandleProps: null,
193+
innerRef: jest.fn(),
194+
} as DraggableProvided
195+
}
196+
snapshot={{ isDragging: false } as DraggableStateSnapshot}
197+
setEvent={jest.fn()}
198+
weekViewRange={weekViewRange}
199+
/>
200+
</SidebarDraftContext.Provider>,
201+
);
202+
203+
const btn = document.querySelector(
204+
`[data-event-id="${LEARN_CHINESE._id}"]`,
205+
)! as HTMLElement;
206+
btn.focus();
207+
fireEvent.keyDown(btn, { key: "ArrowDown", metaKey: true, ctrlKey: true });
208+
209+
expect(onSubmit).toHaveBeenCalledTimes(1);
210+
211+
// TODO: Do a date validation
212+
});
87213
});

packages/web/src/views/Calendar/components/Sidebar/SomedayTab/SomedayEvents/SomedayEventContainer/SomedayEventContainer.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { useState } from "react";
2+
import { toast } from "react-toastify";
23
import { Key } from "ts-key-enum";
34
import { FloatingFocusManager, FloatingPortal } from "@floating-ui/react";
45
import { DraggableProvided, DraggableStateSnapshot } from "@hello-pangea/dnd";
56
import { Priorities } from "@core/constants/core.constants";
67
import { Categories_Event, Schema_Event } from "@core/types/event.types";
8+
import { computeCurrentEventDateRange } from "@web/common/utils/web.date.util";
79
import { useDraftForm } from "@web/views/Calendar/components/Draft/hooks/state/useDraftForm";
810
import { useSidebarContext } from "@web/views/Calendar/components/Draft/sidebar/context/useSidebarContext";
911
import { Setters_Sidebar } from "@web/views/Calendar/components/Draft/sidebar/hooks/useSidebarState";
@@ -53,10 +55,44 @@ export const SomedayEventContainer = ({
5355
const [isFocused, setIsFocused] = useState(false);
5456

5557
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
58+
// ENTER opens the edit form
5659
if (e.key === Key.Enter) {
5760
e.preventDefault();
5861
e.stopPropagation();
5962
actions.onDraft(event, category);
63+
return;
64+
}
65+
66+
// META + CTRL + UP/DOWN should migrate the event between Someday lists
67+
const isMetaCtrl = e.metaKey && e.ctrlKey;
68+
const isArrowUp = e.key === "ArrowUp";
69+
const isArrowDown = e.key === "ArrowDown";
70+
71+
if (isMetaCtrl && (isArrowUp || isArrowDown)) {
72+
e.preventDefault();
73+
e.stopPropagation();
74+
75+
// Prevent migrating recurring events
76+
const canMigrate =
77+
!event.recurrence?.rule || event.recurrence?.rule.length === 0;
78+
79+
if (!canMigrate) {
80+
toast.error("Can't migrate recurring events");
81+
return;
82+
}
83+
84+
const duration = isArrowUp ? "week" : "month";
85+
const targetCategory = isArrowUp
86+
? Categories_Event.SOMEDAY_WEEK
87+
: Categories_Event.SOMEDAY_MONTH;
88+
89+
const updatedEvent = computeCurrentEventDateRange(
90+
{ duration },
91+
event,
92+
weekViewRange,
93+
);
94+
95+
actions.onSubmit(targetCategory, updatedEvent);
6096
}
6197
};
6298

0 commit comments

Comments
 (0)