Skip to content

Commit

Permalink
Merge pull request #4177 from dpalou/MOBILE-4638
Browse files Browse the repository at this point in the history
MOBILE-4638 question: Update correctness icons to match last LMS changes
  • Loading branch information
crazyserver authored Sep 17, 2024
2 parents 129e335 + bfa9b05 commit 90a356f
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/addons/qtype/match/component/addon-qtype-match.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
{{ row.accessibilityLabel }}
</label>
</div>
<ion-icon *ngIf="row.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success" slot="start"
<ion-icon *ngIf="row.isCorrect === 1" class="core-correct-icon" [name]="correctIcon" color="success" slot="start"
[attr.aria-label]="'core.question.correct' | translate" />
<ion-icon *ngIf="row.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger" slot="start"
<ion-icon *ngIf="row.isCorrect === 0" class="core-correct-icon" [name]="incorrectIcon" color="danger" slot="start"
[attr.aria-label]="'core.question.incorrect' | translate" />
<ion-select-option *ngFor="let option of row.options" [value]="option.value">
{{option.label}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
</div>
</div>
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" [name]="correctIcon" color="success"
[attr.aria-label]="'core.question.correct' | translate" />
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" [name]="incorrectIcon" color="danger"
[attr.aria-label]="'core.question.incorrect' | translate" />
</ion-checkbox>
<div *ngIf="option.feedback" class="specificfeedback">
Expand All @@ -53,9 +53,9 @@
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
</div>
</div>
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" [name]="correctIcon" color="success"
[attr.aria-label]="'core.question.correct' | translate" />
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" [name]="incorrectIcon" color="danger"
[attr.aria-label]="'core.question.incorrect' | translate" />
</ion-radio>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@if (item.correctClass === 'correct') {
<ion-icon [name]="correctIcon" slot="start" [ariaLabel]="'core.question.correct' | translate" color="success" />
} @else if (item.correctClass === 'incorrect') {
<ion-icon name="fas-xmark" slot="start" [ariaLabel]="'core.question.incorrect' | translate" color="danger" />
<ion-icon [name]="incorrectIcon" slot="start" [ariaLabel]="'core.question.incorrect' | translate" color="danger" />
} @else if (item.correctClass.startsWith('partial')) {
<ion-icon [name]="partialCorrectIcon" slot="start" [ariaLabel]="'core.question.partiallycorrect' | translate"
color="warning" />
Expand Down
9 changes: 2 additions & 7 deletions src/addons/qtype/ordering/component/ordering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ export class AddonQtypeOrderingComponent extends CoreQuestionBaseComponent<Addon
value: '',
};

correctIcon = '';
partialCorrectIcon = '';

constructor(elementRef: ElementRef) {
super('AddonQtypeOrderingComponent', elementRef);
}
Expand All @@ -59,9 +56,6 @@ export class AddonQtypeOrderingComponent extends CoreQuestionBaseComponent<Addon
return;
}

this.correctIcon = CoreQuestionHelper.getCorrectIcon();
this.partialCorrectIcon = CoreQuestionHelper.getPartiallyCorrectIcon();

// Replace Moodle's feedback classes with our own.
CoreQuestionHelper.replaceFeedbackClasses(questionElement);

Expand All @@ -81,7 +75,8 @@ export class AddonQtypeOrderingComponent extends CoreQuestionBaseComponent<Addon
// Remove correctness icons from the content.
const itemContentEl = element.querySelector<HTMLElement>('[data-itemcontent]');
itemContentEl?.querySelector(
'.icon.fa-check, .icon.fa-remove, .icon.fa-check-square, .icon.fa-check-double, .icon.fa-xmark',
'.icon.fa-check, .icon.fa-remove, .icon.fa-check-square, .icon.fa-circle-check, .icon.fa-xmark, ' +
'.icon.fa-circle-xmark, .icon.fa-square-check, .icon.circle-half-stroke',
)?.remove();

