From bbaeb3b04d8f6ac0b1e5f5d59b324df5c2ef0a0c Mon Sep 17 00:00:00 2001
From: Alex Jordan
Date: Wed, 8 Jul 2026 19:17:23 -0700
Subject: [PATCH 2/5] For pages in the admin course, use 'Course ID' instead of
'Course Name'
---
.../ContentGenerator/CourseAdmin/archive_course_form.html.ep | 4 ++--
.../ContentGenerator/CourseAdmin/delete_course_form.html.ep | 4 ++--
.../CourseAdmin/hide_inactive_course_form.html.ep | 4 ++--
.../CourseAdmin/unarchive_course_form.html.ep | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/templates/ContentGenerator/CourseAdmin/archive_course_form.html.ep b/templates/ContentGenerator/CourseAdmin/archive_course_form.html.ep
index 39106e4990..fba07f6e3c 100644
--- a/templates/ContentGenerator/CourseAdmin/archive_course_form.html.ep
+++ b/templates/ContentGenerator/CourseAdmin/archive_course_form.html.ep
@@ -5,7 +5,7 @@
<%= maketext(
'Courses are listed either alphabetically or in order by the time of most recent login activity, oldest '
. 'first. To change the listing order check the mode you want and click "Refresh Listing". The '
- . 'listing format is: Course_Name (status :: date/time of most recent login) where status is "hidden" '
+ . 'listing format is: Course_ID (status :: date/time of most recent login) where status is "hidden" '
. 'or "visible".'
) =%>
<%= select_field archive_courseIDs => [ map { [ $courseLabels->{$_} => $_ ] } @$courseIDs ],
id => 'archive_courseIDs',
diff --git a/templates/ContentGenerator/CourseAdmin/delete_course_form.html.ep b/templates/ContentGenerator/CourseAdmin/delete_course_form.html.ep
index 0306c31f29..68e9915ef7 100644
--- a/templates/ContentGenerator/CourseAdmin/delete_course_form.html.ep
+++ b/templates/ContentGenerator/CourseAdmin/delete_course_form.html.ep
@@ -6,7 +6,7 @@
<%= maketext(
'Courses are listed either alphabetically or in order by the time of most recent login activity, '
. 'oldest first. To change the listing order check the mode you want and click "Refresh Listing". '
- . 'The listing format is: Course_Name (status :: date/time of most recent login) where status is '
+ . 'The listing format is: Course_ID (status :: date/time of most recent login) where status is '
. '"hidden" or "visible".'
) =%>
@@ -35,7 +35,7 @@
<%= $c->hidden_fields('subDisplay') =%>
<%= select_field delete_courseID => [ map { [ $courseLabels->{$_} => $_ ] } @$courseIDs ],
id => 'delete_courseID',
diff --git a/templates/ContentGenerator/CourseAdmin/hide_inactive_course_form.html.ep b/templates/ContentGenerator/CourseAdmin/hide_inactive_course_form.html.ep
index 152bb1cbf2..be442fb54f 100644
--- a/templates/ContentGenerator/CourseAdmin/hide_inactive_course_form.html.ep
+++ b/templates/ContentGenerator/CourseAdmin/hide_inactive_course_form.html.ep
@@ -12,7 +12,7 @@
<%= maketext(
'Courses are listed either alphabetically or in order by the time of most recent login activity, '
. 'oldest first. To change the listing order check the mode you want and click "Refresh Listing". '
- . 'The listing format is: Course_Name (status :: date/time of most recent login) where status is "hidden" '
+ . 'The listing format is: Course_ID (status :: date/time of most recent login) where status is "hidden" '
. 'or "visible".'
) =%>
@@ -43,7 +43,7 @@
%
<%= maketext('Select course(s) to hide or unhide.') %>
<%= text_field new_courseID => '',
id => 'new_courseID',
size => 25,
From da34ce9581b91e560bb4781753113302f4f69d89 Mon Sep 17 00:00:00 2001
From: Glenn Rice
Date: Thu, 9 Jul 2026 06:18:38 -0500
Subject: [PATCH 5/5] Combine the `listArchiveCourses` and `statArchiveCourses`
methods.
The `listArchiveCourses` also stats the archive files found and returns
the files as a hash whose keys are the course ids and the values are
references to hashes containing the `filename` (the basename of the file
including the `.tar.gz` extension) and file `size`
Both of the places that use the `listArchiveCourses` method are updated
to use this return value.
---
lib/WeBWorK/Utils/CourseManagement.pm | 41 ++++++++++---------
.../ContentGenerator/CourseAdmin.html.ep | 5 ++-
.../CourseAdmin/unarchive_course_form.html.ep | 22 ++++++----
3 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/lib/WeBWorK/Utils/CourseManagement.pm b/lib/WeBWorK/Utils/CourseManagement.pm
index 41073c1810..d584758dfd 100644
--- a/lib/WeBWorK/Utils/CourseManagement.pm
+++ b/lib/WeBWorK/Utils/CourseManagement.pm
@@ -29,7 +29,6 @@ use WeBWorK::Utils::Instructor qw(assignSetsToUsers);
our @EXPORT_OK = qw(
listCourses
listArchivedCourses
- statArchivedCourses
addCourse
renameCourse
retitleCourse
@@ -110,7 +109,17 @@ sub listCourses {
=item listArchivedCourses($ce)
-Lists the courses which have been archived (end in .tar.gz).
+Lists the courses which have been archived (end in .tar.gz). The courses found
+are returned as a hash whose keys are the course ids and the values are
+references to hashes containing the C (the basename of the file
+including the .tar.gz extension) and file C. For example,
+
+ {
+ myTestCourse => {
+ filename => 'myTestCourse.tar.gz',
+ size => '605 KB'
+ }
+ }
=cut
@@ -118,30 +127,24 @@ sub listArchivedCourses {
my ($ce) = @_;
my $archivesDir = path("$ce->{webworkDirs}{courses}/$ce->{admin_course_id}/archives");
surePathToFile($ce->{webworkDirs}{courses}, "$archivesDir/test"); # Ensure archives directory exists.
- return @{ $archivesDir->list->grep(qr/\.tar\.gz$/)->map('basename') };
-}
-=item statArchivedCourses($ce)
+ my $archives = $archivesDir->list->grep(qr/\.tar\.gz$/i);
-File info for the courses which have been archived (end in .tar.gz).
-
-=cut
-
-sub statArchivedCourses {
- my ($ce) = @_;
- my @archives = listArchivedCourses($ce);
- my $archivesDir = path("$ce->{webworkDirs}{courses}/$ce->{admin_course_id}/archives");
my %return;
- for (@archives) {
- my @stat = stat("$archivesDir/$_");
- my $size = $stat[7];
+ for (@$archives) {
+ my $size = $_->stat->size;
my @units = qw(B KB MB GB);
my $unit_idx = 0;
- while ($size >= 1024 && $unit_idx < @units - 1) {
+ while ($size >= 1024 && $unit_idx < $#units) {
$size /= 1024;
- $unit_idx++;
+ ++$unit_idx;
}
- $return{ $_ =~ s/\.tar\.gz$//ir } = { filename => $_, size => sprintf("%s %s", int($size), $units[$unit_idx]) };
+ my $basename = $_->basename;
+ my $round = 10**($unit_idx > 0 ? $unit_idx - 1 : 0);
+ $return{ $basename =~ s/\.tar\.gz$//ir } = {
+ filename => $basename,
+ size => sprintf("%s %s", int($size * $round) / $round, $units[$unit_idx])
+ };
}
return %return;
}
diff --git a/templates/ContentGenerator/CourseAdmin.html.ep b/templates/ContentGenerator/CourseAdmin.html.ep
index be8e357ad9..793a193ac0 100644
--- a/templates/ContentGenerator/CourseAdmin.html.ep
+++ b/templates/ContentGenerator/CourseAdmin.html.ep
@@ -65,8 +65,9 @@
) =%>
- % for (sort { lc($a) cmp lc($b) } listArchivedCourses($ce)) {
-
<%= $_ %>
+ % my %courseArchives = listArchivedCourses($ce);
+ % for (sort { lc($a) cmp lc($b) } keys %courseArchives) {
+
<%= "$_ ($courseArchives{$_}{size})" %>
% }
% }
diff --git a/templates/ContentGenerator/CourseAdmin/unarchive_course_form.html.ep b/templates/ContentGenerator/CourseAdmin/unarchive_course_form.html.ep
index e5b2d4afc1..1218c6bfe7 100644
--- a/templates/ContentGenerator/CourseAdmin/unarchive_course_form.html.ep
+++ b/templates/ContentGenerator/CourseAdmin/unarchive_course_form.html.ep
@@ -1,10 +1,10 @@
-% use WeBWorK::Utils::CourseManagement qw(statArchivedCourses);
+% use WeBWorK::Utils::CourseManagement qw(listArchivedCourses);
%