Skip to content

Commit

Permalink
Merge pull request openwebwork#2091 from drgrice1/dismisible-alerts
Browse files Browse the repository at this point in the history
Make messages dismissible and PG editor tmp edits more clear
  • Loading branch information
Alex-Jordan authored Jul 3, 2023
2 parents 1bc9a1a + b0742af commit b848e11
Show file tree
Hide file tree
Showing 17 changed files with 242 additions and 251 deletions.
17 changes: 16 additions & 1 deletion htdocs/js/PGProblemEditor/pgproblemeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,16 @@

fetch(webserviceURL, { method: 'post', mode: 'same-origin', body: new URLSearchParams(request_object) })
.then((response) => response.json())
.then((data) => showMessage(data.server_response, data.result_data))
.then((data) => {
showMessage(data.server_response, data.result_data);
if (data.result_data) {
// Add the temporary file coloring and change the current file to the saved file.
document.querySelectorAll('.set-file-info').forEach((nfo) => nfo.classList.add('temporaryFile'));
for (const currentFile of document.querySelectorAll('.current-file')) {
currentFile.textContent = currentFile.dataset.tmpFile;
}
}
})
.catch((err) => showMessage(`Error saving temporary file: ${err?.message ?? err}`));
};

Expand Down Expand Up @@ -106,6 +115,12 @@
revertRadio.checked = true;
}

// Add the temporary file coloring and change the current file to the saved file.
document.querySelectorAll('.set-file-info').forEach((nfo) => nfo.classList.add('temporaryFile'));
for (const currentFile of document.querySelectorAll('.current-file')) {
currentFile.textContent = currentFile.dataset.tmpFile;
}