return {
Expand Down
14 changes: 11 additions & 3 deletions src/core/features/question/classes/base-question-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export class CoreQuestionBaseComponent<T extends AddonModQuizQuestion = AddonMod
@Output() buttonClicked = new EventEmitter<CoreQuestionBehaviourButton>(); // Will emit when a behaviour button is clicked.
@Output() onAbort = new EventEmitter<void>(); // Should emit an event if the question should be aborted.

correctIcon = '';
incorrectIcon = '';
partialCorrectIcon = '';

protected logger: CoreLogger;
protected hostElement: HTMLElement;

Expand All @@ -60,6 +64,10 @@ export class CoreQuestionBaseComponent<T extends AddonModQuizQuestion = AddonMod
* @inheritdoc
*/
ngOnInit(): void {
this.correctIcon = CoreQuestionHelper.getCorrectIcon().fullName;
this.incorrectIcon = CoreQuestionHelper.getIncorrectIcon().fullName;
this.partialCorrectIcon = CoreQuestionHelper.getPartiallyCorrectIcon().fullName;

if (!this.question) {
this.logger.warn('Aborting because of no question received.');

Expand Down Expand Up @@ -492,17 +500,17 @@ export class CoreQuestionBaseComponent<T extends AddonModQuizQuestion = AddonMod
// Check if question is marked as correct.
if (input.classList.contains('incorrect')) {
question.input.correctClass = 'core-question-incorrect';
question.input.correctIcon = 'fas-xmark';
question.input.correctIcon = this.incorrectIcon;
question.input.correctIconColor = CoreIonicColorNames.DANGER;
question.input.correctIconLabel = 'core.question.incorrect';
} else if (input.classList.contains('correct')) {
question.input.correctClass = 'core-question-correct';
question.input.correctIcon = CoreQuestionHelper.getCorrectIcon();
question.input.correctIcon = this.correctIcon;
question.input.correctIconColor = CoreIonicColorNames.SUCCESS;
question.input.correctIconLabel = 'core.question.correct';
} else if (input.classList.contains('partiallycorrect')) {
question.input.correctClass = 'core-question-partiallycorrect';
question.input.correctIcon = CoreQuestionHelper.getPartiallyCorrectIcon();
question.input.correctIcon = this.partialCorrectIcon;
question.input.correctIconColor = CoreIonicColorNames.WARNING;
question.input.correctIconLabel = 'core.question.partiallycorrect';
} else {
Expand Down
110 changes: 81 additions & 29 deletions src/core/features/question/services/question-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,30 +799,71 @@ export class CoreQuestionHelperProvider {
* Returns correct icon based on the LMS version.
* In LMS 4.4 and older, fa-check means correct. In 4.5+, fa-check means partially correct.
*
* @param withPrefix Whether to include the prefix in the icon name.
* @returns Icon name.
* @returns Icon data.
*/
getCorrectIcon(withPrefix = true): string {
const icon = CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.5')
? 'check-double'
: 'check';
getCorrectIcon(): IconData {
if (CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.5')) {
return {
name: 'circle-check',
prefix: 'far',
library: 'regular',
fullName: 'far-circle-check',
};
} else {
return {
name: 'check',
prefix: 'fas',
library: 'solid',
fullName: 'fas-check',
};
}
}

return withPrefix ? `fas-${icon}` : icon;
/**
* Returns incorrect correct icon based on the LMS version.
*
* @returns Icon data.
*/
getIncorrectIcon(): IconData {
if (CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.5')) {
return {
name: 'circle-xmark',
prefix: 'far',
library: 'regular',
fullName: 'far-circle-xmark',
};
} else {
return {
name: 'xmark',
prefix: 'fas',
library: 'solid',
fullName: 'fas-xmark',
};
}
}

/**
* Returns partially correct icon based on the LMS version.
* In LMS 4.4 and older, fa-check means correct. In 4.5+, fa-check means partially correct.
*
* @param withPrefix Whether to include the prefix in the icon name.
* @returns Icon name.
* @returns Icon data.
*/
getPartiallyCorrectIcon(withPrefix = true): string {
const icon = CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.5')
? 'check'
: 'square-check';

return withPrefix ? `fas-${icon}` : icon;
getPartiallyCorrectIcon(): IconData {
if (CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.5')) {
return {
name: 'circle-half-stroke',
prefix: 'fas',
library: 'solid',
fullName: 'fas-circle-half-stroke',
};
} else {
return {
name: 'square-check',
prefix: 'fas',
library: 'solid',
fullName: 'fas-square-check',
};
}
}

/**
Expand All @@ -833,41 +874,42 @@ export class CoreQuestionHelperProvider {
treatCorrectnessIcons(element: HTMLElement): void {
const icons = <HTMLElement[]> Array.from(element.querySelectorAll('img.icon, img.questioncorrectnessicon, i.icon'));
icons.forEach((icon) => {
let iconName: string | undefined;
let iconData: IconData | undefined;
let color: string | undefined;

const correctIcon = this.getCorrectIcon(false);
const partiallyCorrectIcon = this.getCorrectIcon(false);
const correctIcon = this.getCorrectIcon();
const incorrectIcon = this.getIncorrectIcon();
const partiallyCorrectIcon = this.getPartiallyCorrectIcon();
if ('src' in icon) {
if ((icon as HTMLImageElement).src.indexOf('correct') >= 0) {
iconName = correctIcon;
iconData = correctIcon;
color = CoreIonicColorNames.SUCCESS;
} else if ((icon as HTMLImageElement).src.indexOf('incorrect') >= 0 ) {
iconName = 'xmark';
iconData = incorrectIcon;
color = CoreIonicColorNames.DANGER;
}
} else {
if (icon.classList.contains(`fa-${partiallyCorrectIcon}`)) {
iconName = partiallyCorrectIcon;
if (icon.classList.contains(`fa-${partiallyCorrectIcon.name}`)) {
iconData = partiallyCorrectIcon;
color = CoreIonicColorNames.WARNING;
} else if (icon.classList.contains(`fa-${correctIcon}`)) {
iconName = correctIcon;
} else if (icon.classList.contains(`fa-${correctIcon.name}`)) {
iconData = correctIcon;
color = CoreIonicColorNames.SUCCESS;
} else if (icon.classList.contains('fa-xmark') || icon.classList.contains('fa-remove')) {
iconName = 'xmark';
} else if (icon.classList.contains(`fa-${incorrectIcon.name}`) || icon.classList.contains('fa-remove')) {
iconData = incorrectIcon;
color = CoreIonicColorNames.DANGER;
}
}

if (!iconName) {
if (!iconData) {
return;
}

// Replace the icon with the font version.
const newIcon: HTMLIonIconElement = document.createElement('ion-icon');

newIcon.setAttribute('name', `fas-${iconName}`);
newIcon.setAttribute('src', CoreIcons.getIconSrc('font-awesome', 'solid', iconName));
newIcon.setAttribute('name', iconData.fullName);
newIcon.setAttribute('src', CoreIcons.getIconSrc('font-awesome', iconData.library, iconData.name));
newIcon.className = `core-correct-icon ion-color ion-color-${color} questioncorrectnessicon`;
newIcon.title = icon.title;
newIcon.setAttribute('aria-label', icon.title);
Expand Down Expand Up @@ -997,3 +1039,13 @@ export type CoreQuestionBehaviourButton = {
export type CoreQuestionBehaviourCertaintyOption = CoreQuestionBehaviourButton & {
text: string;
};

/**
* Data about a font-awesome icon.
*/
type IconData = {
name: string;
prefix: string;
library: string;
fullName: string;
};

0 comments on commit 90a356f

Please sign in to comment.