Merge branch 'MDL-72897-master' of https://github.com/ferranrecio/moodle

This commit is contained in:
Ilya Tregubov
2022-01-12 11:32:36 +02:00
22 changed files with 267 additions and 37 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core_courseformat/local/courseeditor/exporter",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function b(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function c(a){for(var c=1,e;c<arguments.length;c++){e=null!=arguments[c]?arguments[c]:{};if(c%2){b(Object(e),!0).forEach(function(b){d(a,b,e[b])})}else if(Object.getOwnPropertyDescriptors){Object.defineProperties(a,Object.getOwnPropertyDescriptors(e))}else{b(Object(e)).forEach(function(b){Object.defineProperty(a,b,Object.getOwnPropertyDescriptor(e,b))})}}return a}function d(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}function e(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function f(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function g(a,b,c){if(b)f(a.prototype,b);if(c)f(a,c);return a}var h=function(){function a(b){e(this,a);this.reactive=b;this.COMPLETIONS=["incomplete","complete","complete","fail"]}g(a,[{key:"course",value:function course(a){var b,c,d=this,e={sections:[],editmode:this.reactive.isEditing,highlighted:null!==(b=a.course.highlighted)&&void 0!==b?b:""},f=null!==(c=a.course.sectionlist)&&void 0!==c?c:[];f.forEach(function(b){var c,f=null!==(c=a.section.get(b))&&void 0!==c?c:{},g=d.section(a,f);e.sections.push(g)});e.hassections=0!=e.sections.length;return e}},{key:"section",value:function(a,b){var d,e,f=this,g=c({},b,{highlighted:null!==(d=a.course.highlighted)&&void 0!==d?d:"",cms:[]}),h=null!==(e=b.cmlist)&&void 0!==e?e:[];h.forEach(function(b){var c=a.cm.get(b),d=f.cm(a,c);g.cms.push(d)});g.hascms=0!=g.cms.length;return g}},{key:"cm",value:function(a,b){var d=c({},b,{isactive:!1});return d}},{key:"cmDraggableData",value:function cmDraggableData(a,b){var c=a.cm.get(b);if(!c){return null}var d,e=a.section.get(c.sectionid),f=null===e||void 0===e?void 0:e.cmlist.indexOf(c.id);if(f!==void 0){d=null===e||void 0===e?void 0:e.cmlist[f+1]}return{type:"cm",id:c.id,name:c.name,sectionid:c.sectionid,nextcmid:d}}},{key:"sectionDraggableData",value:function sectionDraggableData(a,b){var c=a.section.get(b);if(!c){return null}return{type:"section",id:c.id,name:c.name,number:c.number}}},{key:"cmCompletion",value:function cmCompletion(a,b){var c={statename:"",state:"NaN"};if(b.completionstate!==void 0){var d;c.state=b.completionstate;c.hasstate=!0;var e=null!==(d=this.COMPLETIONS[b.completionstate])&&void 0!==d?d:"NaN";c["is".concat(e)]=!0}return c}}]);return a}();a.default=h;return a.default});
define ("core_courseformat/local/courseeditor/exporter",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function b(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function c(a){for(var c=1,e;c<arguments.length;c++){e=null!=arguments[c]?arguments[c]:{};if(c%2){b(Object(e),!0).forEach(function(b){d(a,b,e[b])})}else if(Object.getOwnPropertyDescriptors){Object.defineProperties(a,Object.getOwnPropertyDescriptors(e))}else{b(Object(e)).forEach(function(b){Object.defineProperty(a,b,Object.getOwnPropertyDescriptor(e,b))})}}return a}function d(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}function e(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function f(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function g(a,b,c){if(b)f(a.prototype,b);if(c)f(a,c);return a}var h=function(){function a(b){e(this,a);this.reactive=b;this.COMPLETIONS=["incomplete","complete","complete","fail"]}g(a,[{key:"course",value:function course(a){var b,c,d=this,e={sections:[],editmode:this.reactive.isEditing,highlighted:null!==(b=a.course.highlighted)&&void 0!==b?b:""},f=null!==(c=a.course.sectionlist)&&void 0!==c?c:[];f.forEach(function(b){var c,f=null!==(c=a.section.get(b))&&void 0!==c?c:{},g=d.section(a,f);e.sections.push(g)});e.hassections=0!=e.sections.length;return e}},{key:"section",value:function(a,b){var d,e,f=this,g=c({},b,{highlighted:null!==(d=a.course.highlighted)&&void 0!==d?d:"",cms:[]}),h=null!==(e=b.cmlist)&&void 0!==e?e:[];h.forEach(function(b){var c=a.cm.get(b),d=f.cm(a,c);g.cms.push(d)});g.hascms=0!=g.cms.length;return g}},{key:"cm",value:function(a,b){var d=c({},b,{isactive:!1});return d}},{key:"cmDraggableData",value:function cmDraggableData(a,b){var c=a.cm.get(b);if(!c){return null}var d,e=a.section.get(c.sectionid),f=null===e||void 0===e?void 0:e.cmlist.indexOf(c.id);if(f!==void 0){d=null===e||void 0===e?void 0:e.cmlist[f+1]}return{type:"cm",id:c.id,name:c.name,sectionid:c.sectionid,nextcmid:d}}},{key:"sectionDraggableData",value:function sectionDraggableData(a,b){var c=a.section.get(b);if(!c){return null}return{type:"section",id:c.id,name:c.name,number:c.number}}},{key:"cmCompletion",value:function cmCompletion(a,b){var c={statename:"",state:"NaN"};if(b.completionstate!==void 0){var d;c.state=b.completionstate;c.hasstate=!0;var e=null!==(d=this.COMPLETIONS[b.completionstate])&&void 0!==d?d:"NaN";c["is".concat(e)]=!0}return c}},{key:"allItemsArray",value:function allItemsArray(a){var b,c=[],d=null!==(b=a.course.sectionlist)&&void 0!==b?b:[];d.forEach(function(b){var d,e=a.section.get(b);c.push({type:"section",id:e.id,url:e.sectionurl});var f=null!==(d=e.cmlist)&&void 0!==d?d:[];f.forEach(function(b){var d=a.cm.get(b);c.push({type:"cm",id:d.id,url:d.url})})});return c}}]);return a}();a.default=h;return a.default});
//# sourceMappingURL=exporter.min.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+35
View File
@@ -49,6 +49,7 @@ export default class Component extends BaseComponent {
SECTION_CMLIST: `[data-for='cmlist']`,
COURSE_SECTIONLIST: `[data-for='course_sectionlist']`,
CM: `[data-for='cmitem']`,
PAGE: `#page`,
TOGGLER: `[data-action="togglecoursecontentsection"]`,
COLLAPSE: `[data-toggle="collapse"]`,
TOGGLEALL: `[data-toggle="toggleall"]`,
@@ -124,6 +125,13 @@ export default class Component extends BaseComponent {
CourseEvents.manualCompletionToggled,
this._completionHandler
);
// Capture page scroll to update page item.
this.addEventListener(
document.querySelector(this.selectors.PAGE),
"scroll",
this._scrollHandler
);
}
/**
@@ -291,6 +299,33 @@ export default class Component extends BaseComponent {
this.reactive.dispatch('cmCompletion', [detail.cmid], detail.completed);
}
/**
* Check the current page scroll and update the active element if necessary.
*/
_scrollHandler() {
const pageOffset = document.querySelector(this.selectors.PAGE).scrollTop;
const items = this.reactive.getExporter().allItemsArray(this.reactive.state);
// Check what is the active element now.
let pageItem = null;
items.every(item => {
const index = (item.type === 'section') ? this.sections : this.cms;
if (index[item.id] === undefined) {
return true;
}
const element = index[item.id].element;
// Activities without url can only be page items in edit mode.
if (item.type === 'cm' && !item.url && !this.reactive.isEditing) {
return pageOffset >= element.offsetTop;
}
pageItem = item;
return pageOffset >= element.offsetTop;
});
if (pageItem) {
this.reactive.dispatch('setPageItem', pageItem.type, pageItem.id);
}
}
/**
* Update a course section when the section number changes.
*
@@ -177,4 +177,27 @@ export default class {
}
return data;
}
/**
* Return a sorted list of all sections and cms items in the state.
*
* @param {Object} state the current state.
* @returns {Array} all sections and cms items in the state.
*/
allItemsArray(state) {
const items = [];
const sectionlist = state.course.sectionlist ?? [];
// Add sections.
sectionlist.forEach(sectionid => {
const sectioninfo = state.section.get(sectionid);
items.push({type: 'section', id: sectioninfo.id, url: sectioninfo.sectionurl});
// Add cms.
const cmlist = sectioninfo.cmlist ?? [];
cmlist.forEach(cmid => {
const cminfo = state.cm.get(cmid);
items.push({type: 'cm', id: cminfo.id, url: cminfo.url});
});
});
return items;
}
}
@@ -166,6 +166,7 @@ export default class {
* @param {bool} dragValue the new dragging value
*/
cmDrag(stateManager, cmIds, dragValue) {
this.setPageItem(stateManager);
this._setElementsValue(stateManager, 'cm', cmIds, 'dragging', dragValue);
}
@@ -177,6 +178,7 @@ export default class {
* @param {bool} dragValue the new dragging value
*/
sectionDrag(stateManager, sectionIds, dragValue) {
this.setPageItem(stateManager);
this._setElementsValue(stateManager, 'section', sectionIds, 'dragging', dragValue);
}
@@ -225,6 +227,48 @@ export default class {
stateManager.setReadOnly(true);
}
/**
* Set the page current item.
*
* Only one element of the course state can be the page item at a time.
*
* There are several actions that can alter the page current item. For example, when the user is in an activity
* page, the page item is always the activity one. However, in a course page, when the user scrolls to an element,
* this element get the page item.
*
* If the page item is static means that it is not meant to change. This is important because
* static page items has some special logic. For example, if a cm is the static page item
* and it is inside a collapsed section, the course index will expand the section to make it visible.
*
* @param {StateManager} stateManager the current state manager
* @param {String|undefined} type the element type (section or cm). Undefined will remove the current page item.
* @param {Number|undefined} id the element id
* @param {boolean|undefined} isStatic if the page item is static
*/
setPageItem(stateManager, type, id, isStatic) {
let newPageItem;
if (type !== undefined) {
newPageItem = stateManager.get(type, id);
if (!newPageItem) {
return;
}
}
stateManager.setReadOnly(false);
// Remove the current page item.
const course = stateManager.get('course');
course.pageItem = null;
// Save the new page item.
if (newPageItem) {
course.pageItem = {
id,
type,
sectionId: (type == 'section') ? newPageItem.id : newPageItem.sectionid,
isStatic,
};
}
stateManager.setReadOnly(true);
}
/**
* Unlock all course elements.
*
+33 -3
View File
@@ -79,14 +79,21 @@ export default class Component extends DndCmItem {
stateReady(state) {
this.configDragDrop(this.id);
const cm = state.cm.get(this.id);
const course = state.course;
// Refresh completion icon.
this._refreshCompletion({
state,
element: cm,
});
// Check if this we are displaying this activity id page.
// Check if the current url is the cm url.
if (window.location.href == cm.url || window.location.href == `${course.baseurl}#${cm.anchor}`) {
this.reactive.dispatch('setPageItem', 'cm', this.id);
this.element.scrollIntoView({block: "center"});
}
// Check if this we are displaying this activity page.
if (Config.contextid != Config.courseContextId && Config.contextInstanceId == this.id) {
this.element.classList.add(this.classes.PAGEITEM);
this.reactive.dispatch('setPageItem', 'cm', this.id, true);
this.element.scrollIntoView({block: "center"});
}
// Add anchor logic if the element is not user visible.
if (!cm.uservisible) {
@@ -108,6 +115,7 @@ export default class Component extends DndCmItem {
{watch: `cm[${this.id}]:deleted`, handler: this.remove},
{watch: `cm[${this.id}]:updated`, handler: this._refreshCm},
{watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},
{watch: `course.pageItem:updated`, handler: this._refreshPageItem},
];
}
@@ -127,6 +135,23 @@ export default class Component extends DndCmItem {
this.locked = element.locked;
}
/**
* Handle a page item update.
*
* @param {Object} details the update details
* @param {Object} details.element the course state data.
*/
_refreshPageItem({element}) {
if (!element.pageItem) {
return;
}
const isPageId = (element.pageItem.type == 'cm' && element.pageItem.id == this.id);
this.element.classList.toggle(this.classes.PAGEITEM, isPageId);
if (isPageId && !this.reactive.isEditing) {
this.element.scrollIntoView({block: "nearest"});
}
}
/**
* Update the activity completion icon.
*
@@ -166,7 +191,12 @@ export default class Component extends DndCmItem {
const cm = this.reactive.get('cm', this.id);
// If the user cannot access the element but the element is present in the page
// the new url should be an anchor link.
if (document.getElementById(cm.anchor)) {
const element = document.getElementById(cm.anchor);
if (element) {
// Marc the element as page item once the event is handled.
setTimeout(() => {
this.reactive.dispatch('setPageItem', 'cm', cm.id);
}, 50);
return;
}
// If the element is not present in the page we need to go to the specific section.
@@ -74,8 +74,10 @@ export default class Component extends BaseComponent {
/**
* Initial state ready method.
*
* @param {Object} state the state data
*/
stateReady() {
stateReady(state) {
// Activate section togglers.
this.addEventListener(this.element, 'click', this._sectionTogglers);
@@ -89,6 +91,9 @@ export default class Component extends BaseComponent {
this.cms[cm.dataset.id] = cm;
});
// Set the page item if any.
this._refreshPageItem({element: state.course, state});
// Configure Aria Tree.
this.contentTree = new ContentTree(this.element, this.selectors, this.reactive.isEditing);
}
@@ -100,6 +105,8 @@ export default class Component extends BaseComponent {
{watch: `cm:deleted`, handler: this._deleteCm},
{watch: `section:created`, handler: this._createSection},
{watch: `section:deleted`, handler: this._deleteSection},
{watch: `course.pageItem:created`, handler: this._refreshPageItem},
{watch: `course.pageItem:updated`, handler: this._refreshPageItem},
// Sections and cm sorting.
{watch: `course.sectionlist:updated`, handler: this._refreshCourseSectionlist},
{watch: `section.cmlist:updated`, handler: this._refreshSectionCmlist},
@@ -192,6 +199,28 @@ export default class Component extends BaseComponent {
jQuery(collapsible).collapse(togglerValue);
}
/**
* Handle a page item update.
*
* @param {Object} details the update details
* @param {Object} details.state the state data.
* @param {Object} details.element the course state data.
*/
_refreshPageItem({element, state}) {
if (!element?.pageItem?.isStatic || element.pageItem.type != 'cm') {
return;
}
// Check if we need to uncollapse the section and scroll to the element.
const section = state.section.get(element.pageItem.sectionId);
if (section.indexcollapsed) {
this._expandSectionNode(section, true);
setTimeout(
() => this.cms[element.pageItem.id]?.scrollIntoView({block: "nearest"}),
250
);
}
}
/**
* Create a newcm instance.
*
@@ -47,10 +47,12 @@ export default class Component extends DndSection {
SECTIONCURRENT: 'current',
LOCKED: 'editinprogress',
RESTRICTIONS: 'rectrictions',
PAGEITEM: 'pageitem',
};
// We need our id to watch specific events.
this.id = this.element.dataset.id;
this.isPageItem = false;
}
/**
@@ -74,16 +76,23 @@ export default class Component extends DndSection {
*/
stateReady(state) {
this.configState(state);
const sectionItem = this.getElement(this.selectors.SECTION_ITEM);
// Drag and drop is only available for components compatible course formats.
if (this.reactive.isEditing && this.reactive.supportComponents) {
// Init the inner dragable element passing the full section as affected region.
const titleitem = new SectionTitle({
...this,
element: this.getElement(this.selectors.SECTION_ITEM),
element: sectionItem,
fullregion: this.element,
});
this.configDragDrop(titleitem);
}
// Check if the current url is the section url.
const section = state.section.get(this.id);
if (window.location.href == section.sectionurl.replace(/&amp;/g, "&")) {
this.reactive.dispatch('setPageItem', 'section', this.id);
sectionItem.scrollIntoView();
}
}
/**
@@ -95,6 +104,7 @@ export default class Component extends DndSection {
return [
{watch: `section[${this.id}]:deleted`, handler: this.remove},
{watch: `section[${this.id}]:updated`, handler: this._refreshSection},
{watch: `course.pageItem:updated`, handler: this._refreshPageItem},
];
}
@@ -111,12 +121,12 @@ export default class Component extends DndSection {
* Update a course index section using the state information.
*
* @param {Object} param details the update details.
* @param {Object} param.element
* @param {Object} param.element the section element
*/
_refreshSection({element}) {
// Update classes.
const sectionitem = this.getElement(this.selectors.SECTION_ITEM);
sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);
const sectionItem = this.getElement(this.selectors.SECTION_ITEM);
sectionItem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);
this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);
this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);
this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);
@@ -125,4 +135,33 @@ export default class Component extends DndSection {
// Update title.
this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;
}
/**
* Handle a page item update.
*
* @param {Object} details the update details
* @param {Object} details.state the state data.
* @param {Object} details.element the course state data.
*/
_refreshPageItem({element, state}) {
if (!element.pageItem) {
return;
}
if (element.pageItem.sectionId !== this.id && this.isPageItem) {
this.pageItem = false;
this.getElement(this.selectors.SECTION_ITEM).classList.remove(this.classes.PAGEITEM);
return;
}
const section = state.section.get(this.id);
if (section.indexcollapsed && !element.pageItem?.isStatic) {
this.pageItem = (element.pageItem?.sectionId == this.id);
} else {
this.pageItem = (element.pageItem.type == 'section' && element.pageItem.id == this.id);
}
const sectionItem = this.getElement(this.selectors.SECTION_ITEM);
sectionItem.classList.toggle(this.classes.PAGEITEM, this.pageItem ?? false);
if (this.pageItem && !this.reactive.isEditing) {
this.element.scrollIntoView({block: "nearest"});
}
}
}
@@ -73,7 +73,7 @@
>
<a data-toggle="collapse"
href="#courseindexcollapse{{number}}"
class="courseindex-link icons-collapse-expand {{#indexcollapsed}}collapsed{{/indexcollapsed}}"
class="courseindex-chevron icons-collapse-expand {{#indexcollapsed}}collapsed{{/indexcollapsed}}"
aria-expanded="{{^indexcollapsed}}true{{/indexcollapsed}}{{#indexcollapsed}}false{{/indexcollapsed}}"
aria-controls="courseindexcollapse{{number}}"
tabindex="-1"
+12 -4
View File
@@ -15,14 +15,16 @@ $courseindex-item-current: $primary !default;
@include hover-focus() {
color: $courseindex-link-hover-color;
.courseindex-link {
.courseindex-link,
.courseindex-chevron {
color: $courseindex-link-hover-color;
cursor: pointer;
}
&.dimmed {
color: $courseindex-link-hover-color;
.courseindex-link {
.courseindex-link,
.courseindex-chevron {
color: $courseindex-link-hover-color;
}
}
@@ -54,7 +56,8 @@ $courseindex-item-current: $primary !default;
padding-right: 4px;
}
.courseindex-link {
.courseindex-link,
.courseindex-chevron {
color: $courseindex-link-color;
@include hover-focus() {
color: $courseindex-link-hover-color;
@@ -75,7 +78,8 @@ $courseindex-item-current: $primary !default;
&.dimmed {
color: $courseindex-link-dimmed-color;
.courseindex-link {
.courseindex-link,
.courseindex-chevron {
color: $courseindex-link-dimmed-color;
}
}
@@ -94,9 +98,13 @@ $courseindex-item-current: $primary !default;
&.pageitem {
background-color: $courseindex-item-page-bg;
color: $courseindex-link-hover-color;
scroll-margin: 6rem;
a {
color: $courseindex-link-hover-color;
}
.courseindex-link {
text-shadow: 0 1px 0 rgba($courseindex-link-hover-color, .3);
}
}
// Completion.
+17 -6
View File
@@ -21234,19 +21234,26 @@ div.editor_atto_toolbar button .icon {
font-weight: bold; }
.courseindex .courseindex-item .icons-collapse-expand {
padding-right: 4px; }
.courseindex .courseindex-item .courseindex-link {
.courseindex .courseindex-item .courseindex-link,
.courseindex .courseindex-item .courseindex-chevron {
color: #495057; }
.courseindex .courseindex-item .courseindex-link:hover, .courseindex .courseindex-item .courseindex-link:focus {
.courseindex .courseindex-item .courseindex-link:hover, .courseindex .courseindex-item .courseindex-link:focus,
.courseindex .courseindex-item .courseindex-chevron:hover,
.courseindex .courseindex-item .courseindex-chevron:focus {
color: black;
text-decoration: none; }
.courseindex .courseindex-item:hover, .courseindex .courseindex-item:focus {
color: black; }
.courseindex .courseindex-item:hover .courseindex-link, .courseindex .courseindex-item:focus .courseindex-link {
.courseindex .courseindex-item:hover .courseindex-link,
.courseindex .courseindex-item:hover .courseindex-chevron, .courseindex .courseindex-item:focus .courseindex-link,
.courseindex .courseindex-item:focus .courseindex-chevron {
color: black;
cursor: pointer; }
.courseindex .courseindex-item:hover.dimmed, .courseindex .courseindex-item:focus.dimmed {
color: black; }
.courseindex .courseindex-item:hover.dimmed .courseindex-link, .courseindex .courseindex-item:focus.dimmed .courseindex-link {
.courseindex .courseindex-item:hover.dimmed .courseindex-link,
.courseindex .courseindex-item:hover.dimmed .courseindex-chevron, .courseindex .courseindex-item:focus.dimmed .courseindex-link,
.courseindex .courseindex-item:focus.dimmed .courseindex-chevron {
color: black; }
.courseindex .courseindex-item:hover.draggable, .courseindex .courseindex-item:focus.draggable {
cursor: pointer; }
@@ -21258,7 +21265,8 @@ div.editor_atto_toolbar button .icon {
border-color: #dee2e6; }
.courseindex .courseindex-item.dimmed {
color: #6a737b; }
.courseindex .courseindex-item.dimmed .courseindex-link {
.courseindex .courseindex-item.dimmed .courseindex-link,
.courseindex .courseindex-item.dimmed .courseindex-chevron {
color: #6a737b; }
.courseindex .courseindex-item .courseindex-locked {
display: none; }
@@ -21266,9 +21274,12 @@ div.editor_atto_toolbar button .icon {
display: block; }
.courseindex .courseindex-item.pageitem {
background-color: #e9ecef;
color: black; }
color: black;
scroll-margin: 6rem; }
.courseindex .courseindex-item.pageitem a {
color: black; }
.courseindex .courseindex-item.pageitem .courseindex-link {
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3); }
.courseindex .courseindex-item .completioninfo {
min-width: 24px; }
.courseindex .courseindex-item .completioninfo.completion_complete {
+17 -6
View File
@@ -21180,19 +21180,26 @@ div.editor_atto_toolbar button .icon {
font-weight: bold; }
.courseindex .courseindex-item .icons-collapse-expand {
padding-right: 4px; }
.courseindex .courseindex-item .courseindex-link {
.courseindex .courseindex-item .courseindex-link,
.courseindex .courseindex-item .courseindex-chevron {
color: #495057; }
.courseindex .courseindex-item .courseindex-link:hover, .courseindex .courseindex-item .courseindex-link:focus {
.courseindex .courseindex-item .courseindex-link:hover, .courseindex .courseindex-item .courseindex-link:focus,
.courseindex .courseindex-item .courseindex-chevron:hover,
.courseindex .courseindex-item .courseindex-chevron:focus {
color: black;
text-decoration: none; }
.courseindex .courseindex-item:hover, .courseindex .courseindex-item:focus {
color: black; }
.courseindex .courseindex-item:hover .courseindex-link, .courseindex .courseindex-item:focus .courseindex-link {
.courseindex .courseindex-item:hover .courseindex-link,
.courseindex .courseindex-item:hover .courseindex-chevron, .courseindex .courseindex-item:focus .courseindex-link,
.courseindex .courseindex-item:focus .courseindex-chevron {
color: black;
cursor: pointer; }
.courseindex .courseindex-item:hover.dimmed, .courseindex .courseindex-item:focus.dimmed {
color: black; }
.courseindex .courseindex-item:hover.dimmed .courseindex-link, .courseindex .courseindex-item:focus.dimmed .courseindex-link {
.courseindex .courseindex-item:hover.dimmed .courseindex-link,
.courseindex .courseindex-item:hover.dimmed .courseindex-chevron, .courseindex .courseindex-item:focus.dimmed .courseindex-link,
.courseindex .courseindex-item:focus.dimmed .courseindex-chevron {
color: black; }
.courseindex .courseindex-item:hover.draggable, .courseindex .courseindex-item:focus.draggable {
cursor: pointer; }
@@ -21204,7 +21211,8 @@ div.editor_atto_toolbar button .icon {
border-color: #dee2e6; }
.courseindex .courseindex-item.dimmed {
color: #6a737b; }
.courseindex .courseindex-item.dimmed .courseindex-link {
.courseindex .courseindex-item.dimmed .courseindex-link,
.courseindex .courseindex-item.dimmed .courseindex-chevron {
color: #6a737b; }
.courseindex .courseindex-item .courseindex-locked {
display: none; }
@@ -21212,9 +21220,12 @@ div.editor_atto_toolbar button .icon {
display: block; }
.courseindex .courseindex-item.pageitem {
background-color: #e9ecef;
color: black; }
color: black;
scroll-margin: 6rem; }
.courseindex .courseindex-item.pageitem a {
color: black; }
.courseindex .courseindex-item.pageitem .courseindex-link {
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3); }
.courseindex .courseindex-item .completioninfo {
min-width: 24px; }
.courseindex .courseindex-item .completioninfo.completion_complete {