mirror of
https://github.com/moodle/moodle.git
synced 2025-04-14 04:52:36 +02:00
MDL-73232 core_courseformat: Inform user when reaching section max
* Disable the Add new Section button when max has been reached * It also grays out the (+) button between sections and display a tooltip * When adding a new section via the (+) button between section should add a section with the (+) (add) button disabled.
This commit is contained in:
parent
554a790bf0
commit
4fe100f161
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -40,6 +40,7 @@ import Pending from 'core/pending';
|
||||
import ContentTree from 'core_courseformat/local/courseeditor/contenttree';
|
||||
// The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
import jQuery from 'jquery';
|
||||
import Notification from "core/notification";
|
||||
|
||||
// Load global strings.
|
||||
prefetchStrings('core', ['movecoursesection', 'movecoursemodule', 'confirm', 'delete']);
|
||||
@ -82,11 +83,15 @@ export default class extends BaseComponent {
|
||||
ACTIONMENUTOGGLER: `[data-toggle="dropdown"]`,
|
||||
// Availability modal selectors.
|
||||
OPTIONSRADIO: `[type='radio']`,
|
||||
COURSEADDSECTION: `#course-addsection`,
|
||||
MAXSECTIONSWARNING: `[data-region='max-sections-warning']`,
|
||||
ADDSECTIONREGION: `[data-region='section-addsection']`,
|
||||
};
|
||||
// Component css classes.
|
||||
this.classes = {
|
||||
DISABLED: `disabled`,
|
||||
ITALIC: `font-italic`,
|
||||
DISPLAYNONE: `d-none`,
|
||||
};
|
||||
}
|
||||
|
||||
@ -719,12 +724,28 @@ export default class extends BaseComponent {
|
||||
* @param {boolean} locked the new locked value.
|
||||
*/
|
||||
_setAddSectionLocked(locked) {
|
||||
const targets = this.getElements(this.selectors.ADDSECTION);
|
||||
const targets = this.getElements(this.selectors.ADDSECTIONREGION);
|
||||
targets.forEach(element => {
|
||||
element.classList.toggle(this.classes.DISABLED, locked);
|
||||
element.classList.toggle(this.classes.ITALIC, locked);
|
||||
this.setElementLocked(element, locked);
|
||||
const addSectionElement = element.querySelector(this.selectors.ADDSECTION);
|
||||
addSectionElement.classList.toggle(this.classes.DISABLED, locked);
|
||||
this.setElementLocked(addSectionElement, locked);
|
||||
// We tweak the element to show a tooltip as a title attribute.
|
||||
if (locked) {
|
||||
getString('sectionaddmax', 'core_courseformat')
|
||||
.then((text) => addSectionElement.setAttribute('title', text))
|
||||
.catch(Notification.exception);
|
||||
addSectionElement.style.pointerEvents = null; // Unlocks the pointer events.
|
||||
addSectionElement.style.userSelect = null; // Unlocks the pointer events.
|
||||
} else {
|
||||
addSectionElement.setAttribute('title', addSectionElement.dataset.addSections);
|
||||
}
|
||||
});
|
||||
const courseAddSection = this.getElement(this.selectors.COURSEADDSECTION);
|
||||
const addSection = courseAddSection.querySelector(this.selectors.ADDSECTION);
|
||||
addSection.classList.toggle(this.classes.DISPLAYNONE, locked);
|
||||
const noMoreSections = courseAddSection.querySelector(this.selectors.MAXSECTIONSWARNING);
|
||||
noMoreSections.classList.toggle(this.classes.DISPLAYNONE, !locked);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,11 +153,11 @@ class addsection implements named_templatable, renderable {
|
||||
if ($singlesection) {
|
||||
$params['sectionreturn'] = $singlesection;
|
||||
}
|
||||
|
||||
$data->addsections = (object) [
|
||||
'url' => new moodle_url('/course/changenumsections.php', $params),
|
||||
'title' => $addstring,
|
||||
'newsection' => $maxsections - $lastsection,
|
||||
'canaddsection' => $lastsection < $maxsections,
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
|
@ -51,18 +51,24 @@
|
||||
</a>
|
||||
{{/decrease}}
|
||||
{{#addsections}}
|
||||
|
||||
<a href="{{{url}}}"
|
||||
class="btn add-section d-flex justify-content-center align-items-center p-3"
|
||||
data-add-sections="{{title}}"
|
||||
data-new-sections="{{newsection}}"
|
||||
data-action="addSection"
|
||||
{{#insertafter}} data-id="{{id}}" {{/insertafter}}
|
||||
>
|
||||
{{#pix}} t/add, core {{/pix}}
|
||||
{{title}}
|
||||
</a>
|
||||
|
||||
<a href="{{{url}}}"
|
||||
class="w-100 btn add-section justify-content-center align-items-center p-3"
|
||||
data-add-sections="{{title}}"
|
||||
data-new-sections="{{newsection}}"
|
||||
data-action="addSection"
|
||||
{{#insertafter}} data-id="{{id}}" {{/insertafter}}
|
||||
>
|
||||
{{#pix}} t/add, core {{/pix}}
|
||||
{{title}}
|
||||
</a>
|
||||
<div class="d-none p-3 max-section-alert" data-region="max-sections-warning">
|
||||
<div class="w-100 text-center">
|
||||
{{#pix}}t/block, moodle{{/pix}}
|
||||
</div>
|
||||
<div class="w-100 font-italic text-center">
|
||||
{{#str}}maxsectionaddmessage, core_courseformat{{/str}}
|
||||
</div>
|
||||
</div>
|
||||
{{/addsections}}
|
||||
</div>
|
||||
{{/showaddsection}}
|
||||
|
@ -33,21 +33,21 @@
|
||||
}
|
||||
}}
|
||||
{{#showaddsection}}
|
||||
<div class="changenumsections bulk-hidden" data-region="section-addsection">
|
||||
<div class="changenumsections bulk-hidden {{^canaddsection}}disabled{{/canaddsection}}" data-region="section-addsection">
|
||||
{{#addsections}}
|
||||
{{< core_courseformat/local/content/divider}}
|
||||
{{$extraclasses}}always-hidden mt-2{{/extraclasses}}
|
||||
{{$content}}
|
||||
<a href="{{{url}}}"
|
||||
class="btn add-content section-modchooser section-modchooser-link activitychooser-button d-flex justify-content-center align-items-center p-1 icon-no-margin"
|
||||
class="btn add-content section-modchooser section-modchooser-link activitychooser-button d-flex justify-content-center align-items-center p-1 icon-no-margin
|
||||
{{^canaddsection}}disabled{{/canaddsection}}"
|
||||
data-add-sections="{{title}}"
|
||||
data-new-sections="{{newsection}}"
|
||||
data-action="addSection"
|
||||
{{#insertafter}} data-id="{{id}}" {{/insertafter}}
|
||||
title="{{title}}"
|
||||
title="{{#canaddsection}}{{title}}{{/canaddsection}}{{^canaddsection}}{{#str}}sectionaddmax, core_courseformat{{/str}}{{/canaddsection}}"
|
||||
>
|
||||
{{#pix}} t/add, core {{/pix}}
|
||||
<span class="sr-only">{{title}}</span>
|
||||
</a>
|
||||
{{/content}}
|
||||
{{/ core_courseformat/local/content/divider}}
|
||||
|
@ -381,3 +381,17 @@ Feature: Course index depending on role
|
||||
And I turn editing mode on
|
||||
When I set the field "Edit section name" in the "page-header" "region" to "Custom section name"
|
||||
Then I should see "Custom section name" in the "courseindex-content" "region"
|
||||
|
||||
@javascript
|
||||
Scenario: We cannot add a section when the number of section reaches maxsections but as soon as we reach under the limit we can add a section again.
|
||||
Given the following config values are set as admin:
|
||||
| maxsections | 4 | moodlecourse|
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
Then I should see "Section 1" in the "courseindex-content" "region"
|
||||
And ".disabled" "css_element" should exist in the "[data-action='addSection']" "css_element"
|
||||
And I should see "You have reached the maximum number of sections allowed for a course."
|
||||
And I delete section "4"
|
||||
And I click on "Delete" "button" in the ".modal" "css_element"
|
||||
And ".disabled" "css_element" should not exist in the "[data-action='addSection']" "css_element"
|
||||
And I should not see "You have reached the maximum number of sections allowed for a course."
|
||||
|
@ -63,6 +63,7 @@ $string['cmsmove_title'] = 'Move selected activities';
|
||||
$string['cmsmove_info'] = 'Move {$a} activities after';
|
||||
$string['courseindex'] = 'Course index';
|
||||
$string['courseindexoptions'] = 'Course index options';
|
||||
$string['maxsectionaddmessage'] = 'You have reached the maximum number of sections allowed for a course.';
|
||||
$string['nobulkaction'] = 'No bulk actions available';
|
||||
$string['preference:coursesectionspreferences'] = 'Section user preferences for course {$a}';
|
||||
$string['privacy:metadata:preference:coursesectionspreferences'] = 'Section user preferences like collapsed and expanded.';
|
||||
@ -72,6 +73,7 @@ $string['section_show_feedback'] = 'Course section {$a->name} shown.';
|
||||
$string['section_show_feedback_batch'] = 'Selected {$a->count} course sections shown.';
|
||||
$string['section_delete_feedback'] = 'Course section {$a->name} deleted.';
|
||||
$string['section_delete_feedback_batch'] = 'Selected {$a->count} course sections deleted.';
|
||||
$string['sectionaddmax'] = 'You have reached the maximum number of sections allowed for a course...';
|
||||
$string['sectionavailability_title'] = 'Section availability';
|
||||
$string['sectiondelete_info'] = 'This will delete {$a->name} and all the activities it contains.';
|
||||
$string['sectiondelete_title'] = 'Delete section?';
|
||||
|
@ -1256,6 +1256,13 @@ $divider-hover-color: $primary !default;
|
||||
}
|
||||
}
|
||||
|
||||
.max-section-alert {
|
||||
border-top: $divider-width dashed $border-color;
|
||||
font-size: $font-size-sm;
|
||||
font-weight: normal;
|
||||
color: $gray-500;
|
||||
}
|
||||
|
||||
/* Single section page specific styles */
|
||||
|
||||
.single-section {
|
||||
@ -1549,6 +1556,9 @@ $divider-hover-color: $primary !default;
|
||||
width: 100%;
|
||||
margin: map-get($spacers, 2) map-get($spacers, 1);
|
||||
border-top: $divider-width dashed $divider-color;
|
||||
.changenumsections.disabled & {
|
||||
border-top: $divider-width dashed $divider-color;
|
||||
}
|
||||
}
|
||||
.divider-content {
|
||||
opacity: 0;
|
||||
@ -1588,6 +1598,9 @@ $divider-hover-color: $primary !default;
|
||||
&:has(.btn.add-content:hover) {
|
||||
hr {
|
||||
border-color: $divider-hover-color;
|
||||
.changenumsections.disabled & {
|
||||
border-color: $gray-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1625,6 +1638,20 @@ $divider-hover-color: $primary !default;
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.changenumsections.disabled & {
|
||||
color: $gray-500;
|
||||
background-color: $gray-200;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $gray-500;
|
||||
background-color: $gray-200;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
pointer-events: auto; // Restore pointer events for the disabled button so we can see the tooltip.
|
||||
}
|
||||
}
|
||||
|
||||
/* Bulk editing */
|
||||
|
@ -29098,6 +29098,13 @@ span.editinstructions .alert-link {
|
||||
color: #0f6cbf;
|
||||
}
|
||||
|
||||
.max-section-alert {
|
||||
border-top: 2px dashed #dee2e6;
|
||||
font-size: 0.8203125rem;
|
||||
font-weight: normal;
|
||||
color: #8f959e;
|
||||
}
|
||||
|
||||
/* Single section page specific styles */
|
||||
.single-section > ul > .course-section.hidden .section-item {
|
||||
background-color: inherit;
|
||||
@ -29757,6 +29764,9 @@ span.editinstructions .alert-link {
|
||||
margin: 0.5rem 0.25rem;
|
||||
border-top: 2px dashed #dee2e6;
|
||||
}
|
||||
.changenumsections.disabled .divider hr {
|
||||
border-top: 2px dashed #dee2e6;
|
||||
}
|
||||
.divider .divider-content {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
@ -29786,6 +29796,9 @@ span.editinstructions .alert-link {
|
||||
.divider:has(.btn.add-content:hover) hr {
|
||||
border-color: #0f6cbf;
|
||||
}
|
||||
.changenumsections.disabled .divider:has(.btn.add-content:hover) hr {
|
||||
border-color: #e9ecef;
|
||||
}
|
||||
|
||||
.activity:focus-within + .activity .divider .divider-content,
|
||||
.course-section-header:focus-within + .content .section .activity:first-child .divider .divider-content,
|
||||
@ -29816,6 +29829,19 @@ span.editinstructions .alert-link {
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.changenumsections.disabled .btn.add-content {
|
||||
color: #8f959e;
|
||||
background-color: #e9ecef;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.changenumsections.disabled .btn.add-content:hover, .changenumsections.disabled .btn.add-content:focus {
|
||||
color: #8f959e;
|
||||
background-color: #e9ecef;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Bulk editing */
|
||||
.bulkenabled .bulk-hidden {
|
||||
|
@ -29098,6 +29098,13 @@ span.editinstructions .alert-link {
|
||||
color: #0f6cbf;
|
||||
}
|
||||
|
||||
.max-section-alert {
|
||||
border-top: 2px dashed #dee2e6;
|
||||
font-size: 0.8203125rem;
|
||||
font-weight: normal;
|
||||
color: #8f959e;
|
||||
}
|
||||
|
||||
/* Single section page specific styles */
|
||||
.single-section > ul > .course-section.hidden .section-item {
|
||||
background-color: inherit;
|
||||
@ -29757,6 +29764,9 @@ span.editinstructions .alert-link {
|
||||
margin: 0.5rem 0.25rem;
|
||||
border-top: 2px dashed #dee2e6;
|
||||
}
|
||||
.changenumsections.disabled .divider hr {
|
||||
border-top: 2px dashed #dee2e6;
|
||||
}
|
||||
.divider .divider-content {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
@ -29786,6 +29796,9 @@ span.editinstructions .alert-link {
|
||||
.divider:has(.btn.add-content:hover) hr {
|
||||
border-color: #0f6cbf;
|
||||
}
|
||||
.changenumsections.disabled .divider:has(.btn.add-content:hover) hr {
|
||||
border-color: #e9ecef;
|
||||
}
|
||||
|
||||
.activity:focus-within + .activity .divider .divider-content,
|
||||
.course-section-header:focus-within + .content .section .activity:first-child .divider .divider-content,
|
||||
@ -29816,6 +29829,19 @@ span.editinstructions .alert-link {
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.changenumsections.disabled .btn.add-content {
|
||||
color: #8f959e;
|
||||
background-color: #e9ecef;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.changenumsections.disabled .btn.add-content:hover, .changenumsections.disabled .btn.add-content:focus {
|
||||
color: #8f959e;
|
||||
background-color: #e9ecef;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Bulk editing */
|
||||
.bulkenabled .bulk-hidden {
|
||||
|
Loading…
x
Reference in New Issue
Block a user