11import { useQuery , useMutation , gql } from "@apollo/client" ;
2- import React , { useState , useEffect } from "react" ;
2+ import React , { useState , useEffect , useCallback } from "react" ;
33
44import Link from "@mui/material/Link" ;
55import { Link as ReactLink } from "react-router-dom" ;
@@ -26,23 +26,19 @@ import Chip from "@mui/material/Chip";
2626import { ShareProjDialog } from "../components/ShareProjDialog" ;
2727import useMe from "../lib/me" ;
2828import { getUpTime } from "../lib/utils" ;
29- import { Button } from "@mui/material" ;
29+ import {
30+ Button ,
31+ Dialog ,
32+ DialogActions ,
33+ DialogContent ,
34+ DialogTitle ,
35+ } from "@mui/material" ;
3036import { useAuth } from "../lib/auth" ;
3137import { GoogleSignin } from "./login" ;
3238import { timeDifference } from "../lib/utils" ;
3339
34- function RepoLine ( { repo, deletable, sharable, runtimeInfo } ) {
40+ function RepoLine ( { repo, deletable, sharable, runtimeInfo, onDeleteRepo } ) {
3541 const { me } = useMe ( ) ;
36- const [ deleteRepo ] = useMutation (
37- gql `
38- mutation deleteRepo($id: ID!) {
39- deleteRepo(id: $id)
40- }
41- ` ,
42- {
43- refetchQueries : [ "GetRepos" ] ,
44- }
45- ) ;
4642 const [ killRuntime ] = useMutation (
4743 gql `
4844 mutation killRuntime($sessionId: String!) {
@@ -99,13 +95,9 @@ function RepoLine({ repo, deletable, sharable, runtimeInfo }) {
9995 < Tooltip title = "Delete Repo" >
10096 < IconButton
10197 size = "small"
102- onClick = { async ( ) => {
98+ onClick = { ( ) => {
10399 // FIXME ensure the runtime is killed
104- deleteRepo ( {
105- variables : {
106- id : repo . id ,
107- } ,
108- } ) ;
100+ onDeleteRepo ( repo ) ;
109101 } }
110102 >
111103 < DeleteIcon fontSize = "inherit" />
@@ -207,6 +199,19 @@ function CreateRepoForm(props) {
207199
208200function RepoList ( { repos } ) {
209201 const { me } = useMe ( ) ;
202+ const [ clickedRepo , setClickedRepo ] = useState <
203+ { id : string ; name : string } | undefined
204+ > ( ) ;
205+ const [ deleteRepo ] = useMutation (
206+ gql `
207+ mutation deleteRepo($id: ID!) {
208+ deleteRepo(id: $id)
209+ }
210+ ` ,
211+ {
212+ refetchQueries : [ "GetRepos" ] ,
213+ }
214+ ) ;
210215 // FIXME once ttl is reached, the runtime is killed, but this query is not
211216 // updated.
212217 const { loading, data } = useQuery ( gql `
@@ -217,37 +222,55 @@ function RepoList({ repos }) {
217222 }
218223 }
219224 ` ) ;
225+
226+ const onConfirmDeleteRepo = useCallback ( ( ) => {
227+ deleteRepo ( {
228+ variables : {
229+ id : clickedRepo ?. id ,
230+ } ,
231+ } ) ;
232+ setClickedRepo ( undefined ) ;
233+ } , [ clickedRepo , deleteRepo ] ) ;
220234 return (
221- < TableContainer component = { Paper } >
222- < Table >
223- < TableHead >
224- < TableRow >
225- < TableCell align = "left" > Name</ TableCell >
226- < TableCell align = "left" > Visibility</ TableCell >
227- < TableCell align = "left" > Status (TTL: 12h)</ TableCell >
228- < TableCell align = "left" > Last Viewed</ TableCell >
229- < TableCell align = "left" > Operations</ TableCell >
230- </ TableRow >
231- </ TableHead >
232- < TableBody >
233- { repos . map ( ( repo ) => (
234- < RepoLine
235- repo = { repo }
236- deletable = { true }
237- sharable = { true }
238- runtimeInfo = {
239- loading
240- ? null
241- : data . listAllRuntimes . find (
242- ( { sessionId } ) => sessionId === `${ me . id } _${ repo . id } `
243- )
244- }
245- key = { repo . id }
246- />
247- ) ) }
248- </ TableBody >
249- </ Table >
250- </ TableContainer >
235+ < >
236+ < TableContainer component = { Paper } >
237+ < Table >
238+ < TableHead >
239+ < TableRow >
240+ < TableCell align = "left" > Name</ TableCell >
241+ < TableCell align = "left" > Visibility</ TableCell >
242+ < TableCell align = "left" > Status (TTL: 12h)</ TableCell >
243+ < TableCell align = "left" > Last Viewed</ TableCell >
244+ < TableCell align = "left" > Operations</ TableCell >
245+ </ TableRow >
246+ </ TableHead >
247+ < TableBody >
248+ { repos . map ( ( repo ) => (
249+ < RepoLine
250+ repo = { repo }
251+ deletable = { true }
252+ sharable = { true }
253+ runtimeInfo = {
254+ loading
255+ ? null
256+ : data . listAllRuntimes . find (
257+ ( { sessionId } ) => sessionId === `${ me . id } _${ repo . id } `
258+ )
259+ }
260+ key = { repo . id }
261+ onDeleteRepo = { setClickedRepo }
262+ />
263+ ) ) }
264+ </ TableBody >
265+ </ Table >
266+ </ TableContainer >
267+ < ConfirmDeleteDialog
268+ repoName = { clickedRepo ?. name }
269+ open = { Boolean ( clickedRepo ) }
270+ handleCancel = { ( ) => setClickedRepo ( undefined ) }
271+ handleConfirm = { onConfirmDeleteRepo }
272+ />
273+ </ >
251274 ) ;
252275}
253276
@@ -403,6 +426,32 @@ function RepoLists() {
403426 ) ;
404427}
405428
429+ function ConfirmDeleteDialog ( {
430+ open,
431+ repoName,
432+ handleConfirm,
433+ handleCancel,
434+ } : {
435+ open : boolean ;
436+ repoName ?: string ;
437+ handleConfirm : ( ) => void ;
438+ handleCancel : ( ) => void ;
439+ } ) {
440+ const name = repoName ?? "Repo" ;
441+ return (
442+ < Dialog open = { open } onClose = { handleCancel } fullWidth >
443+ < DialogTitle > { `Delete ${ name } ` } </ DialogTitle >
444+ < DialogContent > Are you sure?</ DialogContent >
445+ < DialogActions >
446+ < Button onClick = { handleCancel } > Cancel</ Button >
447+ < Button onClick = { handleConfirm } autoFocus >
448+ Confirm
449+ </ Button >
450+ </ DialogActions >
451+ </ Dialog >
452+ ) ;
453+ }
454+
406455export default function Page ( ) {
407456 const { me } = useMe ( ) ;
408457 const { hasToken, loginGuest, isSignedIn } = useAuth ( ) ;
0 commit comments