Skip to content

Commit 79a7c65

Browse files
authored
Merge pull request #3000 from Alex-Jordan/conf
add-on conf files
2 parents 57cb6e1 + 724fb0f commit 79a7c65

6 files changed

Lines changed: 133 additions & 30 deletions

File tree

conf/defaults.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ $webworkDirs{bin} = "$webworkDirs{root}/bin";
272272
# Location of configuration files.
273273
$webworkDirs{conf} = "$webworkDirs{root}/conf";
274274

275+
# Location of add-on configuration files.
276+
$webworkDirs{addOnConf} = "$webworkDirs{conf}/addon";
277+
275278
# Location of assets (tex, pg, themes)
276279
$webworkDirs{assets} = "$webworkDirs{root}/assets";
277280

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
(() => {
2+
const addOnConfSelect = document.getElementById('add_on_conf');
3+
if (!addOnConfSelect) return;
4+
5+
const addOnConfOptgroups = addOnConfSelect.querySelectorAll('optgroup');
6+
7+
// Track previously selected options to identify the newly clicked option
8+
let previousSelection = [];
9+
10+
addOnConfSelect.addEventListener('change', () => {
11+
// Find the option the user just clicked/selected
12+
const newlySelected = Array.from(addOnConfSelect.selectedOptions).find(
13+
(option) => !previousSelection.includes(option)
14+
);
15+
16+
if (newlySelected) {
17+
// Find the parent optgroup
18+
const parent = newlySelected.closest('optgroup');
19+
20+
// Loop through all options in the other groups and unselect them as appropriate
21+
for (const group of addOnConfOptgroups) {
22+
for (const option of group.children) {
23+
if (
24+
option !== newlySelected &&
25+
(parent.dataset.single || (!parent.dataset.single && group.dataset.single))
26+
) {
27+
option.selected = false;
28+
}
29+
}
30+
}
31+
}
32+
33+
// Update tracking variable for the next change event
34+
previousSelection = Array.from(addOnConfSelect.selectedOptions);
35+
});
36+
})();

