From 7bf4235358047acc7896657dc0048e3b5f8a73c8 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 22 May 2024 10:47:21 +0100 Subject: [PATCH 01/12] New: Added correctness classes to progress bars --- js/PageLevelProgressIndicatorView.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index 571f387..af1c020 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -76,10 +76,14 @@ class PageLevelProgressIndicatorView extends Backbone.View { } checkCompletion() { - const percentage = this.setPercentageComplete(); + this.setPercentageComplete(); + const isComplete = this.model.get('_isComplete'); + const isCorrect = this.model.get('_isCorrect'); this.$el - .toggleClass('is-complete', percentage === 100) - .toggleClass('is-incomplete', percentage !== 100); + .toggleClass('is-complete', isComplete) + .toggleClass('is-incomplete', !isComplete) + .toggleClass('is-correct', isComplete && isCorrect) + .toggleClass('is-incorrect', isComplete && !isCorrect); } } From b614d4de179ccbdb9bb9018fef56e8c5b06d7e6f Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 22 May 2024 14:09:41 +0100 Subject: [PATCH 02/12] Update PageLevelProgressIndicatorView.js --- js/PageLevelProgressIndicatorView.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index af1c020..a586256 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -47,7 +47,6 @@ class PageLevelProgressIndicatorView extends Backbone.View { setPercentageComplete() { const percentage = this.calculatePercentage(); this.model.set('percentageComplete', percentage); - return percentage; } calculatePercentage() { From b38ef3b2156904cf0bcf441a6ff06e12243ac261 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 22 May 2024 14:11:07 +0100 Subject: [PATCH 03/12] Changed to absolute values --- js/PageLevelProgressIndicatorView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index a586256..a30f70d 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -81,8 +81,8 @@ class PageLevelProgressIndicatorView extends Backbone.View { this.$el .toggleClass('is-complete', isComplete) .toggleClass('is-incomplete', !isComplete) - .toggleClass('is-correct', isComplete && isCorrect) - .toggleClass('is-incorrect', isComplete && !isCorrect); + .toggleClass('is-correct', isComplete && isCorrect === true) + .toggleClass('is-incorrect', isComplete && isCorrect === false); } } From b7905a0db409c44c581e698786bd6795e4884537 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 22 May 2024 14:21:11 +0100 Subject: [PATCH 04/12] Revert to completion calculation As the completion calculation can be overridden and will change the concept of complete for the plp status e.g. for assessment pass requirements etc. --- js/PageLevelProgressIndicatorView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index a30f70d..dc5b0c2 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -47,6 +47,7 @@ class PageLevelProgressIndicatorView extends Backbone.View { setPercentageComplete() { const percentage = this.calculatePercentage(); this.model.set('percentageComplete', percentage); + return percentage; } calculatePercentage() { @@ -75,8 +76,8 @@ class PageLevelProgressIndicatorView extends Backbone.View { } checkCompletion() { - this.setPercentageComplete(); - const isComplete = this.model.get('_isComplete'); + const percentage = this.setPercentageComplete(); + const isComplete = (percentage === 100); const isCorrect = this.model.get('_isCorrect'); this.$el .toggleClass('is-complete', isComplete) From d94276f71a72e9085557a877ff9c05f050312ae8 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Tue, 4 Jun 2024 15:59:12 +0100 Subject: [PATCH 05/12] Added class is-partially-correct --- js/PageLevelProgressIndicatorView.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index dc5b0c2..28481a6 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -79,11 +79,13 @@ class PageLevelProgressIndicatorView extends Backbone.View { const percentage = this.setPercentageComplete(); const isComplete = (percentage === 100); const isCorrect = this.model.get('_isCorrect'); + const isPartlyCorrect = this.model.get('_isAtLeastOneCorrectSelection'); this.$el .toggleClass('is-complete', isComplete) .toggleClass('is-incomplete', !isComplete) .toggleClass('is-correct', isComplete && isCorrect === true) - .toggleClass('is-incorrect', isComplete && isCorrect === false); + .toggleClass('is-partially-correct', isComplete && isCorrect === false && isPartlyCorrect) + .toggleClass('is-incorrect', isComplete && isCorrect === false && !isPartlyCorrect); } } From f7644804df7f51b76962c3a7929ffab94c4fd64a Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 12 Jun 2024 08:37:41 +0100 Subject: [PATCH 06/12] Added correctness arialabels and _canShowMarking support --- js/PageLevelProgressIndicatorView.js | 12 +++++++----- templates/pageLevelProgressItem.jsx | 10 ++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index 28481a6..efc0a3d 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -78,14 +78,16 @@ class PageLevelProgressIndicatorView extends Backbone.View { checkCompletion() { const percentage = this.setPercentageComplete(); const isComplete = (percentage === 100); - const isCorrect = this.model.get('_isCorrect'); - const isPartlyCorrect = this.model.get('_isAtLeastOneCorrectSelection'); + const canShowMarking = Boolean(this.model.get('_canShowMarking')); + const isCorrect = (canShowMarking && isComplete && this.model.get('_isCorrect') === true); + const isPartlyCorrect = (canShowMarking && isComplete && this.model.get('_isCorrect') === false && this.model.get('_isAtLeastOneCorrectSelection')); + const isIncorrect = (canShowMarking && isComplete && this.model.get('_isCorrect') === false && !this.model.get('_isAtLeastOneCorrectSelection')); this.$el .toggleClass('is-complete', isComplete) .toggleClass('is-incomplete', !isComplete) - .toggleClass('is-correct', isComplete && isCorrect === true) - .toggleClass('is-partially-correct', isComplete && isCorrect === false && isPartlyCorrect) - .toggleClass('is-incorrect', isComplete && isCorrect === false && !isPartlyCorrect); + .toggleClass('is-correct', isCorrect) + .toggleClass('is-partially-correct', isPartlyCorrect) + .toggleClass('is-incorrect', isIncorrect); } } diff --git a/templates/pageLevelProgressItem.jsx b/templates/pageLevelProgressItem.jsx index cb16f2e..a611c7a 100644 --- a/templates/pageLevelProgressItem.jsx +++ b/templates/pageLevelProgressItem.jsx @@ -13,6 +13,9 @@ export default function PageLevelProgressItem(props) { _isLocked, _isVisible, _isComplete, + _isCorrect, + _isAtLeastOneCorrectSelection, + _canShowMarking, title, altTitle, _id, @@ -20,6 +23,10 @@ export default function PageLevelProgressItem(props) { _children } = props; + const isCorrect = (_canShowMarking && _isComplete && _isCorrect === true); + const isPartlyCorrect = (_canShowMarking && _isComplete && _isCorrect === false && _isAtLeastOneCorrectSelection); + const isIncorrect = (_canShowMarking && _isComplete && _isCorrect === false && !_isAtLeastOneCorrectSelection); + const indicatorSeat = React.createRef(); useEffect(() => { if (_isOptional) return; @@ -57,6 +64,9 @@ export default function PageLevelProgressItem(props) { _isOptional && `${_globals._extensions._pageLevelProgress.optionalContent}.`, !_isOptional && _isComplete && `${_globals._accessibility._ariaLabels.complete}.`, !_isOptional && !_isComplete && `${_globals._accessibility._ariaLabels.incomplete}.`, + isCorrect && `${_globals._accessibility._ariaLabels.answeredCorrectly}.`, + isPartlyCorrect && `${_globals._accessibility._ariaLabels.answeredPartlyCorrect ?? _globals._accessibility._ariaLabels.answeredIncorrectly}.`, + isIncorrect && `${_globals._accessibility._ariaLabels.answeredIncorrectly}.`, compile(a11y.normalize(altTitle || title)) ])} > From c480f907896ca0136f8364dd3e2b82d01f199238 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 12 Jun 2024 09:09:47 +0100 Subject: [PATCH 07/12] Breaking: Convert indicator to jsx, add outer container (fixes 230) --- js/PageLevelProgressIndicatorView.js | 51 ++++++++++++------------ less/pageLevelProgressIndicator.less | 1 + templates/pageLevelProgressIndicator.hbs | 14 ------- templates/pageLevelProgressIndicator.jsx | 24 +++++++++++ 4 files changed, 50 insertions(+), 40 deletions(-) delete mode 100644 templates/pageLevelProgressIndicator.hbs create mode 100644 templates/pageLevelProgressIndicator.jsx diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index efc0a3d..ed43776 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -1,4 +1,7 @@ import Adapt from 'core/js/adapt'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { templates } from 'core/js/reactHelpers'; class PageLevelProgressIndicatorView extends Backbone.View { @@ -16,25 +19,15 @@ class PageLevelProgressIndicatorView extends Backbone.View { this.setUpEventListeners(); this.setPercentageComplete(); this.render(); - this.refresh(); } addClasses() { this.$el.addClass([ - 'pagelevelprogress__indicator', + 'pagelevelprogress__indicator-outer', 'is-' + this.type ].join(' ')); } - checkAria() { - if (!this.ariaLabel) { - this.$el.attr('aria-hidden', true); - return; - } - const data = this.getRenderData(); - this.$('.js-indicator-aria-label').html(Handlebars.compile(this.ariaLabel)(data)); - } - setUpEventListeners() { if (this.parent) { this.listenToOnce(this.parent, 'postRemove', this.remove); @@ -47,6 +40,9 @@ class PageLevelProgressIndicatorView extends Backbone.View { setPercentageComplete() { const percentage = this.calculatePercentage(); this.model.set('percentageComplete', percentage); + this.$el.css({ + '--adapt-pagelevelprogress-percentage': percentage + '%' + }); return percentage; } @@ -55,24 +51,15 @@ class PageLevelProgressIndicatorView extends Backbone.View { } render() { + this.checkCompletion(); + this.checkAriaHidden(); const data = this.getRenderData(); - const template = Handlebars.templates[this.constructor.template]; - this.$el.html(template(data)); - } - - getRenderData() { - const data = this.model.toJSON(); - data.ariaLabel = this.ariaLabel; - data.type = this.type; - return data; + const Component = templates.pageLevelProgressIndicator; + ReactDOM.render(, this.el); } refresh() { - this.checkCompletion(); - this.checkAria(); - this.$('.js-indicator-bar').css({ - width: this.calculatePercentage() + '%' - }); + this.render(); } checkCompletion() { @@ -90,8 +77,20 @@ class PageLevelProgressIndicatorView extends Backbone.View { .toggleClass('is-incorrect', isIncorrect); } + checkAriaHidden() { + if (this.ariaLabel) return; + this.$el.attr('aria-hidden', true); + } + + getRenderData() { + const data = this.model.toJSON(); + data.ariaLabel = this.ariaLabel; + data.type = this.type; + return data; + } + } -PageLevelProgressIndicatorView.template = 'pageLevelProgressIndicator'; +PageLevelProgressIndicatorView.template = 'pageLevelProgressIndicator.jsx'; export default PageLevelProgressIndicatorView; diff --git a/less/pageLevelProgressIndicator.less b/less/pageLevelProgressIndicator.less index 6761b3d..51f8938 100644 --- a/less/pageLevelProgressIndicator.less +++ b/less/pageLevelProgressIndicator.less @@ -25,6 +25,7 @@ height: inherit; min-width: 15%; background-color: @black; + width: var(--adapt-pagelevelprogress-percentage); } &__indicator .js-indicator-aria-label { diff --git a/templates/pageLevelProgressIndicator.hbs b/templates/pageLevelProgressIndicator.hbs deleted file mode 100644 index edfa65f..0000000 --- a/templates/pageLevelProgressIndicator.hbs +++ /dev/null @@ -1,14 +0,0 @@ -{{! make the _globals object in course.json available to this template}} -{{import_globals}} - - - - - - {{#if ariaLabel}} - - {{compile ariaLabel}} - - {{/if}} - - diff --git a/templates/pageLevelProgressIndicator.jsx b/templates/pageLevelProgressIndicator.jsx new file mode 100644 index 0000000..d85d76e --- /dev/null +++ b/templates/pageLevelProgressIndicator.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { compile } from 'core/js/reactHelpers'; + +export default function PageLevelProgressIndicator (props) { + const { + ariaLabel + } = props; + + return ( + + + + + + {ariaLabel && + + {compile(ariaLabel)} + + } + + + + ); +}; From 749b0a48522289c4d89c6a371a4c8c99a5ad109e Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 19 Jun 2024 11:39:48 +0100 Subject: [PATCH 08/12] Update templates/pageLevelProgressIndicator.jsx Co-authored-by: joe-allen-89 <85872286+joe-allen-89@users.noreply.github.com> --- templates/pageLevelProgressIndicator.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/pageLevelProgressIndicator.jsx b/templates/pageLevelProgressIndicator.jsx index d85d76e..3701672 100644 --- a/templates/pageLevelProgressIndicator.jsx +++ b/templates/pageLevelProgressIndicator.jsx @@ -14,7 +14,7 @@ export default function PageLevelProgressIndicator (props) { {ariaLabel && - {compile(ariaLabel)} + {compile(ariaLabel, props)} } From 562c2601b80c996811b06c0dbae0e404be3da9a1 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 19 Jun 2024 11:57:39 +0100 Subject: [PATCH 09/12] Ensure percentageComplete is correctly calculated --- js/PageLevelProgressIndicatorView.js | 2 +- js/PageLevelProgressNavigationView.js | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index 7079bc0..4987a57 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -35,7 +35,7 @@ class PageLevelProgressIndicatorView extends Backbone.View { } else { this.listenTo(Adapt, 'remove', this.remove); } - this.listenTo(Adapt.course, 'bubble:change:_isComplete bubble:change:_isVisited', this.refresh); + this.listenTo(Adapt.course, 'bubble:change:_isComplete bubble:change:_isVisited', this.render); } setPercentageComplete() { diff --git a/js/PageLevelProgressNavigationView.js b/js/PageLevelProgressNavigationView.js index 85341cc..a74e048 100644 --- a/js/PageLevelProgressNavigationView.js +++ b/js/PageLevelProgressNavigationView.js @@ -39,6 +39,7 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie this.setUpEventListeners(); this.render(); this.addIndicator(); + this.refreshProgressBar(); this.deferredUpdate(); tooltips.register({ @@ -58,8 +59,13 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie } addIndicator() { + const { + _useCourseProgressInNavigationButton = false + } = Adapt.course.get('_pageLevelProgress') ?? {}; this.indicatorView = new PageLevelProgressIndicatorView({ - model: this.pageModel, + model: _useCourseProgressInNavigationButton + ? Adapt.course + : this.pageModel, calculatePercentage: this._getPageCompletionPercentage.bind(this), ariaLabel: this.model.get('ariaLabel') }); @@ -68,13 +74,12 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie } _getPageCompletionPercentage() { - const courseConfig = Adapt.course.get('_pageLevelProgress'); - - if (courseConfig._useCourseProgressInNavigationButton) { - return completionCalculations.calculatePercentageComplete(Adapt.course); - } - - return completionCalculations.calculatePercentageComplete(this.pageModel, true); + const { + _useCourseProgressInNavigationButton = false + } = Adapt.course.get('_pageLevelProgress') ?? {}; + return _useCourseProgressInNavigationButton + ? completionCalculations.calculatePercentageComplete(Adapt.course) + : completionCalculations.calculatePercentageComplete(this.pageModel, true); } deferredUpdate() { @@ -86,6 +91,7 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie } refreshProgressBar() { + this.model.set('percentageComplete', this._getPageCompletionPercentage()); this.collection = getPageLevelProgressItemsJSON(this.pageModel); this.updateProgressBar(); } From d4f6f4613e0c8ab3cf7bca6cc64e5927d67d8295 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 19 Jun 2024 12:04:42 +0100 Subject: [PATCH 10/12] Ensure tooltip can use percentageComplete --- js/PageLevelProgressNavigationView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/PageLevelProgressNavigationView.js b/js/PageLevelProgressNavigationView.js index a74e048..3b19592 100644 --- a/js/PageLevelProgressNavigationView.js +++ b/js/PageLevelProgressNavigationView.js @@ -46,6 +46,7 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie _id: 'pagelevelprogress', ...Adapt.course.get('_globals')?._extensions?._pageLevelProgress?._navTooltip || {} }); + this.tooltip = tooltips.getTooltip('pagelevelprogress'); } setUpEventListeners() { @@ -92,6 +93,7 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie refreshProgressBar() { this.model.set('percentageComplete', this._getPageCompletionPercentage()); + this.tooltip.set('percentageComplete', this._getPageCompletionPercentage()); this.collection = getPageLevelProgressItemsJSON(this.pageModel); this.updateProgressBar(); } From 6bd9321be47b2f56b5a39078203978a16e555a60 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Wed, 19 Jun 2024 12:05:49 +0100 Subject: [PATCH 11/12] variable --- js/PageLevelProgressNavigationView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/PageLevelProgressNavigationView.js b/js/PageLevelProgressNavigationView.js index 3b19592..9801b76 100644 --- a/js/PageLevelProgressNavigationView.js +++ b/js/PageLevelProgressNavigationView.js @@ -92,8 +92,9 @@ export default class PageLevelProgressNavigationView extends NavigationButtonVie } refreshProgressBar() { - this.model.set('percentageComplete', this._getPageCompletionPercentage()); - this.tooltip.set('percentageComplete', this._getPageCompletionPercentage()); + const percentageComplete = this._getPageCompletionPercentage(); + this.model.set('percentageComplete', percentageComplete); + this.tooltip.set('percentageComplete', percentageComplete); this.collection = getPageLevelProgressItemsJSON(this.pageModel); this.updateProgressBar(); } From 8f64d79243e3a122776df72c26fbc117c1bdae4c Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Mon, 24 Jun 2024 09:07:12 +0100 Subject: [PATCH 12/12] Simplify page/menu completion calculations --- js/PageLevelProgressIndicatorView.js | 7 ++++++- js/adapt-contrib-pageLevelProgress.js | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/js/PageLevelProgressIndicatorView.js b/js/PageLevelProgressIndicatorView.js index 4987a57..9ef37c7 100644 --- a/js/PageLevelProgressIndicatorView.js +++ b/js/PageLevelProgressIndicatorView.js @@ -3,6 +3,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { templates } from 'core/js/reactHelpers'; import ItemsComponentModel from 'core/js/models/itemsComponentModel'; +import completionCalculations from './completionCalculations'; class PageLevelProgressIndicatorView extends Backbone.View { @@ -48,9 +49,13 @@ class PageLevelProgressIndicatorView extends Backbone.View { } calculatePercentage() { - const isPresentationComponentWithItems = (!this.model.isTypeGroup('question') && this.model instanceof ItemsComponentModel); const isComplete = this.model.get('_isComplete'); if (isComplete) return 100; + const isContentObject = this.model.isTypeGroup('contentobject'); + if (isContentObject) { + return completionCalculations.calculatePercentageComplete(this.model); + } + const isPresentationComponentWithItems = (!this.model.isTypeGroup('question') && this.model instanceof ItemsComponentModel); if (isPresentationComponentWithItems) { const children = this.model.getChildren(); const visited = children.filter(child => child.get('_isVisited')); diff --git a/js/adapt-contrib-pageLevelProgress.js b/js/adapt-contrib-pageLevelProgress.js index 73bddd0..24b1203 100644 --- a/js/adapt-contrib-pageLevelProgress.js +++ b/js/adapt-contrib-pageLevelProgress.js @@ -118,15 +118,10 @@ class PageLevelProgress extends Backbone.Controller { parent: view, model: view.model, type: 'menu-item', - calculatePercentage: this._getMenuItemCompletionPercentage.bind(view), ariaLabel: PageLevelProgress.globalsConfig?.pageLevelProgressMenuBar }).$el); } - _getMenuItemCompletionPercentage() { - return completionCalculations.calculatePercentageComplete(this.model); - } - // This should add/update progress on page navigation bar renderNavigationView(pageModel) { // Do not render if _isDefaultNavigationDisabled is set to true