@@ -241,11 +241,11 @@ function SubmissionReviewScoreTweak() {
241
241
</ Box >
242
242
) ;
243
243
}
244
- function SubmissionHistory ( { submission } : { submission : SubmissionWithFilesGraderResultsOutputTestsAndRubric } ) {
245
- const pathname = usePathname ( ) ;
246
- const invalidate = useInvalidate ( ) ;
247
- const router = useRouter ( ) ;
248
- const [ hasNewSubmission , setHasNewSubmission ] = useState < boolean > ( false ) ;
244
+ function SubmissionHistoryContents ( {
245
+ submission
246
+ } : {
247
+ submission : SubmissionWithFilesGraderResultsOutputTestsAndRubric ;
248
+ } ) {
249
249
const groupOrProfileFilter : CrudFilter = submission . assignment_group_id
250
250
? {
251
251
field : "assignment_group_id" ,
@@ -257,6 +257,7 @@ function SubmissionHistory({ submission }: { submission: SubmissionWithFilesGrad
257
257
operator : "eq" ,
258
258
value : submission . profile_id
259
259
} ;
260
+ const invalidate = useInvalidate ( ) ;
260
261
const { data, isLoading } = useList < SubmissionWithGraderResultsAndReview > ( {
261
262
resource : "submissions" ,
262
263
meta : {
@@ -280,10 +281,152 @@ function SubmissionHistory({ submission }: { submission: SubmissionWithFilesGrad
280
281
pageSize : 1000
281
282
}
282
283
} ) ;
284
+ const router = useRouter ( ) ;
285
+ const { time_zone } = useCourse ( ) ;
286
+ const [ isActivating , setIsActivating ] = useState ( false ) ;
287
+ const pathname = usePathname ( ) ;
288
+ const isGraderInterface = pathname . includes ( "/grade" ) ;
289
+ const { dueDate } = useAssignmentDueDate ( submission . assignments , {
290
+ studentPrivateProfileId : submission . profile_id || undefined ,
291
+ assignmentGroupId : submission . assignment_group_id || undefined
292
+ } ) ;
293
+ const isStaff = useIsGraderOrInstructor ( ) ;
294
+ const now = TZDate . tz ( time_zone ?? "America/New_York" ) . getTime ( ) ;
295
+ const disableActivationButton = Boolean ( dueDate && now > dueDate . getTime ( ) && ! isStaff ) ;
296
+ if ( isLoading ) {
297
+ return < Skeleton height = "100px" /> ;
298
+ }
299
+ return (
300
+ < >
301
+ < Text > Submission History</ Text >
302
+ < Box
303
+ maxHeight = "400px"
304
+ overflowY = "auto"
305
+ css = { {
306
+ "&::-webkit-scrollbar" : {
307
+ width : "8px"
308
+ } ,
309
+ "&::-webkit-scrollbar-track" : {
310
+ background : "#f1f1f1" ,
311
+ borderRadius : "4px"
312
+ } ,
313
+ "&::-webkit-scrollbar-thumb" : {
314
+ background : "#888" ,
315
+ borderRadius : "4px"
316
+ } ,
317
+ "&::-webkit-scrollbar-thumb:hover" : {
318
+ background : "#555"
319
+ }
320
+ } }
321
+ >
322
+ < Toaster />
323
+ < Table . Root >
324
+ < Table . Header >
325
+ < Table . Row >
326
+ < Table . ColumnHeader > #</ Table . ColumnHeader >
327
+ < Table . ColumnHeader > Date</ Table . ColumnHeader >
328
+ < Table . ColumnHeader > Auto Grader Score</ Table . ColumnHeader >
329
+ < Table . ColumnHeader > Total Score</ Table . ColumnHeader >
330
+ < Table . ColumnHeader > Actions</ Table . ColumnHeader >
331
+ </ Table . Row >
332
+ </ Table . Header >
333
+ < Table . Body >
334
+ { data ?. data . map ( ( historical_submission ) => {
335
+ const link = isGraderInterface
336
+ ? `/course/${ historical_submission . class_id } /grade/assignments/${ historical_submission . assignment_id } /submissions/${ historical_submission . id } `
337
+ : `/course/${ historical_submission . class_id } /assignments/${ historical_submission . assignment_id } /submissions/${ historical_submission . id } ` ;
338
+ return (
339
+ < Table . Row key = { historical_submission . id } bg = { pathname . startsWith ( link ) ? "bg.emphasized" : undefined } >
340
+ < Table . Cell >
341
+ < Link href = { link } >
342
+ { historical_submission . is_active && < ActiveSubmissionIcon /> }
343
+ { historical_submission . ordinal }
344
+ </ Link >
345
+ </ Table . Cell >
346
+ < Table . Cell >
347
+ < Link href = { link } >
348
+ { formatRelative (
349
+ new TZDate (
350
+ historical_submission . created_at || new Date ( ) . toUTCString ( ) ,
351
+ time_zone || "America/New_York"
352
+ ) ,
353
+ TZDate . tz ( time_zone || "America/New_York" )
354
+ ) }
355
+ </ Link >
356
+ </ Table . Cell >
357
+ < Table . Cell >
358
+ < Link href = { link } >
359
+ { ! historical_submission . grader_results
360
+ ? "In Progress"
361
+ : historical_submission . grader_results && historical_submission . grader_results . errors
362
+ ? "Error"
363
+ : `${ historical_submission . grader_results ?. score } /${ historical_submission . grader_results ?. max_score } ` }
364
+ </ Link >
365
+ </ Table . Cell >
366
+ < Table . Cell >
367
+ < Link href = { link } >
368
+ { historical_submission . submission_reviews ?. completed_at &&
369
+ historical_submission . submission_reviews ?. total_score +
370
+ "/" +
371
+ historical_submission . assignments . total_points }
372
+ </ Link >
373
+ </ Table . Cell >
374
+ < Table . Cell >
375
+ { historical_submission . is_active ? (
376
+ < > This submission is active</ >
377
+ ) : historical_submission . is_not_graded ? (
378
+ < > Not for grading</ >
379
+ ) : (
380
+ < Button
381
+ variant = "outline"
382
+ size = "xs"
383
+ disabled = { disableActivationButton }
384
+ loading = { isActivating }
385
+ onClick = { async ( ) => {
386
+ setIsActivating ( true ) ;
387
+ try {
388
+ const supabase = createClient ( ) ;
389
+ await activateSubmission ( { submission_id : historical_submission . id } , supabase ) ;
390
+ invalidate ( { resource : "submissions" , invalidates : [ "list" ] } ) ;
391
+ toaster . create ( {
392
+ title : "Active submission changed" ,
393
+ type : "success"
394
+ } ) ;
395
+ router . push ( link ) ;
396
+ } catch ( error ) {
397
+ const errorId = Sentry . captureException ( error ) ;
398
+ toaster . create ( {
399
+ title : "Error activating submission" ,
400
+ description : `We have recorded this error with trace ID: ${ errorId } ` ,
401
+ type : "error"
402
+ } ) ;
403
+ } finally {
404
+ setIsActivating ( false ) ;
405
+ }
406
+ } }
407
+ >
408
+ < Icon as = { FaCheckCircle } />
409
+ Activate
410
+ </ Button >
411
+ ) }
412
+ </ Table . Cell >
413
+ </ Table . Row >
414
+ ) ;
415
+ } ) }
416
+ </ Table . Body >
417
+ </ Table . Root >
418
+ </ Box >
419
+ </ >
420
+ ) ;
421
+ }
422
+ function SubmissionHistory ( { submission } : { submission : SubmissionWithFilesGraderResultsOutputTestsAndRubric } ) {
423
+ const invalidate = useInvalidate ( ) ;
424
+ const [ hasNewSubmission , setHasNewSubmission ] = useState < boolean > ( false ) ;
425
+
283
426
useList < Submission > ( {
284
427
resource : "submissions" ,
285
428
meta : {
286
- select : "* "
429
+ select : "id, assignment_group_id, profile_id, is_active "
287
430
} ,
288
431
filters : [
289
432
{
@@ -306,25 +449,12 @@ function SubmissionHistory({ submission }: { submission: SubmissionWithFilesGrad
306
449
invalidate ( { resource : "submissions" , invalidates : [ "list" ] } ) ;
307
450
}
308
451
} ) ;
309
- const { time_zone } = useCourse ( ) ;
310
- const [ isActivating , setIsActivating ] = useState ( false ) ;
311
- const isGraderInterface = pathname . includes ( "/grade" ) ;
312
- const { dueDate } = useAssignmentDueDate ( submission . assignments , {
313
- studentPrivateProfileId : submission . profile_id || undefined ,
314
- assignmentGroupId : submission . assignment_group_id || undefined
315
- } ) ;
316
- const isStaff = useIsGraderOrInstructor ( ) ;
317
- const disableActivationButton = Boolean (
318
- dueDate &&
319
- TZDate . tz ( time_zone ?? "America/New_York" ) . getTime ( ) >
320
- new TZDate ( dueDate , time_zone ?? "America/New_York" ) . getTime ( ) &&
321
- ! isStaff
322
- ) ;
323
- if ( isLoading || ! submission . assignments ) {
452
+
453
+ if ( ! submission . assignments ) {
324
454
return < Skeleton height = "20px" /> ;
325
455
}
326
456
return (
327
- < PopoverRoot >
457
+ < PopoverRoot lazyMount unmountOnExit >
328
458
< PopoverTrigger asChild >
329
459
< Button variant = { hasNewSubmission ? "solid" : "outline" } colorPalette = { hasNewSubmission ? "yellow" : "default" } >
330
460
< Icon as = { FaHistory } />
@@ -335,127 +465,7 @@ function SubmissionHistory({ submission }: { submission: SubmissionWithFilesGrad
335
465
< PopoverContent minWidth = { { base : "none" , md : "lg" } } >
336
466
< PopoverArrow />
337
467
< PopoverBody >
338
- < Text > Submission History</ Text >
339
- < Box
340
- maxHeight = "400px"
341
- overflowY = "auto"
342
- css = { {
343
- "&::-webkit-scrollbar" : {
344
- width : "8px"
345
- } ,
346
- "&::-webkit-scrollbar-track" : {
347
- background : "#f1f1f1" ,
348
- borderRadius : "4px"
349
- } ,
350
- "&::-webkit-scrollbar-thumb" : {
351
- background : "#888" ,
352
- borderRadius : "4px"
353
- } ,
354
- "&::-webkit-scrollbar-thumb:hover" : {
355
- background : "#555"
356
- }
357
- } }
358
- >
359
- < Toaster />
360
- < Table . Root >
361
- < Table . Header >
362
- < Table . Row >
363
- < Table . ColumnHeader > #</ Table . ColumnHeader >
364
- < Table . ColumnHeader > Date</ Table . ColumnHeader >
365
- < Table . ColumnHeader > Auto Grader Score</ Table . ColumnHeader >
366
- < Table . ColumnHeader > Total Score</ Table . ColumnHeader >
367
- < Table . ColumnHeader > Actions</ Table . ColumnHeader >
368
- </ Table . Row >
369
- </ Table . Header >
370
- < Table . Body >
371
- { data ?. data . map ( ( historical_submission ) => {
372
- const link = isGraderInterface
373
- ? `/course/${ historical_submission . class_id } /grade/assignments/${ historical_submission . assignment_id } /submissions/${ historical_submission . id } `
374
- : `/course/${ historical_submission . class_id } /assignments/${ historical_submission . assignment_id } /submissions/${ historical_submission . id } ` ;
375
- return (
376
- < Table . Row
377
- key = { historical_submission . id }
378
- bg = { pathname . startsWith ( link ) ? "bg.emphasized" : undefined }
379
- >
380
- < Table . Cell >
381
- < Link href = { link } >
382
- { historical_submission . is_active && < ActiveSubmissionIcon /> }
383
- { historical_submission . ordinal }
384
- </ Link >
385
- </ Table . Cell >
386
- < Table . Cell >
387
- < Link href = { link } >
388
- { formatRelative (
389
- new TZDate (
390
- historical_submission . created_at || new Date ( ) . toUTCString ( ) ,
391
- time_zone || "America/New_York"
392
- ) ,
393
- TZDate . tz ( time_zone || "America/New_York" )
394
- ) }
395
- </ Link >
396
- </ Table . Cell >
397
- < Table . Cell >
398
- < Link href = { link } >
399
- { ! historical_submission . grader_results
400
- ? "In Progress"
401
- : historical_submission . grader_results && historical_submission . grader_results . errors
402
- ? "Error"
403
- : `${ historical_submission . grader_results ?. score } /${ historical_submission . grader_results ?. max_score } ` }
404
- </ Link >
405
- </ Table . Cell >
406
- < Table . Cell >
407
- < Link href = { link } >
408
- { historical_submission . submission_reviews ?. completed_at &&
409
- historical_submission . submission_reviews ?. total_score +
410
- "/" +
411
- historical_submission . assignments . total_points }
412
- </ Link >
413
- </ Table . Cell >
414
- < Table . Cell >
415
- { historical_submission . is_active ? (
416
- < > This submission is active</ >
417
- ) : historical_submission . is_not_graded ? (
418
- < > Not for grading</ >
419
- ) : (
420
- < Button
421
- variant = "outline"
422
- size = "xs"
423
- disabled = { disableActivationButton }
424
- loading = { isActivating }
425
- onClick = { async ( ) => {
426
- setIsActivating ( true ) ;
427
- try {
428
- const supabase = createClient ( ) ;
429
- await activateSubmission ( { submission_id : historical_submission . id } , supabase ) ;
430
- invalidate ( { resource : "submissions" , invalidates : [ "list" ] } ) ;
431
- toaster . create ( {
432
- title : "Active submission changed" ,
433
- type : "success"
434
- } ) ;
435
- router . push ( link ) ;
436
- } catch ( error ) {
437
- const errorId = Sentry . captureException ( error ) ;
438
- toaster . create ( {
439
- title : "Error activating submission" ,
440
- description : `We have recorded this error with trace ID: ${ errorId } ` ,
441
- type : "error"
442
- } ) ;
443
- } finally {
444
- setIsActivating ( false ) ;
445
- }
446
- } }
447
- >
448
- < Icon as = { FaCheckCircle } />
449
- Activate
450
- </ Button >
451
- ) }
452
- </ Table . Cell >
453
- </ Table . Row >
454
- ) ;
455
- } ) }
456
- </ Table . Body >
457
- </ Table . Root >
458
- </ Box >
468
+ < SubmissionHistoryContents submission = { submission } />
459
469
</ PopoverBody >
460
470
</ PopoverContent >
461
471
</ PopoverRoot >
0 commit comments