@@ -11,6 +11,7 @@ import {
11
11
renameProject ,
12
12
} from '../../../../common/api/db' ;
13
13
import { invalidateAllCaches , maybeAxiosError } from '../../../../common/api/utils' ;
14
+ import * as Panel from '../PanelUtils' ;
14
15
15
16
import ProjectForm , { ProjectFormValues } from './ProjectForm' ;
16
17
@@ -40,36 +41,53 @@ export default function ProjectListItem({
40
41
onToggleEditMode,
41
42
} : ProjectListItemProps ) {
42
43
const [ submitError , setSubmitError ] = useState < string | null > ( null ) ;
44
+ const [ loading , setLoading ] = useState ( false ) ;
43
45
44
- const handleSubmitRename = async ( values : ProjectFormValues ) => {
45
- try {
46
+ const handleSubmitAction = ( actionType : 'rename' | 'duplicate' ) => {
47
+ return async ( values : ProjectFormValues ) => {
48
+ setLoading ( true ) ;
46
49
setSubmitError ( null ) ;
47
-
48
- if ( ! values . filename ) {
49
- setSubmitError ( 'Filename cannot be blank' ) ;
50
- return ;
50
+ try {
51
+ if ( ! values . filename ) {
52
+ setSubmitError ( 'Filename cannot be blank' ) ;
53
+ return ;
54
+ }
55
+ const action = actionType === 'rename' ? renameProject : duplicateProject ;
56
+ await action ( filename , values . filename ) ;
57
+ await onRefetch ( ) ;
58
+ onSubmit ( ) ;
59
+ } catch ( error ) {
60
+ setSubmitError ( maybeAxiosError ( error ) ) ;
61
+ } finally {
62
+ setLoading ( false ) ;
51
63
}
52
- await renameProject ( filename , values . filename ) ;
64
+ } ;
65
+ } ;
66
+
67
+ const handleLoad = async ( filename : string ) => {
68
+ setLoading ( true ) ;
69
+ setSubmitError ( null ) ;
70
+ try {
71
+ await loadProject ( filename ) ;
53
72
await onRefetch ( ) ;
54
- onSubmit ( ) ;
73
+ await invalidateAllCaches ( ) ;
55
74
} catch ( error ) {
56
75
setSubmitError ( maybeAxiosError ( error ) ) ;
76
+ } finally {
77
+ setLoading ( false ) ;
57
78
}
58
79
} ;
59
80
60
- const handleSubmitDuplicate = async ( values : ProjectFormValues ) => {
81
+ const handleDelete = async ( filename : string ) => {
82
+ setLoading ( true ) ;
83
+ setSubmitError ( null ) ;
61
84
try {
62
- setSubmitError ( null ) ;
63
-
64
- if ( ! values . filename ) {
65
- setSubmitError ( 'Filename cannot be blank' ) ;
66
- return ;
67
- }
68
- await duplicateProject ( filename , values . filename ) ;
85
+ await deleteProject ( filename ) ;
69
86
await onRefetch ( ) ;
70
- onSubmit ( ) ;
71
87
} catch ( error ) {
72
88
setSubmitError ( maybeAxiosError ( error ) ) ;
89
+ } finally {
90
+ setLoading ( false ) ;
73
91
}
74
92
} ;
75
93
@@ -86,50 +104,55 @@ export default function ProjectListItem({
86
104
const classes = current && ! isCurrentlyBeingEdited ? style . current : undefined ;
87
105
88
106
return (
89
- < tr key = { filename } className = { classes } >
90
- { isCurrentlyBeingEdited ? (
91
- < td colSpan = { 99 } >
92
- < ProjectForm
93
- action = { editingMode }
94
- filename = { filename }
95
- onSubmit = { editingMode === 'duplicate' ? handleSubmitDuplicate : handleSubmitRename }
96
- onCancel = { handleCancel }
97
- submitError = { submitError }
98
- />
99
- </ td >
100
- ) : (
101
- < >
102
- < td className = { style . containCell } > { filename } </ td >
103
- < td > { new Date ( updatedAt ) . toLocaleString ( ) } </ td >
104
- < td className = { style . actionButton } >
105
- < ActionMenu
106
- current = { current }
107
+ < >
108
+ { submitError && (
109
+ < tr key = 'filename-error' >
110
+ < td colSpan = { 99 } >
111
+ < Panel . Error > { submitError } </ Panel . Error >
112
+ </ td >
113
+ </ tr >
114
+ ) }
115
+ < tr key = { filename } className = { classes } >
116
+ { isCurrentlyBeingEdited ? (
117
+ < td colSpan = { 99 } >
118
+ < ProjectForm
119
+ action = { editingMode }
107
120
filename = { filename }
108
- onChangeEditMode = { handleToggleEditMode }
109
- onRefetch = { onRefetch }
121
+ onSubmit = { editingMode === 'duplicate' ? handleSubmitAction ( 'duplicate' ) : handleSubmitAction ( 'rename' ) }
122
+ onCancel = { handleCancel }
110
123
/>
111
124
</ td >
112
- </ >
113
- ) }
114
- </ tr >
125
+ ) : (
126
+ < >
127
+ < td className = { style . containCell } > { filename } </ td >
128
+ < td > { new Date ( updatedAt ) . toLocaleString ( ) } </ td >
129
+ < td className = { style . actionButton } >
130
+ < ActionMenu
131
+ current = { current }
132
+ filename = { filename }
133
+ onChangeEditMode = { handleToggleEditMode }
134
+ onDelete = { handleDelete }
135
+ onLoad = { handleLoad }
136
+ isDisabled = { loading }
137
+ />
138
+ </ td >
139
+ </ >
140
+ ) }
141
+ </ tr >
142
+ </ >
115
143
) ;
116
144
}
117
145
118
- function ActionMenu ( {
119
- current,
120
- filename,
121
- onChangeEditMode,
122
- onRefetch,
123
- } : {
146
+ interface ActionMenuProps {
124
147
current ?: boolean ;
125
148
filename : string ;
149
+ isDisabled : boolean ;
126
150
onChangeEditMode : ( editMode : EditMode , filename : string ) => void ;
127
- onRefetch : ( ) => Promise < void > ;
128
- } ) {
129
- const handleLoad = async ( ) => {
130
- await loadProject ( filename ) ;
131
- await invalidateAllCaches ( ) ;
132
- } ;
151
+ onDelete : ( filename : string ) => void ;
152
+ onLoad : ( filename : string ) => void ;
153
+ }
154
+ function ActionMenu ( props : ActionMenuProps ) {
155
+ const { current, filename, isDisabled, onChangeEditMode, onDelete, onLoad } = props ;
133
156
134
157
const handleRename = ( ) => {
135
158
onChangeEditMode ( 'rename' , filename ) ;
@@ -139,11 +162,6 @@ function ActionMenu({
139
162
onChangeEditMode ( 'duplicate' , filename ) ;
140
163
} ;
141
164
142
- const handleDelete = async ( ) => {
143
- await deleteProject ( filename ) ;
144
- await onRefetch ( ) ;
145
- } ;
146
-
147
165
const handleDownload = async ( ) => {
148
166
await downloadProject ( filename ) ;
149
167
} ;
@@ -161,16 +179,17 @@ function ActionMenu({
161
179
color = '#e2e2e2' // $gray-200
162
180
variant = 'ontime-ghosted'
163
181
size = 'sm'
182
+ isDisabled = { isDisabled }
164
183
/>
165
184
< MenuList >
166
- < MenuItem onClick = { handleLoad } isDisabled = { current } >
185
+ < MenuItem onClick = { ( ) => onLoad ( filename ) } isDisabled = { current } >
167
186
Load
168
187
</ MenuItem >
169
188
< MenuItem onClick = { handleRename } > Rename</ MenuItem >
170
189
< MenuItem onClick = { handleDuplicate } > Duplicate</ MenuItem >
171
190
< MenuItem onClick = { handleDownload } > Download</ MenuItem >
172
191
< MenuItem onClick = { handleExportCSV } > Export CSV Rundown</ MenuItem >
173
- < MenuItem isDisabled = { current } onClick = { handleDelete } >
192
+ < MenuItem isDisabled = { current } onClick = { ( ) => onDelete ( filename ) } >
174
193
Delete
175
194
</ MenuItem >
176
195
</ MenuList >
0 commit comments