lib/WeBWorK/ContentGenerator/CourseAdmin.pm

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,12 @@ sub do_add_course ($c) {
377377
# Include any optional arguments, including a template course and the course title and course institution.
378378
my %optional_arguments;
379379
if ($copy_from_course ne '') {
380-
%optional_arguments = map { $_ => 1 } $c->param('copy_component');
381-
$optional_arguments{copyFrom} = $copy_from_course;
382-
$optional_arguments{copyConfig} = $c->param('copy_config_file');
380+
%optional_arguments = map { $_ => 1 } $c->param('copy_component');
381+
$optional_arguments{copyFrom} = $copy_from_course;
382+
$optional_arguments{copyConfig} =
383+
$c->param('copy_config_file') || ($c->param('add_on_conf') && $c->param('add_on_conf') eq '*');
384+
$optional_arguments{addOnConf} =
385+
$c->param('add_on_conf') && $c->param('add_on_conf') ne '*' ? [ $c->param('add_on_conf') ] : [];
383386
}
384387
if ($add_courseTitle ne '') {
385388
$optional_arguments{courseTitle} = $add_courseTitle;

lib/WeBWorK/Utils/CourseManagement.pm

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,12 @@ sub addCourse {
424424
my $courseEnvFile = $ce->{courseFiles}{environment};
425425
open my $fh, ">:utf8", $courseEnvFile
426426
or die "failed to open $courseEnvFile for writing.\n";
427-
writeCourseConf($fh);
427+
my $addOnConf = $options{addOnConf} // [];
428+
my $relConfFolder = File::Spec->abs2rel($ce->{webworkDirs}{addOnConf}, $ce->{webworkDirs}{root});
429+
for (@$addOnConf) {
430+
$_ = File::Spec->catfile($relConfFolder, $_);
431+
}
432+
writeCourseConf($fh, $addOnConf);
428433
close $fh;
429434
}
430435

@@ -1172,24 +1177,34 @@ sub protectQString {
11721177
return $string;
11731178
}
11741179

1175-
=item writeCourseConf($fh)
1180+
=item writeCourseConf($fh, $addOnConf)
11761181
1177-
Writes an essentially empty course.conf file to $fh, a file handle. System
1178-
administrators can use this file to override global settings for a course.
1182+
Writes the course.conf file to C<$fh>, a file handle. System administrators can
1183+
use this file to override global settings for a course. If C<$addOnConf> is
1184+
provided, then it should be a reference to an array of config files to be
1185+
included at the end of the course.conf file.
11791186
11801187
=back
11811188
11821189
=cut
11831190

11841191
sub writeCourseConf {
1185-
my ($fh) = @_;
1192+
my ($fh, $addOnConf) = @_;
11861193

1187-
print $fh <<'EOF';
1194+
my $content = <<'EOF';
11881195
#!perl
11891196
11901197
# This file is used to override the global WeBWorK course environment for this course.
11911198
11921199
EOF
1200+
1201+
if (ref $addOnConf eq 'ARRAY') {
1202+
for my $conf (@$addOnConf) {
1203+
$content .= "\ninclude('$conf');";
1204+
}
1205+
}
1206+
1207+
print $fh $content;
11931208
}
11941209

11951210
sub get_SeedCE

templates/ContentGenerator/CourseAdmin/add_course_form.html.ep

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
% use WeBWorK::Utils::CourseManagement qw(listCourses);
22
%
3+
% content_for js => begin
4+
<%= javascript getAssetURL($ce, 'js/CourseAdmin/restrict_select.js'), defer => undef =%>
5+
% end
6+
%
37
% # Create an array of permission values for the permission selects.
48
% my $permissionLevels = [];
59
% for my $role (sort { $ce->{userRoles}{$a} <=> $ce->{userRoles}{$b} } keys %{ $ce->{userRoles} }) {
@@ -217,26 +221,63 @@
217221
<%= maketext('course institution (will override "Institution" input above)') =%>
218222
</label>
219223
</div>
220-
<div class="form-check mt-3 mb-2">
221-
<label class="form-check-label">
222-
<%= check_box copy_config_file => 1, class => 'form-check-input' =%>
223-
<%= maketext('course configuration file') =%>
224-
<a class="help-popup" role="button" tabindex="0" data-bs-placement="top" data-bs-toggle="popover"
225-
data-bs-content="<%= maketext('Copying the course configuration file may copy configuration '
226-
. 'settings that are specific to the original course instructor. If this is a new course '
227-
. 'for a new instructor, use the fields above to add the new instructor and do not copy '
228-
. 'the course configuration file. Then if there is something in the course configuration '
229-
. 'file that should be carried into the new course, the administrator can copy that manually. '
230-
. 'Alternatively, do copy the course configuration file, but then the administrator should '
231-
. 'inspect the new course configuration file and make adjustments for the new instructor.') =%>"
232-
>
233-
<i class="icon fas fa-question-circle" aria-hidden="true"></i>
234-
<span class="visually-hidden">
235-
<%= maketext('Notes regarding copying the course configuration file') =%>
236-
</span>
237-
</a>
238-
</label>
239-
</div>
224+
% my @addOnConfFiles;
225+
% if (-d $ce->{webworkDirs}{addOnConf}) {
226+
% @addOnConfFiles = glob "$ce->{webworkDirs}{addOnConf}/*.conf";
227+
% for (0 .. $#addOnConfFiles){
228+
% $addOnConfFiles[$_] =~ s/^.*\/|\.conf$//g;
229+
% }
230+
% }
231+
% if (@addOnConfFiles) {
232+
<div class="row my-2">
233+
<%= label_for add_on_conf => maketext('Configuration File:'),
234+
class => 'col-auto col-form-label fw-bold' =%>
235+
<div class="col-auto">
236+
<%= select_field add_on_conf => [
237+
c(
238+
maketext('Default')
239+
=> [ [ maketext('Use distribution default config file') => '', selected => undef ] ],
240+
'data-single' => 'true',
241+
),
242+
c(
243+
maketext('Source Course')
244+
=> [ [ maketext("Use source course's config file") => '*' ] ],
245+
'data-single' => 'true'
246+
),
247+
c(
248+
maketext('Append to distribution default')
249+
=> [ map { [ $_ => "$_.conf" ] } @addOnConfFiles ]
250+
)
251+
],
252+
id => 'add_on_conf',
253+
multiple => undef,
254+
size => 8,
255+
class => 'form-select' =%>
256+
</div>
257+
</div>
258+
% } else {
259+
<div class="form-check mt-3 mb-2">
260+
<label class="form-check-label">
261+
<%= check_box copy_config_file => 1, class => 'form-check-input' =%>
262+
<%= maketext('course configuration file') =%>
263+
<a class="help-popup" role="button" tabindex="0" data-bs-placement="top"
264+
data-bs-toggle="popover" data-bs-content="<%= maketext('Copying the course configuration '
265+
. 'file may copy configuration settings that are specific to the original course '
266+
. 'instructor. If this is a new course for a new instructor, use the fields above to '
267+
. 'add the new instructor and do not copy the course configuration file. Then if '
268+
. 'there is something in the course configuration file that should be carried into '
269+
. 'the new course, the administrator can copy that manually. Alternatively, do copy '
270+
. 'the course configuration file, but then the administrator should inspect the new '
271+
. 'course configuration file and make adjustments for the new instructor.') =%>"
272+
>
273+
<i class="icon fas fa-question-circle" aria-hidden="true"></i>
274+
<span class="visually-hidden">
275+
<%= maketext('Notes regarding copying the course configuration file') =%>
276+
</span>
277+
</a>
278+
</label>
279+
</div>
280+
% }
240281
</fieldset>
241282
<%= hidden_field last_page_was_add_course => 1 =%>
242283
<%= $c->hidden_fields('number_of_additional_users') =%>

templates/HelpFiles/AdminAddCourse.html.ep

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@
1818
. 'creating future courses, or manage and email course users. Note, by default these new users will be '
1919
. '"Dropped" and unable to login to the [_1] course.', $ce->{admin_course_id}) =%>
2020
</p>
21-
<p class="mb-0">
21+
<p>
2222
<%= maketext('You may choose a course to copy components from. Select the course and which components to copy. '
2323
. 'If the course is not a true course (like the modelCourse) then only the templates and html folders, '
2424
. 'and the simple and course config files can be copied. The "simple config" file contains the settings '
2525
. 'made in the "Course Config" page. The "course config" file should only be copied if you know what you '
2626
. 'are doing.') =%>
2727
</p>
28+
<p class="mb-0">
29+
<%= maketext('If there are .conf files in the [_1] folder, you may select a number of these to include at the '
30+
. 'end of the course.conf file. This only applies when not copying a course.conf file from another course.',
31+
$ce->{webworkDirs}{addOnConf}) =%>
32+
</p>

0 commit comments

Comments
 (0)