@@ -13,6 +13,8 @@ import { TaskType, Task, taskUrgency } from "task.json";
1313import { DateTime } from "luxon" ;
1414import { useDispatch , useSelector } from "react-redux" ;
1515import { rootActions , RootState } from "../store" ;
16+ import { useState } from "react" ;
17+ import ConfirmationDialog from "./ConfirmationDialog" ;
1618
1719interface Props {
1820 onAdd : ( ) => void ;
@@ -81,12 +83,11 @@ const CustomToolbar = (props: CustomToolbarProps) => {
8183
8284
8385interface 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
9293const 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
213214function 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