Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions conf/defaults.config
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ $webworkDirs{bin} = "$webworkDirs{root}/bin";
# Location of configuration files.
$webworkDirs{conf} = "$webworkDirs{root}/conf";

# Location of add-on configuration files.
$webworkDirs{addOnConf} = "$webworkDirs{conf}/addon";

# Location of assets (tex, pg, themes)
$webworkDirs{assets} = "$webworkDirs{root}/assets";

Expand Down
9 changes: 6 additions & 3 deletions lib/WeBWorK/ContentGenerator/CourseAdmin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,12 @@ sub do_add_course ($c) {
# Include any optional arguments, including a template course and the course title and course institution.
my %optional_arguments;
if ($copy_from_course ne '') {
%optional_arguments = map { $_ => 1 } $c->param('copy_component');
$optional_arguments{copyFrom} = $copy_from_course;
$optional_arguments{copyConfig} = $c->param('copy_config_file');
%optional_arguments = map { $_ => 1 } $c->param('copy_component');
$optional_arguments{copyFrom} = $copy_from_course;
$optional_arguments{copyConfig} =
$c->param('copy_config_file') || ($c->param('add_on_conf') && $c->param('add_on_conf') eq '*');
$optional_arguments{addOnConf} =
$c->param('add_on_conf') && $c->param('add_on_conf') ne '*' ? [ $c->param('add_on_conf') ] : [];
}
if ($add_courseTitle ne '') {
$optional_arguments{courseTitle} = $add_courseTitle;
Expand Down
25 changes: 21 additions & 4 deletions lib/WeBWorK/Utils/CourseManagement.pm
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,12 @@ sub addCourse {
my $courseEnvFile = $ce->{courseFiles}{environment};
open my $fh, ">:utf8", $courseEnvFile
or die "failed to open $courseEnvFile for writing.\n";
writeCourseConf($fh);
my $addOnConf = $options{addOnConf} // [];
my $relConfFolder = File::Spec->abs2rel($ce->{webworkDirs}{addOnConf}, $ce->{webworkDirs}{root});
for (@$addOnConf) {
$_ = File::Spec->catfile($relConfFolder, $_);
}
writeCourseConf($fh, $addOnConf);
close $fh;
}

Expand Down Expand Up @@ -1172,24 +1177,36 @@ sub protectQString {
return $string;
}

=item writeCourseConf($fh)
=item writeCourseConf($fh, $addOnConf)

Writes an essentially empty course.conf file to $fh, a file handle. System
administrators can use this file to override global settings for a course.
$addOnConf should be an array reference of config files to tack on at the end.

=back

=cut

sub writeCourseConf {
my ($fh) = @_;
my ($fh, $addOnConf) = @_;

print $fh <<'EOF';
my $content = <<'EOF';
#!perl

# This file is used to override the global WeBWorK course environment for this course.

EOF

if ($addOnConf ne '') {
for my $conf (@$addOnConf) {
$content .= <<"EOF";

include('$conf');
EOF
}
}

print $fh $content;
}

sub get_SeedCE
Expand Down
113 changes: 93 additions & 20 deletions templates/ContentGenerator/CourseAdmin/add_course_form.html.ep
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
% use WeBWorK::Utils::CourseManagement qw(listCourses);
%
%= javascript begin
document.addEventListener('DOMContentLoaded', (event) => {

const addonconfSelect = document.getElementById('add_on_conf');
const addonconfOptgroups = [...addonconfSelect.querySelectorAll('optgroup')];

// Track previously selected options to identify the newly clicked option
let previousSelection = [];

addonconfSelect.addEventListener('change', (event) => {
const currentSelection = Array.from(addonconfSelect.selectedOptions);

// Find the exact option the user just clicked/selected
const newlySelected = currentSelection.find(option => !previousSelection.includes(option));

if (newlySelected) {
// Find if the parent optgroup has the single restriction
const singleGroup = newlySelected.closest('optgroup[data-single="true"]');

// Loop through all options in the other groups and unselect them as appropriate
addonconfOptgroups.forEach((group) => {
Array.from(group.children).forEach(option => {
if (option !== newlySelected && (singleGroup || !singleGroup && group.dataset.single)) {
option.selected = false;
}
});
});
}

// Update tracking variable for the next change event
previousSelection = Array.from(addonconfSelect.selectedOptions);
});

});
% end
% # Create an array of permission values for the permission selects.
% my $permissionLevels = [];
% for my $role (sort { $ce->{userRoles}{$a} <=> $ce->{userRoles}{$b} } keys %{ $ce->{userRoles} }) {
Expand Down Expand Up @@ -217,26 +252,64 @@
<%= maketext('course institution (will override "Institution" input above)') =%>
</label>
</div>
<div class="form-check mt-3 mb-2">
<label class="form-check-label">
<%= check_box copy_config_file => 1, class => 'form-check-input' =%>
<%= maketext('course configuration file') =%>
<a class="help-popup" role="button" tabindex="0" data-bs-placement="top" data-bs-toggle="popover"
data-bs-content="<%= maketext('Copying the course configuration file may copy configuration '
. 'settings that are specific to the original course instructor. If this is a new course '
. 'for a new instructor, use the fields above to add the new instructor and do not copy '
. 'the course configuration file. Then if there is something in the course configuration '
. 'file that should be carried into the new course, the administrator can copy that manually. '
. 'Alternatively, do copy the course configuration file, but then the administrator should '
. 'inspect the new course configuration file and make adjustments for the new instructor.') =%>"
>
<i class="icon fas fa-question-circle" aria-hidden="true"></i>
<span class="visually-hidden">
<%= maketext('Notes regarding copying the course configuration file') =%>
</span>
</a>
</label>
</div>
% my $addOnConfFolder = $ce->{webworkDirs}{addOnConf};
% my @addOnConfFiles;
% if (-d $addOnConfFolder) {
% @addOnConfFiles = glob "$addOnConfFolder/*.conf";
% for (0..$#addOnConfFiles){
% $addOnConfFiles[$_] =~ s/^.*\/|\.conf$//g;
% }
% }
% if (@addOnConfFiles) {
<div class="row my-2">
<%= label_for add_on_conf => maketext('Configuration File:'),
class => 'col-auto col-form-label fw-bold' =%>
<div class="col-auto">
<%= select_field add_on_conf => [
c(
maketext('Use Default')
=> [ [ maketext('Distribution Default Config File') => '' ] ],
'data-single' => "true"
),
c(
maketext('Source Course')
=> [ [ maketext("Source Course's Config File") => '*' ] ],
'data-single' => "true"
),
c(
maketext('Append to Distribution Default')
=> [ map { [ $_ => "$_.conf" ] } @addOnConfFiles ]
)
],
id => 'add_on_conf',
multiple => undef,
size => 8,
class => 'form-select' =%>
</div>
</div>
% } else {
<div class="form-check mt-3 mb-2">
<label class="form-check-label">
<%= check_box copy_config_file => 1, class => 'form-check-input' =%>
<%= maketext('course configuration file') =%>
<a class="help-popup" role="button" tabindex="0" data-bs-placement="top"
data-bs-toggle="popover" data-bs-content="<%= maketext('Copying the course configuration '
. 'file may copy configuration settings that are specific to the original course '
. 'instructor. If this is a new course for a new instructor, use the fields above to '
. 'add the new instructor and do not copy the course configuration file. Then if '
. 'there is something in the course configuration file that should be carried into '
. 'the new course, the administrator can copy that manually. Alternatively, do copy '
. 'the course configuration file, but then the administrator should inspect the new '
. 'course configuration file and make adjustments for the new instructor.') =%>"
>
<i class="icon fas fa-question-circle" aria-hidden="true"></i>
<span class="visually-hidden">
<%= maketext('Notes regarding copying the course configuration file') =%>
</span>
</a>
</label>
</div>
% }
</fieldset>
<%= hidden_field last_page_was_add_course => 1 =%>
<%= $c->hidden_fields('number_of_additional_users') =%>
Expand Down
7 changes: 6 additions & 1 deletion templates/HelpFiles/AdminAddCourse.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
. 'creating future courses, or manage and email course users. Note, by default these new users will be '
. '"Dropped" and unable to login to the [_1] course.', $ce->{admin_course_id}) =%>
</p>
<p class="mb-0">
<p>
<%= maketext('You may choose a course to copy components from. Select the course and which components to copy. '
. 'If the course is not a true course (like the modelCourse) then only the templates and html folders, '
. 'and the simple and course config files can be copied. The "simple config" file contains the settings '
. 'made in the "Course Config" page. The "course config" file should only be copied if you know what you '
. 'are doing.') =%>
</p>
<p class="mb-0">
<%= maketext('If there are .conf files in the [_1] folder, you may select a number of these to include at the '
. 'end of the course.conf file. This only applies when not copying a course.conf file from another course.',
$ce->{webworkDirs}{addOnConf}) =%>
</p>
Loading