if (editorForm) editorForm.target = 'WW_View';
} else {
e.preventDefault();
Expand Down
18 changes: 18 additions & 0 deletions htdocs/themes/math4/math4.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@
const codeshards = document.querySelectorAll('.codeshard');
if (codeshards.length == 1) codeshards[0].setAttribute('aria-label', 'answer');

const messages = document.querySelectorAll('#message .alert-dismissible, #message_bottom .alert-dismissible');
if (messages.length) {
const dismissBtn = document.getElementById('dismiss-messages-btn');
dismissBtn?.classList.remove('d-none');

// Hide the dismiss button when the last alert is dismissed.
for (const message of messages) {
message.addEventListener('closed.bs.alert', () => {
if (!document.querySelector('#message .alert-dismissible, #message_bottom .alert-dismissible'))
dismissBtn.remove();
}, { once: true });
}

dismissBtn?.addEventListener('click', () =>
messages.forEach((message) => bootstrap.Alert.getOrCreateInstance(message)?.close())
);
}

// Accessibility
// Present the contents of the data-alt attribute as alternative content for screen reader users.
// The icon should be formatted as <i class="icon fas fa-close" data-alt="close"></i>
Expand Down
10 changes: 8 additions & 2 deletions htdocs/themes/math4/math4.scss
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,14 @@ h2.page-title {

/* Message section */
.message:not(:empty) {
display: inline-block;
margin-bottom: 0.5rem;
display: inline-flex;
flex-direction: column;
gap: 0.25rem;
margin: 0 0 0.5rem;

p {
margin: 0;
}
}

.font-visible { font-weight: bold; }
Expand Down
5 changes: 5 additions & 0 deletions htdocs/themes/math4/system.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@
% }
% if ($c->can('message')) {
<div id="message_bottom" class="message"><%= $c->message %></div>
<div>
<button type="button" id="dismiss-messages-btn" class="btn btn-primary d-none">
<%= maketext('Dismiss All Messages') %>
</button>
</div>
% }
%
% # Footer
Expand Down
30 changes: 28 additions & 2 deletions lib/WeBWorK/ContentGenerator.pm
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,20 @@ message() template escape handler.
=cut

sub addgoodmessage ($c, $message) {
$c->addmessage($c->tag('p', class => 'alert alert-success p-1 my-2', $c->b($message)));
$c->addmessage($c->tag(
'p',
class => 'alert alert-success alert-dismissible fade show ps-1 py-1',
$c->c(
$message,
$c->tag(
'button',
type => 'button',
class => 'btn-close p-2',
data => { bs_dismiss => 'alert' },
'aria-label' => $c->maketext('Dismiss')
)
)->join('')
));
return;
}

Expand All @@ -276,7 +289,20 @@ message() template escape handler.
=cut

sub addbadmessage ($c, $message) {
$c->addmessage($c->tag('p', class => 'alert alert-danger p-1 my-2', $c->b($message)));
$c->addmessage($c->tag(
'p',
class => 'alert alert-danger alert-dismissible fade show ps-1 py-1',
$c->c(
$message,
$c->tag(
'button',
type => 'button',
class => 'btn-close p-2',
data => { bs_dismiss => 'alert' },
'aria-label' => $c->maketext('Dismiss')
)
)->join('')
));
return;
}

Expand Down
4 changes: 3 additions & 1 deletion lib/WeBWorK/ContentGenerator/CourseAdmin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ sub pre_header_initialize ($c) {
return unless $authz->hasPermissions($user, 'create_and_delete_courses');

# Get result and send to message
# FIXME: I am pretty sure this is not used anymore. All methods add their messages directly to the page except the
# table messages, and those are added below and not here.
my $status_message = $c->param('status_message');
$c->addmessage($c->tag('p', class => 'my-2', $c->b($status_message))) if $status_message;
$c->addmessage($c->tag('p', $c->b($status_message))) if $status_message;

# Check that the non-native tables are present in the database.
# These are the tables which are not course specific.
Expand Down
88 changes: 28 additions & 60 deletions lib/WeBWorK/ContentGenerator/Instructor/AchievementList.pm
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,12 @@ sub initialize ($c) {
}

my $actionHandler = "${actionID}_handler";
$c->addmessage($c->tag('p', class => 'mb-1', $c->maketext('Results of last action performed: ')));
$c->addmessage($c->$actionHandler);
my ($success, $action_result) = $c->$actionHandler;
if ($success) {
$c->addgoodmessage($c->b($c->maketext('Result of last action performed: [_1]', $action_result)));
} else {
$c->addbadmessage($c->b($c->maketext('Result of last action performed: [_1]', $action_result)));
}
} else {
$c->addgoodmessage($c->maketext('Please select action to be performed.'));
}
Expand Down Expand Up @@ -155,7 +159,7 @@ sub edit_handler ($c) {
}
$c->{editMode} = 1;

return $c->tag('div', class => 'alert alert-success p-1 mb-0', $result);
return (1, $result);
}

# Handler for assigning achievements to users
Expand Down Expand Up @@ -215,7 +219,7 @@ sub assign_handler ($c) {
}
}

return $c->tag('div', class => 'alert alert-success p-1 mb-0', $c->maketext('Assigned achievements to users'));
return (1, $c->maketext('Assigned achievements to users'));
}

