MDL-78289 core_courseformat: New completion dropdown buttons UI

- Update completion dropdown button styles for students depending on activity
overall completion status.
- Add new behat partial named selector 'core_courseformat > Activity completion'
- Add new behat Feature to test activity completion criteria button or dropdown
for students and teachers.
This commit is contained in:
Mikel Martín
2023-08-01 09:41:21 +02:00
parent a1d5d1b2f7
commit 8ff60512fb
7 changed files with 383 additions and 71 deletions
@@ -102,16 +102,21 @@ class completion implements named_templatable, renderable {
* @return array the completion dialog exported for template
*/
private function get_completion_dialog(\renderer_base $output, stdClass $completioninfo): array {
$dialogcontent = $output->render_from_template('core_courseformat/local/content/cm/completion_dialog', $completioninfo);
$buttoncontent = get_string('completionmenuitem', 'completion');
$buttonclass = '';
if ($completioninfo->istrackeduser) {
$buttoncontent = get_string('todo', 'completion');
} else {
$buttoncontent = get_string('completionmenuitem', 'completion');
if ($completioninfo->overallcomplete) {
$buttoncontent = $output->pix_icon('i/checked', '') . " " . get_string('completion_manual:done', 'core_course');
$buttonclass = 'btn-success';
}
}
$content = $output->render_from_template('core_courseformat/local/content/cm/completion_dialog', $completioninfo);
$completiondialog = new dropdown_dialog($buttoncontent, $content, [
$completiondialog = new dropdown_dialog($buttoncontent, $dialogcontent, [
'classes' => 'completion-dropdown',
'buttonclasses' => 'btn btn-sm btn-outline-secondary dropdown-toggle',
'buttonclasses' => 'btn btn-sm dropdown-toggle icon-no-margin ' . $buttonclass,
'dropdownposition' => dropdown_dialog::POSITION['end'],
]);
@@ -117,7 +117,7 @@
{{! Completion }}
{{#activityinfo}}
{{#hascompletion}}
<div class="activity-info align-self-start mr-sm-2">
<div class="activity-completion align-self-start mr-sm-2">
{{$ core_courseformat/local/content/cm/activity_info}}
{{> core_courseformat/local/content/cm/activity_info}}
{{/ core_courseformat/local/content/cm/activity_info}}
@@ -0,0 +1,43 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
declare(strict_types=1);
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
/**
* Behat step definitions for Course format
*
* @package core_courseformat
* @copyright 2023 Mikel Martín <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_courseformat extends behat_base {
/**
* Return the list of partial named selectors
*
* @return behat_component_named_selector[]
*/
public static function get_partial_named_selectors(): array {
return [
new behat_component_named_selector('Activity completion', [
".//*[@data-activityname=%locator%]//*[@data-region='completionrequirements']",
]),
];
}
}
@@ -0,0 +1,55 @@
@core @core_course @core_courseformat @core_completion @javascript
Feature: Course page activities completion
In order to check activities completions
As a student
I need to see the activity completion criterias dropdown.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| shortname | fullname | enablecompletion |
| C1 | Course 1 | 1 |
And the following "activities" exist:
| activity | name | intro | course | idnumber | section | completion | completionview |
| assign | Activity sample 1 | Test assignment description | C1 | sample1 | 1 | 1 | 0 |
| assign | Activity sample 2 | Test assignment description | C1 | sample2 | 1 | 2 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
Scenario: Teacher does not see manual completion button
When I am on the "C1" "Course" page logged in as "teacher1"
Then "Mark as done" "button" should not exist in the "Activity sample 1" "activity"
And I click on "Completion" "button" in the "Activity sample 1" "activity"
And I should see "Mark as done" in the "Activity sample 1" "core_courseformat > Activity completion"
Scenario: Student should see the manual completion button
When I am on the "C1" "Course" page logged in as "student1"
Then the manual completion button for "Activity sample 1" should exist
And the manual completion button of "Activity sample 1" is displayed as "Mark as done"
And I toggle the manual completion state of "Activity sample 1"
And the manual completion button of "Activity sample 1" is displayed as "Done"
Scenario: Teacher should see the automatic completion criterias of activities
When I am on the "C1" "Course" page logged in as "teacher1"
And I click on "Completion" "button" in the "Activity sample 2" "activity"
Then I should see "View" in the "Activity sample 2" "core_courseformat > Activity completion"
# After viewing the activity, the completion criteria dropdown should still display "Completion".
And I am on the "sample2" Activity page
And I am on the "Course 1" course page
And "Completion" "button" should exist in the "Activity sample 2" "activity"
Scenario: Student should see the automatic completion criterias statuses of activities
When I am on the "C1" "Course" page logged in as "student1"
And I click on "To do" "button" in the "Activity sample 2" "activity"
Then I should see "View" in the "Activity sample 2" "core_courseformat > Activity completion"
# After viewing the activity, the completion criteria dropdown should display "Done" instead of "To do".
And I am on the "sample2" Activity page
And I am on the "Course 1" course page
And "To do" "button" should not exist in the "Activity sample 2" "activity"
And I click on "Done" "button" in the "Activity sample 2" "activity"
And I should see "View" in the "Activity sample 2" "core_courseformat > Activity completion"
+22 -19
View File
@@ -1266,6 +1266,26 @@ $activity-item-hover: theme-color-level('primary', -12) !default;
$activity-item-border-radius: 1rem !default;
$activity-add-hover: theme-color-level('primary', -10) !default;
/* Functions/Mixins definition */
// Activity completion button custom styling mixin.
@mixin completion-button() {
&.btn {
border: $border-width solid $gray-400;
font-weight: bold;
@include border-radius();
.icon {
font-size: inherit;
}
}
@each $color, $value in $theme-colors {
&.btn-#{$color} {
$bg-color: theme-color-level($color, $alert-bg-level);
@include alert-variant($bg-color, $bg-color, $value);
}
}
}
/* Activity & Block 'add' buttons */
.activity-add,
@@ -1558,15 +1578,13 @@ $activity-add-hover: theme-color-level('primary', -10) !default;
}
}
.activity-info {
.activity-completion {
grid-area: completion;
justify-self: end;
// Re-style completion buttons (mark as done & dropdown).
button,
a[role="button"] {
border: $border-width solid $border-color;
@include border-radius();
font-weight: bold;
@include completion-button();
}
@include media-breakpoint-down(xs) {
width: 100%;
@@ -1687,21 +1705,6 @@ $activity-add-hover: theme-color-level('primary', -10) !default;
display: none;
}
// Revisit these styles when MDL-78289 lands. Probably not needed anymore.
.automatic-completion-conditions .badge {
font-size: 80%;
padding: map-get($spacers, 2);
margin-top: map-get($spacers, 1);
.icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem;
}
&:first-child {
margin-top: 0;
}
}
/* Activity divider */
.activity:focus-within + .activity div.divider button,
+126 -23
View File
@@ -28954,6 +28954,7 @@ span.editinstructions .alert-link {
}
/* Variables definition*/
/* Functions/Mixins definition */
/* Activity & Block 'add' buttons */
.activity-add,
.block-add {
@@ -29188,31 +29189,147 @@ span.editinstructions .alert-link {
font-size: 0.875em;
padding: 0;
}
.activity-item .activity-info {
.activity-item .activity-completion {
grid-area: completion;
justify-self: end;
}
.activity-item .activity-info button,
.activity-item .activity-info a[role=button] {
border: 1px solid #dee2e6;
border-radius: 0.5rem;
.activity-item .activity-completion button.btn,
.activity-item .activity-completion a[role=button].btn {
border: 1px solid #ced4da;
font-weight: bold;
border-radius: 0.5rem;
}
.activity-item .activity-completion button.btn .icon,
.activity-item .activity-completion a[role=button].btn .icon {
font-size: inherit;
}
.activity-item .activity-completion button.btn-primary,
.activity-item .activity-completion a[role=button].btn-primary {
color: #0f6cbf;
background-color: #cfe2f2;
border-color: #cfe2f2;
}
.activity-item .activity-completion button.btn-primary hr,
.activity-item .activity-completion a[role=button].btn-primary hr {
border-top-color: #bbd6ed;
}
.activity-item .activity-completion button.btn-primary .alert-link,
.activity-item .activity-completion a[role=button].btn-primary .alert-link {
color: #0b5190;
}
.activity-item .activity-completion button.btn-secondary,
.activity-item .activity-completion a[role=button].btn-secondary {
color: #ced4da;
background-color: #f5f6f8;
border-color: #f5f6f8;
}
.activity-item .activity-completion button.btn-secondary hr,
.activity-item .activity-completion a[role=button].btn-secondary hr {
border-top-color: #e6e9ee;
}
.activity-item .activity-completion button.btn-secondary .alert-link,
.activity-item .activity-completion a[role=button].btn-secondary .alert-link {
color: #b1bbc4;
}
.activity-item .activity-completion button.btn-success,
.activity-item .activity-completion a[role=button].btn-success {
color: #357a32;
background-color: #d7e4d6;
border-color: #d7e4d6;
}
.activity-item .activity-completion button.btn-success hr,
.activity-item .activity-completion a[role=button].btn-success hr {
border-top-color: #c8dac7;
}
.activity-item .activity-completion button.btn-success .alert-link,
.activity-item .activity-completion a[role=button].btn-success .alert-link {
color: #255623;
}
.activity-item .activity-completion button.btn-info,
.activity-item .activity-completion a[role=button].btn-info {
color: #008196;
background-color: #cce6ea;
border-color: #cce6ea;
}
.activity-item .activity-completion button.btn-info hr,
.activity-item .activity-completion a[role=button].btn-info hr {
border-top-color: #badde3;
}
.activity-item .activity-completion button.btn-info .alert-link,
.activity-item .activity-completion a[role=button].btn-info .alert-link {
color: #005563;
}
.activity-item .activity-completion button.btn-warning,
.activity-item .activity-completion a[role=button].btn-warning {
color: #f0ad4e;
background-color: #fcefdc;
border-color: #fcefdc;
}
.activity-item .activity-completion button.btn-warning hr,
.activity-item .activity-completion a[role=button].btn-warning hr {
border-top-color: #fae4c5;
}
.activity-item .activity-completion button.btn-warning .alert-link,
.activity-item .activity-completion a[role=button].btn-warning .alert-link {
color: #ec971f;
}
.activity-item .activity-completion button.btn-danger,
.activity-item .activity-completion a[role=button].btn-danger {
color: #ca3120;
background-color: #f4d6d2;
border-color: #f4d6d2;
}
.activity-item .activity-completion button.btn-danger hr,
.activity-item .activity-completion a[role=button].btn-danger hr {
border-top-color: #efc3be;
}
.activity-item .activity-completion button.btn-danger .alert-link,
.activity-item .activity-completion a[role=button].btn-danger .alert-link {
color: #9e2619;
}
.activity-item .activity-completion button.btn-light,
.activity-item .activity-completion a[role=button].btn-light {
color: #f8f9fa;
background-color: #fefefe;
border-color: #fefefe;
}
.activity-item .activity-completion button.btn-light hr,
.activity-item .activity-completion a[role=button].btn-light hr {
border-top-color: #f1f1f1;
}
.activity-item .activity-completion button.btn-light .alert-link,
.activity-item .activity-completion a[role=button].btn-light .alert-link {
color: #dae0e5;
}
.activity-item .activity-completion button.btn-dark,
.activity-item .activity-completion a[role=button].btn-dark {
color: #343a40;
background-color: #d6d8d9;
border-color: #d6d8d9;
}
.activity-item .activity-completion button.btn-dark hr,
.activity-item .activity-completion a[role=button].btn-dark hr {
border-top-color: #c9cbcd;
}
.activity-item .activity-completion button.btn-dark .alert-link,
.activity-item .activity-completion a[role=button].btn-dark .alert-link {
color: #1d2124;
}
@media (max-width: 575.98px) {
.activity-item .activity-info {
.activity-item .activity-completion {
width: 100%;
margin-top: 0.5rem;
}
.activity-item .activity-info button {
.activity-item .activity-completion button {
width: 100%;
}
}
.activity-item .activity-info .completion-dialog {
.activity-item .activity-completion .completion-dialog {
color: #495057;
font-size: 0.8203125rem;
min-width: 12rem;
}
.activity-item .activity-info .completion-dialog .icon {
.activity-item .activity-completion .completion-dialog .icon {
font-size: 0.8203125rem;
width: 0.8203125rem;
height: 0.8203125rem;
@@ -29314,20 +29431,6 @@ span.editinstructions .alert-link {
display: none;
}
.automatic-completion-conditions .badge {
font-size: 80%;
padding: 0.5rem;
margin-top: 0.25rem;
}
.automatic-completion-conditions .badge .icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem;
}
.automatic-completion-conditions .badge:first-child {
margin-top: 0;
}
/* Activity divider */
.activity:focus-within + .activity div.divider button,
.course-section-header:focus-within + .content .section .activity:first-child div.divider button,
+126 -23
View File
@@ -28954,6 +28954,7 @@ span.editinstructions .alert-link {
}
/* Variables definition*/
/* Functions/Mixins definition */
/* Activity & Block 'add' buttons */
.activity-add,
.block-add {
@@ -29188,31 +29189,147 @@ span.editinstructions .alert-link {
font-size: 0.875em;
padding: 0;
}
.activity-item .activity-info {
.activity-item .activity-completion {
grid-area: completion;
justify-self: end;
}
.activity-item .activity-info button,
.activity-item .activity-info a[role=button] {
border: 1px solid #dee2e6;
border-radius: 0.25rem;
.activity-item .activity-completion button.btn,
.activity-item .activity-completion a[role=button].btn {
border: 1px solid #ced4da;
font-weight: bold;
border-radius: 0.25rem;
}
.activity-item .activity-completion button.btn .icon,
.activity-item .activity-completion a[role=button].btn .icon {
font-size: inherit;
}
.activity-item .activity-completion button.btn-primary,
.activity-item .activity-completion a[role=button].btn-primary {
color: #0f6cbf;
background-color: #cfe2f2;
border-color: #cfe2f2;
}
.activity-item .activity-completion button.btn-primary hr,
.activity-item .activity-completion a[role=button].btn-primary hr {
border-top-color: #bbd6ed;
}
.activity-item .activity-completion button.btn-primary .alert-link,
.activity-item .activity-completion a[role=button].btn-primary .alert-link {
color: #0b5190;
}
.activity-item .activity-completion button.btn-secondary,
.activity-item .activity-completion a[role=button].btn-secondary {
color: #ced4da;
background-color: #f5f6f8;
border-color: #f5f6f8;
}
.activity-item .activity-completion button.btn-secondary hr,
.activity-item .activity-completion a[role=button].btn-secondary hr {
border-top-color: #e6e9ee;
}
.activity-item .activity-completion button.btn-secondary .alert-link,
.activity-item .activity-completion a[role=button].btn-secondary .alert-link {
color: #b1bbc4;
}
.activity-item .activity-completion button.btn-success,
.activity-item .activity-completion a[role=button].btn-success {
color: #357a32;
background-color: #d7e4d6;
border-color: #d7e4d6;
}
.activity-item .activity-completion button.btn-success hr,
.activity-item .activity-completion a[role=button].btn-success hr {
border-top-color: #c8dac7;
}
.activity-item .activity-completion button.btn-success .alert-link,
.activity-item .activity-completion a[role=button].btn-success .alert-link {
color: #255623;
}
.activity-item .activity-completion button.btn-info,
.activity-item .activity-completion a[role=button].btn-info {
color: #008196;
background-color: #cce6ea;
border-color: #cce6ea;
}
.activity-item .activity-completion button.btn-info hr,
.activity-item .activity-completion a[role=button].btn-info hr {
border-top-color: #badde3;
}
.activity-item .activity-completion button.btn-info .alert-link,
.activity-item .activity-completion a[role=button].btn-info .alert-link {
color: #005563;
}
.activity-item .activity-completion button.btn-warning,
.activity-item .activity-completion a[role=button].btn-warning {
color: #f0ad4e;
background-color: #fcefdc;
border-color: #fcefdc;
}
.activity-item .activity-completion button.btn-warning hr,
.activity-item .activity-completion a[role=button].btn-warning hr {
border-top-color: #fae4c5;
}
.activity-item .activity-completion button.btn-warning .alert-link,
.activity-item .activity-completion a[role=button].btn-warning .alert-link {
color: #ec971f;
}
.activity-item .activity-completion button.btn-danger,
.activity-item .activity-completion a[role=button].btn-danger {
color: #ca3120;
background-color: #f4d6d2;
border-color: #f4d6d2;
}
.activity-item .activity-completion button.btn-danger hr,
.activity-item .activity-completion a[role=button].btn-danger hr {
border-top-color: #efc3be;
}
.activity-item .activity-completion button.btn-danger .alert-link,
.activity-item .activity-completion a[role=button].btn-danger .alert-link {
color: #9e2619;
}
.activity-item .activity-completion button.btn-light,
.activity-item .activity-completion a[role=button].btn-light {
color: #f8f9fa;
background-color: #fefefe;
border-color: #fefefe;
}
.activity-item .activity-completion button.btn-light hr,
.activity-item .activity-completion a[role=button].btn-light hr {
border-top-color: #f1f1f1;
}
.activity-item .activity-completion button.btn-light .alert-link,
.activity-item .activity-completion a[role=button].btn-light .alert-link {
color: #dae0e5;
}
.activity-item .activity-completion button.btn-dark,
.activity-item .activity-completion a[role=button].btn-dark {
color: #343a40;
background-color: #d6d8d9;
border-color: #d6d8d9;
}
.activity-item .activity-completion button.btn-dark hr,
.activity-item .activity-completion a[role=button].btn-dark hr {
border-top-color: #c9cbcd;
}
.activity-item .activity-completion button.btn-dark .alert-link,
.activity-item .activity-completion a[role=button].btn-dark .alert-link {
color: #1d2124;
}
@media (max-width: 575.98px) {
.activity-item .activity-info {
.activity-item .activity-completion {
width: 100%;
margin-top: 0.5rem;
}
.activity-item .activity-info button {
.activity-item .activity-completion button {
width: 100%;
}
}
.activity-item .activity-info .completion-dialog {
.activity-item .activity-completion .completion-dialog {
color: #495057;
font-size: 0.8203125rem;
min-width: 12rem;
}
.activity-item .activity-info .completion-dialog .icon {
.activity-item .activity-completion .completion-dialog .icon {
font-size: 0.8203125rem;
width: 0.8203125rem;
height: 0.8203125rem;
@@ -29314,20 +29431,6 @@ span.editinstructions .alert-link {
display: none;
}
.automatic-completion-conditions .badge {
font-size: 80%;
padding: 0.5rem;
margin-top: 0.25rem;
}
.automatic-completion-conditions .badge .icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem;
}
.automatic-completion-conditions .badge:first-child {
margin-top: 0;
}
/* Activity divider */
.activity:focus-within + .activity div.divider button,
.course-section-header:focus-within + .content .section .activity:first-child div.divider button,