Skip to content

Commit 4f06341

Browse files
committed
fix: add confirmation for erasing and fix some bugs
1 parent 08c4809 commit 4f06341

File tree

2 files changed

+166
-132
lines changed

2 files changed

+166
-132
lines changed

src/components/SettingsDialog.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ function SettingsDialog(props: Props) {
119119
};
120120

121121
const clearData = () => {
122+
setConfirmationDialog(false);
122123
dispatch(rootActions.setTaskJson(initTaskJson()));
123124
dispatch(rootActions.addNotification({
124125
severity: "success",

src/components/TaskList.tsx

Lines changed: 165 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { TaskType, Task, taskUrgency } from "task.json";
1313
import { DateTime } from "luxon";
1414
import { useDispatch, useSelector } from "react-redux";
1515
import { rootActions, RootState } from "../store";
16+
import { useState } from "react";
17+
import ConfirmationDialog from "./ConfirmationDialog";
1618

1719
interface Props {
1820
onAdd: () => void;
@@ -81,12 +83,11 @@ const CustomToolbar = (props: CustomToolbarProps) => {
8183

8284

8385
interface CustomToolbarSelectProps {
84-
selectedIds: string[];
8586
taskType: TaskType;
86-
onRemove: (ids: string[]) => void;
87-
onErase: (ids: string[]) => void;
88-
onUndo: (ids: string[]) => void;
89-
onDo: (ids: string[]) => void;
87+
onRemove: () => void;
88+
onErase: () => void;
89+
onUndo: () => void;
90+
onDo: () => void;
9091
};
9192

9293
const CustomToolbarSelect = (props: CustomToolbarSelectProps) => {
@@ -98,7 +99,7 @@ const CustomToolbarSelect = (props: CustomToolbarSelectProps) => {
9899
<Tooltip title="Undo Tasks">
99100
<IconButton
100101
className={classes.add}
101-
onClick={() => props.onUndo(props.selectedIds)}
102+
onClick={props.onUndo}
102103
>
103104
<RestoreIcon />
104105
</IconButton>
@@ -108,7 +109,7 @@ const CustomToolbarSelect = (props: CustomToolbarSelectProps) => {
108109
<Tooltip title="Do Tasks">
109110
<IconButton
110111
className={classes.add}
111-
onClick={() => props.onDo(props.selectedIds)}
112+
onClick={props.onDo}
112113
>
113114
<CheckIcon />
114115
</IconButton>
@@ -118,7 +119,7 @@ const CustomToolbarSelect = (props: CustomToolbarSelectProps) => {
118119
<Tooltip title="Remove Tasks">
119120
<IconButton
120121
className={classes.del}
121-
onClick={() => props.onRemove(props.selectedIds)}
122+
onClick={props.onRemove}
122123
>
123124
<DeleteIcon />
124125
</IconButton>
@@ -128,7 +129,7 @@ const CustomToolbarSelect = (props: CustomToolbarSelectProps) => {
128129
<Tooltip title="Erase Tasks">
129130
<IconButton
130131
className={classes.del}
131-
onClick={() => props.onErase(props.selectedIds)}
132+
onClick={props.onErase}
132133
>
133134
<CloseIcon />
134135
</IconButton>
@@ -211,6 +212,9 @@ const Actions = (props: ActionsProps) => {
211212
};
212213

213214
function TaskList(props: Props) {
215+
const [confirmationText, setConfirmationText] = useState("");
216+
const [confirmationDialog, setConfirmationDialog] = useState(false);
217+
const [eraseIds, setEraseIds] = useState([] as string[]);
214218
const classes = useStyles();
215219
const dispatch = useDispatch();
216220

@@ -248,8 +252,17 @@ function TaskList(props: Props) {
248252
}
249253
};
250254

251-
const eraseTasks = (ids: string[]) => {
252-
dispatch(rootActions.eraseTasks(ids));
255+
const handleEraseCancel = () => {
256+
setConfirmationDialog(false);
257+
};
258+
const handleErase = (ids: string[]) => {
259+
setEraseIds(ids);
260+
setConfirmationText("Warning: This will delete tasks permanently. Make sure the erased tasks are not in other servers and clients if you want to sync with them. Are you sure to erase?");
261+
setConfirmationDialog(true);
262+
};
263+
const eraseTasks = () => {
264+
setConfirmationDialog(false);
265+
dispatch(rootActions.eraseTasks(eraseIds));
253266
};
254267

255268
const undoTasks = (ids: string[]) => {
@@ -281,130 +294,150 @@ function TaskList(props: Props) {
281294
};
282295

283296
return (
284-
<MUIDataTable
285-
title=""
286-
options={{
287-
print: false,
288-
download: false,
289-
customToolbar: () => {
290-
return <CustomToolbar onAdd={props.onAdd} />
291-
},
292-
customToolbarSelect: (selectedRows) => {
293-
const ids = selectedRows.data.map(({ dataIndex }) => tasks[dataIndex].id);
294-
return (
295-
<CustomToolbarSelect
296-
taskType={props.taskType}
297-
selectedIds={ids}
298-
onRemove={removeTasks}
299-
onErase={eraseTasks}
300-
onUndo={undoTasks}
301-
onDo={doTasks}
302-
/>
303-
);
304-
}
305-
}}
306-
columns={[
307-
{
308-
name: "priority",
309-
label: "P",
310-
options: {
311-
sortThirdClickReset: true,
312-
sortCompare(order) {
313-
return (obj1, obj2) => {
314-
const a: string = obj1.data;
315-
const b: string = obj2.data;
316-
let result = 0;
317-
if (a === undefined)
318-
result = -1;
319-
if (b === undefined)
320-
result = 1;
321-
if (a < b)
322-
result = 1;
323-
else if (a > b)
324-
result = -1;
325-
326-
return result * (order === "asc" ? 1 : -1);
327-
};
328-
},
329-
customBodyRenderLite: index => (
330-
<span className={colorTask(tasks[index])}>{tasks[index].priority}</span>
331-
)
332-
}
333-
},
334-
{
335-
name: "text",
336-
label: "Text",
337-
options: {
338-
filterType: "textField",
339-
sort: false,
340-
customBodyRenderLite: index => (
341-
<span className={colorTask(tasks[index])}>{tasks[index].text}</span>
342-
)
343-
}
344-
},
345-
{
346-
name: "projects",
347-
label: "Projects",
348-
options: {
349-
filterType: "multiselect",
350-
sort: false,
351-
customBodyRenderLite: index => (
352-
<>
353-
{tasks[index].projects?.map(proj => (
354-
<Chip className={classes.chip} label={proj} key={proj} />
355-
))}
356-
</>
357-
)
358-
}
359-
},
360-
{
361-
name: "contexts",
362-
label: "Contexts",
363-
options: {
364-
filterType: "multiselect",
365-
sort: false,
366-
customBodyRenderLite: index => (
367-
<>
368-
{tasks[index].contexts?.map(ctx => (
369-
<Chip className={classes.chip} label={ctx} key={ctx} />
370-
))}
371-
</>
372-
)
373-
}
374-
},
375-
{
376-
name: "due",
377-
label: "Due",
378-
options: {
379-
sortThirdClickReset: true,
380-
filterType: "textField",
381-
customBodyRenderLite: index => (
382-
<span className={colorTask(tasks[index])}>{tasks[index].due}</span>
383-
)
384-
}
385-
},
386-
{
387-
name: "actions",
388-
label: "Actions",
389-
options: {
390-
empty: true,
391-
sort: false,
392-
customBodyRenderLite: index => (
393-
<Actions
297+
<>
298+
<ConfirmationDialog
299+
open={confirmationDialog}
300+
text={confirmationText}
301+
onCancel={handleEraseCancel}
302+
onConfirm={eraseTasks}
303+
/>
304+
<MUIDataTable
305+
title=""
306+
options={{
307+
print: false,
308+
download: false,
309+
customToolbar: () => {
310+
return <CustomToolbar onAdd={props.onAdd} />
311+
},
312+
customToolbarSelect: (selectedRows, _, setSelectedRows) => {
313+
const ids = selectedRows.data.map(({ dataIndex }) => tasks[dataIndex].id);
314+
return (
315+
<CustomToolbarSelect
394316
taskType={props.taskType}
395-
task={tasks[index]}
396-
onEdit={props.onEdit}
397-
onRemove={removeTasks}
398-
onErase={eraseTasks}
399-
onUndo={undoTasks}
400-
onDo={doTasks}
317+
onRemove={() => {
318+
setSelectedRows([]);
319+
removeTasks(ids);
320+
}}
321+
onErase={() => {
322+
// When focus is lost, the selected rows will be cleared automatically
323+
// setSelectedRows([]);
324+
handleErase(ids);
325+
}}
326+
onUndo={() => {
327+
setSelectedRows([]);
328+
undoTasks(ids);
329+
}}
330+
onDo={() => {
331+
setSelectedRows([]);
332+
doTasks(ids);
333+
}}
401334
/>
402-
)
335+
);
336+
}
337+
}}
338+
columns={[
339+
{
340+
name: "priority",
341+
label: "P",
342+
options: {
343+
sortThirdClickReset: true,
344+
sortCompare(order) {
345+
return (obj1, obj2) => {
346+
const a: string = obj1.data;
347+
const b: string = obj2.data;
348+
let result = 0;
349+
if (a === undefined)
350+
result = -1;
351+
if (b === undefined)
352+
result = 1;
353+
if (a < b)
354+
result = 1;
355+
else if (a > b)
356+
result = -1;
357+
358+
return result * (order === "asc" ? 1 : -1);
359+
};
360+
},
361+
customBodyRenderLite: index => (
362+
<span className={colorTask(tasks[index])}>{tasks[index].priority}</span>
363+
)
364+
}
365+
},
366+
{
367+
name: "text",
368+
label: "Text",
369+
options: {
370+
filterType: "textField",
371+
sort: false,
372+
customBodyRenderLite: index => (
373+
<span className={colorTask(tasks[index])}>{tasks[index].text}</span>
374+
)
375+
}
376+
},
377+
{
378+
name: "projects",
379+
label: "Projects",
380+
options: {
381+
filterType: "multiselect",
382+
sort: false,
383+
customBodyRenderLite: index => (
384+
<>
385+
{tasks[index].projects?.map(proj => (
386+
<Chip className={classes.chip} label={proj} key={proj} />
387+
))}
388+
</>
389+
)
390+
}
391+
},
392+
{
393+
name: "contexts",
394+
label: "Contexts",
395+
options: {
396+
filterType: "multiselect",
397+
sort: false,
398+
customBodyRenderLite: index => (
399+
<>
400+
{tasks[index].contexts?.map(ctx => (
401+
<Chip className={classes.chip} label={ctx} key={ctx} />
402+
))}
403+
</>
404+
)
405+
}
406+
},
407+
{
408+
name: "due",
409+
label: "Due",
410+
options: {
411+
sortThirdClickReset: true,
412+
filterType: "textField",
413+
customBodyRenderLite: index => (
414+
<span className={colorTask(tasks[index])}>{tasks[index].due}</span>
415+
)
416+
}
417+
},
418+
{
419+
name: "actions",
420+
label: "Actions",
421+
options: {
422+
empty: true,
423+
sort: false,
424+
customBodyRenderLite: index => (
425+
<Actions
426+
taskType={props.taskType}
427+
task={tasks[index]}
428+
onEdit={props.onEdit}
429+
onRemove={removeTasks}
430+
onErase={handleErase}
431+
onUndo={undoTasks}
432+
onDo={doTasks}
433+
/>
434+
)
435+
}
403436
}
404-
}
405-
]}
406-
data={tasks}
407-
/>
437+
]}
438+
data={tasks}
439+
/>
440+
</>
408441
);
409442
}
410443

0 commit comments

Comments
 (0)