diff --git a/course/format/amd/build/local/courseindex/cm.min.js b/course/format/amd/build/local/courseindex/cm.min.js
index 7f17990e6e9..41f6af25e19 100644
--- a/course/format/amd/build/local/courseindex/cm.min.js
+++ b/course/format/amd/build/local/courseindex/cm.min.js
@@ -1,2 +1,2 @@
-define ("core_courseformat/local/courseindex/cm",["exports","core_courseformat/local/courseeditor/dndcmitem","core/templates","core/prefetch"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=e(b);c=e(c);d=e(d);function e(a){return a&&a.__esModule?a:{default:a}}function f(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){f=function(a){return typeof a}}else{f=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return f(a)}function g(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function h(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){g(i,d,e,f,h,"next",a)}function h(a){g(i,d,e,f,h,"throw",a)}f(void 0)})}}function i(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function j(a,b){for(var c=0,d;c.\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: state.cm.get(this.id),\n });\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n\n}\n"],"file":"cm.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../src/local/courseindex/cm.js"],"names":["Prefetch","prefetchTemplate","Component","name","selectors","CM_NAME","CM_COMPLETION","classes","CMHIDDEN","LOCKED","RESTRICTIONS","PAGEITEM","id","element","dataset","state","configDragDrop","_refreshCompletion","cm","get","Config","contextid","courseContextId","contextInstanceId","classList","add","watch","handler","remove","_refreshCm","toggle","visible","getElement","innerHTML","DRAGGING","dragging","locked","hascmrectrictions","reactive","isEditing","istrackeduser","completionElement","value","completionstate","exporter","getExporter","data","cmCompletion","Templates","renderForPromise","html","js","replaceNode","target","document","getElementById","DndCmItem"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\nimport Config from 'core/config';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n PAGEITEM: 'pageitem',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: state.cm.get(this.id),\n });\n // Check if this we are displaying this activity id page.\n if (Config.contextid != Config.courseContextId && Config.contextInstanceId == this.id) {\n this.element.classList.add(this.classes.PAGEITEM);\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n}\n"],"file":"cm.min.js"}
\ No newline at end of file
diff --git a/course/format/amd/src/local/courseindex/cm.js b/course/format/amd/src/local/courseindex/cm.js
index 4b4e903965d..fe0c696b191 100644
--- a/course/format/amd/src/local/courseindex/cm.js
+++ b/course/format/amd/src/local/courseindex/cm.js
@@ -27,6 +27,7 @@
import DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';
import Templates from 'core/templates';
import Prefetch from 'core/prefetch';
+import Config from 'core/config';
// Prefetch the completion icons template.
const completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';
@@ -50,6 +51,7 @@ export default class Component extends DndCmItem {
CMHIDDEN: 'dimmed',
LOCKED: 'editinprogress',
RESTRICTIONS: 'rectrictions',
+ PAGEITEM: 'pageitem',
};
// We need our id to watch specific events.
this.id = this.element.dataset.id;
@@ -81,6 +83,10 @@ export default class Component extends DndCmItem {
state,
element: state.cm.get(this.id),
});
+ // Check if this we are displaying this activity id page.
+ if (Config.contextid != Config.courseContextId && Config.contextInstanceId == this.id) {
+ this.element.classList.add(this.classes.PAGEITEM);
+ }
}
/**
@@ -141,5 +147,4 @@ export default class Component extends DndCmItem {
throw error;
}
}
-
}
diff --git a/theme/boost/scss/moodle/courseindex.scss b/theme/boost/scss/moodle/courseindex.scss
index f1dc7a32b33..bd6c0fb5250 100644
--- a/theme/boost/scss/moodle/courseindex.scss
+++ b/theme/boost/scss/moodle/courseindex.scss
@@ -5,6 +5,7 @@ $courseindex-item-dragging-bg: theme-color-level('info', -11) !default;
$courseindex-item-dragging-border: theme-color-level('info', -9) !default;
$courseindex-item-active-border: $gray-300 !default;
$courseindex-item-active-bg: $gray-100 !default;
+$courseindex-item-page-bg: $gray-200 !default;
$courseindex-item-padding-y: 0.5rem;
$courseindex-item-padding-x: 0.5rem;
$courseindex-item-radius: $border-radius !default;
@@ -89,6 +90,15 @@ $courseindex-item-current: $primary !default;
}
}
+ // Current page item.
+ &.pageitem {
+ background-color: $courseindex-item-page-bg;
+ color: $courseindex-link-hover-color;
+ a {
+ color: $courseindex-link-hover-color;
+ }
+ }
+
// Completion.
.completioninfo {
min-width: 24px;
diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css
index 88094569516..f01240e5349 100644
--- a/theme/boost/style/moodle.css
+++ b/theme/boost/style/moodle.css
@@ -20957,6 +20957,11 @@ div.editor_atto_toolbar button .icon {
display: none; }
.courseindex .courseindex-item.rectrictions .courseindex-locked {
display: block; }
+ .courseindex .courseindex-item.pageitem {
+ background-color: #e9ecef;
+ color: black; }
+ .courseindex .courseindex-item.pageitem a {
+ color: black; }
.courseindex .courseindex-item .completioninfo {
min-width: 24px;
transform: scale(0.7); }
diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css
index 309af898d17..31a7f10a09b 100644
--- a/theme/classic/style/moodle.css
+++ b/theme/classic/style/moodle.css
@@ -20903,6 +20903,11 @@ div.editor_atto_toolbar button .icon {
display: none; }
.courseindex .courseindex-item.rectrictions .courseindex-locked {
display: block; }
+ .courseindex .courseindex-item.pageitem {
+ background-color: #e9ecef;
+ color: black; }
+ .courseindex .courseindex-item.pageitem a {
+ color: black; }
.courseindex .courseindex-item .completioninfo {
min-width: 24px;
transform: scale(0.7); }