# Handler for scoring
Expand Down Expand Up @@ -249,11 +253,7 @@ sub score_handler ($c) {
$scoreFilePath = WeBWorK::Utils::surePathToFile($ce->{courseDirs}->{scoring}, $scoreFilePath);

my $SCORE = Mojo::File->new($scoreFilePath)->open('>:encoding(UTF-8)')
or return $c->tag(
'div',
class => 'alert alert-danger p-1 mb-0',
$c->maketext("Failed to open [_1]", $scoreFilePath)
);
or return (0, $c->maketext("Failed to open [_1]", $scoreFilePath));

# Print out header info
print $SCORE $c->maketext("username, last name, first name, section, achievement level, achievement score,");
Expand Down Expand Up @@ -308,9 +308,8 @@ sub score_handler ($c) {
$SCORE->close;

# Include a download link
return $c->tag(
'div',
class => 'alert alert-success p-1 mb-0',
return (
1,
$c->b($c->maketext(
'Achievement scores saved to [_1]',
$c->link_to(
Expand Down Expand Up @@ -352,11 +351,7 @@ sub delete_handler ($c) {
$c->{selectedAchievementIDs} = [ keys %selectedAchievementIDs ];

my $num = @achievementIDsToDelete;
return $c->tag(
'div',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Deleted [quant,_1,achievement]', $num)
);
return (1, $c->maketext('Deleted [quant,_1,achievement]', $num));
}

# Handler for creating an ahcievement
Expand All @@ -367,16 +362,10 @@ sub create_handler ($c) {

# Create achievement
my $newAchievementID = $c->param('action.create.id');
return $c->tag(
'div',
class => 'alert alert-danger p-1 mb-0',
$c->maketext("Failed to create new achievement: no achievement ID specified!")
) unless $newAchievementID =~ /\S/;
return $c->tag(
'div',
class => 'alert alert-danger p-1 mb-0',
$c->maketext("Achievement [_1] exists. No achievement created", $newAchievementID)
) if $db->existsAchievement($newAchievementID);
return (0, $c->maketext("Failed to create new achievement: no achievement ID specified!"))
unless $newAchievementID =~ /\S/;
return (0, $c->maketext("Achievement [_1] exists. No achievement created", $newAchievementID))
if $db->existsAchievement($newAchievementID);
my $newAchievementRecord = $db->newAchievement;
my $oldAchievementID = $c->{selectedAchievementIDs}->[0];

Expand All @@ -390,11 +379,8 @@ sub create_handler ($c) {
$newAchievementRecord->test('blankachievement.at');
$db->addAchievement($newAchievementRecord);
} elsif ($type eq "copy") {
return $c->tag(
'div',
class => 'alert alert-danger p-1 mb-0',
$c->maketext("Failed to duplicate achievement: no achievement selected for duplication!")
) unless $oldAchievementID =~ /\S/;
return (0, $c->maketext("Failed to duplicate achievement: no achievement selected for duplication!"))
unless $oldAchievementID =~ /\S/;
$newAchievementRecord = $db->getAchievement($oldAchievementID);
$newAchievementRecord->achievement_id($newAchievementID);
$db->addAchievement($newAchievementRecord);
Expand All @@ -410,17 +396,9 @@ sub create_handler ($c) {
# Add to local list of achievements
push @{ $c->{allAchievementIDs} }, $newAchievementID;

return $c->tag(
'div',
class => 'alert alert-danger p-1 mb-0',
$c->maketext("Failed to create new achievement: [_1]", $@)
) if $@;
return (0, $c->maketext("Failed to create new achievement: [_1]", $@)) if $@;

return $c->tag(
'div',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Successfully created new achievement [_1]', $newAchievementID)
);
return (1, $c->maketext('Successfully created new achievement [_1]', $newAchievementID));
}

# Handler for importing achievements
Expand All @@ -436,8 +414,7 @@ sub import_handler ($c) {

# Open file name
my $fh = Mojo::File->new($filePath)->open('<:encoding(UTF-8)')
or
return $c->tag('div', class => 'alert alert-danger p-1 mb-0', $c->maketext("Failed to open [_1]", $filePath));
or return (0, $c->maketext("Failed to open [_1]", $filePath));

# Read in lines from file
my $count = 0;
Expand Down Expand Up @@ -510,11 +487,7 @@ sub import_handler ($c) {

$c->{allAchievementIDs} = [ keys %allAchievementIDs ];

return $c->tag(
'div',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Imported [quant,_1,achievement]', $count)
);
return (1, $c->maketext('Imported [quant,_1,achievement]', $count));
}

# Export handler
Expand All @@ -532,14 +505,14 @@ sub export_handler ($c) {
}
$c->{exportMode} = 1;

return $c->tag('div', class => 'alert alert-success p-1 mb-0', $result);
return (1, $result);
}

# Handler for leaving the export page.
sub cancel_export_handler ($c) {
$c->{exportMode} = 0;

return $c->tag('div', class => 'alert alert-danger p-1 mb-0', $c->maketext('export abandoned'));
return (0, $c->maketext('export abandoned'));
}

# Handler actually exporting achievements.
Expand All @@ -563,8 +536,7 @@ sub save_export_handler ($c) {
$FilePath = WeBWorK::Utils::surePathToFile($ce->{courseDirs}{achievements}, $FilePath);

my $fh = Mojo::File->new($FilePath)->open('>:encoding(UTF-8)')
or
return $c->tag('div', class => 'alert alert-danger p-1 mb-0', $c->maketext('Failed to open [_1]', $FilePath));
or return (0, $c->maketext('Failed to open [_1]', $FilePath));

my $csv = Text::CSV->new({ eol => "\n" });

Expand All @@ -585,17 +557,13 @@ sub save_export_handler ($c) {

$c->{exportMode} = 0;

return $c->tag(
'div',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Exported achievements to [_1]', $FileName)
);
return (1, $c->maketext('Exported achievements to [_1]', $FileName));
}

# Handler for cancelling edits.
sub cancel_edit_handler ($c) {
$c->{editMode} = 0;
return $c->tag('div', class => 'alert alert-danger p-1 mb-0', $c->maketext('changes abandoned'));
return (1, $c->maketext('changes abandoned'));
}

# Handler for saving edits.
Expand Down Expand Up @@ -630,7 +598,7 @@ sub save_edit_handler ($c) {

$c->{editMode} = 0;

return $c->tag('div', class => 'alert alert-success p-1 mb-0', $c->maketext('changes saved'));
return (1, $c->maketext('changes saved'));
}

# Get list of files that can be imported.
Expand Down
20 changes: 4 additions & 16 deletions lib/WeBWorK/ContentGenerator/Instructor/AchievementUserEditor.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,34 +42,22 @@ sub initialize ($c) {

#Check and see if we need to assign or unassign things
if (defined $c->param('assignToAll')) {
$c->addmessage($c->tag(
'p',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Achievement has been assigned to all users.')
));
$c->addgoodmessage($c->maketext('Achievement has been assigned to all users.'));
%selectedUsers = map { $_ => 1 } @all_users;
$doAssignToSelected = 1;
} elsif (defined $c->param('unassignFromAll')
&& defined($c->param('unassignFromAllSafety'))
&& $c->param('unassignFromAllSafety') == 1)
{
%selectedUsers = ();
$c->addmessage($c->tag(
'p',
class => 'alert alert-danger p-1 mb-0',
$c->maketext('Achievement has been unassigned to all students.')
));
$c->addbadmessage($c->maketext('Achievement has been unassigned to all students.'));
$doAssignToSelected = 1;
} elsif (defined $c->param('assignToSelected')) {
$c->addmessage($c->tag(
'p',
class => 'alert alert-success p-1 mb-0',
$c->maketext('Achievement has been assigned to selected users.')
));
$c->addgoodmessage($c->maketext('Achievement has been assigned to selected users.'));
$doAssignToSelected = 1;
} elsif (defined $c->param('unassignFromAll')) {
# no action taken
$c->addmessage($c->tag('p', class => 'alert alert-danger p-1 mb-0', $c->maketext('No action taken')));
$c->addbadmessage($c->maketext('No action taken'));
}

#do actual assignment and unassignment
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ sub revert_handler ($c) {
}

# Determine revert action
my $revertType = $c->param('action.revert.type') || 'do_not_revert';
my $revertType = $c->param('action.revert.type') // '';

if ($revertType eq 'revert') {
$c->{inputFilePath} = $c->{editFilePath};
Expand Down
Loading

0 comments on commit b848e11

Please sign in to comment.