Merge pull request #4049 from crazyserver/MOBILE-4470

Mobile 4470
main
Dani Palou 2024-05-16 12:09:48 +02:00 committed by GitHub
commit 655254abd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 97 additions and 92 deletions

View File

@ -22,6 +22,7 @@ import { AddonModQuizNavigationModalComponent } from './navigation-modal/navigat
import { AddonModQuizPreflightModalComponent } from './preflight-modal/preflight-modal';
import { AddonModQuizAttemptInfoComponent } from './attempt-info/attempt-info';
import { AddonModQuizAttemptStateComponent } from './attempt-state/attempt-state';
import { AddonModQuizQuestionCardComponent } from './question-card/question-card';
@NgModule({
declarations: [
@ -31,13 +32,12 @@ import { AddonModQuizAttemptStateComponent } from './attempt-state/attempt-state
AddonModQuizConnectionErrorComponent,
AddonModQuizNavigationModalComponent,
AddonModQuizPreflightModalComponent,
AddonModQuizQuestionCardComponent,
],
imports: [
CoreSharedModule,
CoreCourseComponentsModule,
],
providers: [
],
exports: [
AddonModQuizAttemptInfoComponent,
AddonModQuizAttemptStateComponent,
@ -45,6 +45,8 @@ import { AddonModQuizAttemptStateComponent } from './attempt-state/attempt-state
AddonModQuizConnectionErrorComponent,
AddonModQuizNavigationModalComponent,
AddonModQuizPreflightModalComponent,
AddonModQuizQuestionCardComponent,
],
})
export class AddonModQuizComponentsModule {}

View File

@ -0,0 +1,19 @@
<ion-card id="addon-mod_quiz-question-{{question.slot}}">
<ion-item-divider>
<ion-label class="ion-text-wrap">
<h2 *ngIf="question.type !== 'description' && question.questionnumber" class="inline">
{{ 'core.question.questionno' | translate:{$a: question.questionnumber} }}
</h2>
<h2 *ngIf="question.type === 'description' || !question.questionnumber" class="inline">
{{ 'core.question.information' | translate }}
</h2>
</ion-label>
<div class="ion-text-wrap ion-margin-start addon-mod_quiz-question-note" slot="end"
*ngIf="question.status || question.readableMark">
<p *ngIf="question.status">{{question.status}}</p>
<p *ngIf="question.readableMark" [innerHTML]="question.readableMark"></p>
</div>
</ion-item-divider>
<ng-content />
</ion-card>

View File

@ -0,0 +1,7 @@
.addon-mod_quiz-question-note p {
margin-top: 2px;
margin-bottom: 2px;
text-align: end;
font-weight: normal;
font-size: var(--mdl-typography-fontSize-md);
}

View File

@ -0,0 +1,30 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input } from '@angular/core';
import { CoreQuestionQuestionForView } from '@features/question/services/question';
/**
* Component that displays a question card.
*/
@Component({
selector: 'addon-mod-quiz-question-card',
templateUrl: 'question-card.html',
styleUrl: 'question-card.scss',
})
export class AddonModQuizQuestionCardComponent {
@Input() question!: CoreQuestionQuestionForView;
}

View File

@ -34,32 +34,14 @@
<!-- Questions -->
<form name="addon-mod_quiz-player-form" *ngIf="questions.length && !quizAborted && !showSummary" #quizForm>
<div *ngFor="let question of questions">
<ion-card id="addon-mod_quiz-question-{{question.slot}}">
<!-- "Header" of the question. -->
<ion-item-divider>
<ion-label class="ion-text-wrap">
<h2 *ngIf="question.type !== 'description' && question.questionnumber" class="inline">
{{ 'core.question.questionno' | translate:{$a: question.questionnumber} }}
</h2>
<h2 *ngIf="question.type === 'description' || !question.questionnumber" class="inline">
{{ 'core.question.information' | translate }}
</h2>
</ion-label>
<div *ngIf="question.status || question.readableMark" slot="end"
class="ion-text-wrap ion-margin-start addon-mod_quiz-question-note">
<p *ngIf="question.status" class="block">{{question.status}}</p>
<p *ngIf="question.readableMark" [innerHTML]="question.readableMark"></p>
</div>
</ion-item-divider>
<!-- Body of the question. -->
<ng-container *ngFor="let question of questions">
<addon-mod-quiz-question-card [question]="question">
<core-question class="ion-text-wrap" [question]="question" [component]="component" [componentId]="cmId"
[attemptId]="attempt!.id" [usageId]="attempt!.uniqueid" [offlineEnabled]="offline" contextLevel="module"
[contextInstanceId]="cmId" [courseId]="courseId" [preferredBehaviour]="quiz!.preferredbehaviour" [review]="false"
(onAbort)="abortQuiz()" (buttonClicked)="behaviourButtonClicked($event)" />
</ion-card>
</div>
</addon-mod-quiz-question-card>
</ng-container>
</form>
<!-- Go to next or previous page. -->

