1- import { useQuery , useMutation , gql } from "@apollo/client" ;
1+ import { useQuery , useMutation , gql , useApolloClient } from "@apollo/client" ;
22import React , { useState , useEffect , useCallback } from "react" ;
33
44import Link from "@mui/material/Link" ;
@@ -32,13 +32,35 @@ import {
3232 DialogActions ,
3333 DialogContent ,
3434 DialogTitle ,
35+ useTheme ,
3536} from "@mui/material" ;
3637import { useAuth } from "../lib/auth" ;
3738import { GoogleSignin } from "./login" ;
3839import { timeDifference } from "../lib/utils" ;
40+ import { useSnackbar } from "notistack" ;
3941
40- function RepoLine ( { repo, deletable, sharable, runtimeInfo, onDeleteRepo } ) {
42+ const GET_REPOS = gql `
43+ query GetRepos {
44+ myRepos {
45+ name
46+ id
47+ public
48+ updatedAt
49+ createdAt
50+ }
51+ }
52+ ` ;
53+
54+ function RepoLine ( {
55+ repo,
56+ deletable,
57+ sharable,
58+ runtimeInfo,
59+ onDeleteRepo,
60+ deleting,
61+ } ) {
4162 const { me } = useMe ( ) ;
63+ const theme = useTheme ( ) ;
4264 const [ killRuntime ] = useMutation (
4365 gql `
4466 mutation killRuntime($sessionId: String!) {
@@ -50,14 +72,25 @@ function RepoLine({ repo, deletable, sharable, runtimeInfo, onDeleteRepo }) {
5072 }
5173 ) ;
5274
75+ // haochen: any reason not using Loading state from useMutation?
5376 const [ killing , setKilling ] = useState ( false ) ;
5477 return (
5578 < TableRow
5679 key = { repo . id }
5780 sx = { { "&:last-child td, &:last-child th" : { border : 0 } } }
5881 >
5982 < TableCell align = "center" >
60- < Link component = { ReactLink } to = { `/repo/${ repo . id } ` } >
83+ < Link
84+ component = { ReactLink }
85+ to = { `/repo/${ repo . id } ` }
86+ sx = {
87+ deleting && {
88+ color : theme . palette . action . disabled ,
89+ textDecorationColor : theme . palette . action . disabled ,
90+ pointerEvents : "none" ,
91+ }
92+ }
93+ >
6194 < Box
6295 sx = { {
6396 display : "flex" ,
@@ -94,20 +127,25 @@ function RepoLine({ repo, deletable, sharable, runtimeInfo, onDeleteRepo }) {
94127 { deletable && (
95128 < Tooltip title = "Delete Repo" >
96129 < IconButton
130+ disabled = { deleting }
97131 size = "small"
98132 onClick = { ( ) => {
99133 // FIXME ensure the runtime is killed
100134 onDeleteRepo ( repo ) ;
101135 } }
102136 >
103- < DeleteIcon fontSize = "inherit" />
137+ { deleting ? (
138+ < CircularProgress size = "14px" />
139+ ) : (
140+ < DeleteIcon fontSize = "inherit" />
141+ ) }
104142 </ IconButton >
105143 </ Tooltip >
106144 ) }
107145 { runtimeInfo ? (
108146 < Tooltip title = "Kill runtime" >
109147 < IconButton
110- disabled = { killing }
148+ disabled = { killing || deleting }
111149 size = "small"
112150 onClick = { async ( ) => {
113151 // FIXME when to set killing=false?
@@ -202,14 +240,29 @@ function RepoList({ repos }) {
202240 const [ clickedRepo , setClickedRepo ] = useState <
203241 { id : string ; name : string } | undefined
204242 > ( ) ;
205- const [ deleteRepo ] = useMutation (
243+ const [ isConfirmDeleteDialogOpen , setConfirmDeleteDialogOpen ] =
244+ useState ( false ) ;
245+ const { enqueueSnackbar } = useSnackbar ( ) ;
246+ const client = useApolloClient ( ) ;
247+ const [ deleteRepo , deleteRepoResult ] = useMutation (
206248 gql `
207249 mutation deleteRepo($id: ID!) {
208250 deleteRepo(id: $id)
209251 }
210252 ` ,
211253 {
212- refetchQueries : [ "GetRepos" ] ,
254+ onCompleted ( ) {
255+ client . writeQuery ( {
256+ query : GET_REPOS ,
257+ data : {
258+ myRepos : repos . filter ( ( repo ) => repo . id !== clickedRepo ?. id ) ,
259+ } ,
260+ } ) ;
261+ enqueueSnackbar ( "Successfully deleted repo" , { variant : "success" } ) ;
262+ } ,
263+ onError ( ) {
264+ enqueueSnackbar ( "Failed to delete repo" , { variant : "error" } ) ;
265+ } ,
213266 }
214267 ) ;
215268 // FIXME once ttl is reached, the runtime is killed, but this query is not
@@ -224,13 +277,14 @@ function RepoList({ repos }) {
224277 ` ) ;
225278
226279 const onConfirmDeleteRepo = useCallback ( ( ) => {
280+ setConfirmDeleteDialogOpen ( false ) ;
227281 deleteRepo ( {
228282 variables : {
229283 id : clickedRepo ?. id ,
230284 } ,
231- } ) ;
232- setClickedRepo ( undefined ) ;
233- } , [ clickedRepo , deleteRepo ] ) ;
285+ } ) . then ( ( ) => setClickedRepo ( undefined ) ) ;
286+ } , [ clickedRepo ?. id , deleteRepo ] ) ;
287+
234288 return (
235289 < >
236290 < TableContainer component = { Paper } >
@@ -249,6 +303,9 @@ function RepoList({ repos }) {
249303 < RepoLine
250304 repo = { repo }
251305 deletable = { true }
306+ deleting = {
307+ repo . id === clickedRepo ?. id && deleteRepoResult . loading
308+ }
252309 sharable = { true }
253310 runtimeInfo = {
254311 loading
@@ -258,34 +315,30 @@ function RepoList({ repos }) {
258315 )
259316 }
260317 key = { repo . id }
261- onDeleteRepo = { setClickedRepo }
318+ onDeleteRepo = { ( repo ) => {
319+ setClickedRepo ( repo ) ;
320+ setConfirmDeleteDialogOpen ( true ) ;
321+ } }
262322 />
263323 ) ) }
264324 </ TableBody >
265325 </ Table >
266326 </ TableContainer >
267327 < ConfirmDeleteDialog
268328 repoName = { clickedRepo ?. name }
269- open = { Boolean ( clickedRepo ) }
270- handleCancel = { ( ) => setClickedRepo ( undefined ) }
329+ open = { isConfirmDeleteDialogOpen }
330+ handleCancel = { ( ) => {
331+ setClickedRepo ( undefined ) ;
332+ setConfirmDeleteDialogOpen ( false ) ;
333+ } }
271334 handleConfirm = { onConfirmDeleteRepo }
272335 />
273336 </ >
274337 ) ;
275338}
276339
277340function MyRepos ( ) {
278- const { loading, error, data } = useQuery ( gql `
279- query GetRepos {
280- myRepos {
281- name
282- id
283- public
284- updatedAt
285- createdAt
286- }
287- }
288- ` ) ;
341+ const { loading, error, data } = useQuery ( GET_REPOS ) ;
289342
290343 if ( loading ) {
291344 return < CircularProgress /> ;
0 commit comments