View File

@ -5,14 +5,6 @@ $quiz-timer-warn-color: $red !default;
$quiz-timer-iterations: 15 !default;
:host {
.addon-mod_quiz-question-note p {
font-weight: normal;
font-size: var(--mdl-typography-fontSize-md);
margin-top: 2px;
margin-bottom: 2px;
text-align: end;
}
core-timer {
// Make the timer go red when it's reaching 0.
@for $i from 0 through $quiz-timer-iterations {

View File

@ -18,7 +18,11 @@ import { Subscription } from 'rxjs';
import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreQuestionComponent } from '@features/question/components/question/question';
import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question';
import {
CoreQuestionQuestionForView,
CoreQuestionQuestionParsed,
CoreQuestionsAnswers,
} from '@features/question/services/question';
import { CoreQuestionBehaviourButton, CoreQuestionHelper } from '@features/question/services/question-helper';
import { CoreNavigator } from '@services/navigator';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
@ -73,7 +77,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
quizAborted = false; // Whether the quiz was aborted due to an error.
offline = false; // Whether the quiz is being attempted in offline mode.
navigation: AddonModQuizNavigationQuestion[] = []; // List of questions to navigate them.
questions: QuizQuestion[] = []; // Questions of the current page.
questions: CoreQuestionQuestionForView[] = []; // Questions of the current page.
nextPage = -2; // Next page.
previousPage = -1; // Previous page.
showSummary = false; // Whether the attempt summary should be displayed.
@ -936,13 +940,6 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
}
/**
* Question with some calculated data for the view.
*/
type QuizQuestion = CoreQuestionQuestionParsed & {
readableMark?: string;
};
/**
* Attempt with some calculated data for the view.
*/

View File

@ -29,35 +29,17 @@
</ion-card>
<!-- Questions -->
<div *ngIf="attempt && questions.length">
<ng-container *ngIf="attempt && questions.length">
<!-- Questions. -->
<div *ngFor="let question of questions">
<ion-card id="addon-mod_quiz-question-{{question.slot}}">
<!-- "Header" of the question. -->
<ion-item-divider>
<ion-label class="ion-text-wrap">
<h2 *ngIf="question.type !== 'description' && question.questionnumber">
{{ 'core.question.questionno' | translate:{$a: question.questionnumber} }}
</h2>
<h2 *ngIf="question.type === 'description' || !question.questionnumber">
{{ 'core.question.information' | translate }}
</h2>
</ion-label>
<div class="ion-text-wrap ion-margin-horizontal addon-mod_quiz-question-note" slot="end"
*ngIf="question.status || question.readableMark">
<p *ngIf="question.status">{{question.status}}</p>
<p *ngIf="question.readableMark" [innerHTML]="question.readableMark"></p>
</div>
</ion-item-divider>
<!-- Body of the question. -->
<ng-container *ngFor="let question of questions">
<addon-mod-quiz-question-card [question]="question">
<core-question class="ion-text-wrap" [question]="question" [component]="component" [componentId]="cmId"
[attemptId]="attempt.id" [usageId]="attempt.uniqueid" [offlineEnabled]="false" contextLevel="module"
[contextInstanceId]="cmId" [courseId]="courseId" [review]="true" [preferredBehaviour]="quiz?.preferredbehaviour" />
</ion-card>
</div>
</div>
</addon-mod-quiz-question-card>
</ng-container>
</ng-container>
<div collapsible-footer appearOnBottom *ngIf="loaded && numPages > 1" slot="fixed">
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap">

View File

@ -1,6 +0,0 @@
:host {
.addon-mod_quiz-question-note p {
margin-top: 2px;
margin-bottom: 2px;
}
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { CoreQuestionQuestionParsed } from '@features/question/services/question';
import { CoreQuestionQuestionForView } from '@features/question/services/question';
import { CoreQuestionHelper } from '@features/question/services/question-helper';
import { IonContent } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
@ -43,7 +43,6 @@ import { ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
@Component({
selector: 'page-addon-mod-quiz-review',
templateUrl: 'review.html',
styleUrls: ['review.scss'],
})
export class AddonModQuizReviewPage implements OnInit {
@ -57,11 +56,10 @@ export class AddonModQuizReviewPage implements OnInit {
additionalData?: AddonModQuizWSAdditionalData[]; // Additional data to display for the attempt.
loaded = false; // Whether data has been loaded.
navigation: AddonModQuizNavigationQuestion[] = []; // List of questions to navigate them.
questions: QuizQuestion[] = []; // Questions of the current page.
questions: CoreQuestionQuestionForView[] = []; // Questions of the current page.
nextPage = -2; // Next page.
previousPage = -2; // Previous page.
readableGrade?: string;
readableMark?: string;
timeTaken?: string;
gradeItemMarks: { name: string; grade: string }[] = [];
overTime?: string;
@ -320,13 +318,6 @@ export class AddonModQuizReviewPage implements OnInit {
}
/**
* Question with some calculated data for the view.
*/
type QuizQuestion = CoreQuestionQuestionParsed & {
readableMark?: string;
};
type LogViewOptions = {
page?: number; // Page being viewed (if viewing pages);
showAllDisabled?: boolean; // Whether the showAll option has just been disabled.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -69,7 +69,7 @@
</ion-badge>
<!-- Download progress. -->
<p *ngIf="downloadEnabled && section.isDownloading">
<core-progress-bar [progress]="section.total === 0 ? -1 : section.count / section.total" />
<core-progress-bar [progress]="section.total === 0 ? -1 : (section.count / section.total) * 100" />
</p>
</ion-label>
<div class="storage-buttons" slot="end"
@ -112,7 +112,8 @@
<ion-icon name="fam-cloud-done" *ngIf="module.downloadStatus === statusDownloaded"
[attr.aria-label]="'core.downloaded' | translate" />{{ module.totalSize | coreBytesToSize }}
</ion-badge>
<ion-badge color="light" *ngIf="module.calculatingSize">
<ion-badge color="light" *ngIf="module.calculatingSize ||
(section.isDownloading && module.downloadStatus === statusDownloaded)">
{{ 'core.calculating' | translate }}
</ion-badge>
</ion-label>

View File

@ -10,12 +10,16 @@
ion-card.section {
ion-card-header {
padding: 0;
.item-heading {
font: var(--mdl-typography-heading4-font);
}
}
ion-card-content {
padding: 0;
.core-course-storage-activity ion-label {
h3 {
p.item-heading {
position: relative;
max-height: var(--course-storage-max-activity-height);
overflow: hidden;
@ -35,15 +39,10 @@
}
}
}
.item-heading {
font-weight: bold;
font-size: 1.2rem;
}
}
}
ion-badge {
margin-top: 8px;
ion-icon {
@include margin-horizontal(null, 8px);
}

View File

@ -653,6 +653,13 @@ export type CoreQuestionQuestionParsed = CoreQuestionQuestionWSData & {
parsedSettings?: Record<string, unknown> | null;
};
/**
* Question with some calculated data for the view.
*/
export type CoreQuestionQuestionForView = CoreQuestionQuestionParsed & {
readableMark?: string;
};
/**
* List of answers to a set of questions.
*/

View File

@ -16,7 +16,8 @@ input[type=checkbox] {
}
ion-checkbox {
&.checkbox-disabled::part(label) {
&.md.checkbox-disabled::part(label),
&.ios.checkbox-disabled {
opacity: var(--mdl-input-disabled-opacity);
}
}

View File

@ -57,7 +57,8 @@ input[type=radio],
}
ion-radio {
&.radio-disabled::part(label) {
&.md.radio-disabled::part(label),
&.ios.radio-disabled {
opacity: var(--mdl-input-disabled-opacity);
}
}