Skip to content

Commit b48a27e

Browse files
committed
MOBILE-3413 h5pactivity: Implement viewing attempt results
1 parent 22caea4 commit b48a27e

File tree

11 files changed

+621
-16
lines changed

11 files changed

+621
-16
lines changed

scripts/langindex.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,12 +659,39 @@
659659
"addon.mod_glossary.noentriesfound": "local_moodlemobileapp",
660660
"addon.mod_glossary.searchquery": "local_moodlemobileapp",
661661
"addon.mod_glossary.tagarea_glossary_entries": "glossary",
662+
"addon.mod_h5pactivity.all_attempts": "h5pactivity",
663+
"addon.mod_h5pactivity.answer_checked": "h5pactivity",
664+
"addon.mod_h5pactivity.answer_correct": "h5pactivity",
665+
"addon.mod_h5pactivity.answer_fail": "h5pactivity",
666+
"addon.mod_h5pactivity.answer_incorrect": "h5pactivity",
667+
"addon.mod_h5pactivity.answer_pass": "h5pactivity",
668+
"addon.mod_h5pactivity.attempt": "h5pactivity",
669+
"addon.mod_h5pactivity.attempt_completion_no": "h5pactivity",
670+
"addon.mod_h5pactivity.attempt_completion_yes": "h5pactivity",
671+
"addon.mod_h5pactivity.attempt_success_fail": "h5pactivity",
672+
"addon.mod_h5pactivity.attempt_success_pass": "h5pactivity",
673+
"addon.mod_h5pactivity.attempt_success_unknown": "h5pactivity",
674+
"addon.mod_h5pactivity.attempts_none": "h5pactivity",
675+
"addon.mod_h5pactivity.completion": "h5pactivity",
662676
"addon.mod_h5pactivity.downloadh5pfile": "local_moodlemobileapp",
677+
"addon.mod_h5pactivity.duration": "h5pactivity",
663678
"addon.mod_h5pactivity.errorgetactivity": "local_moodlemobileapp",
664679
"addon.mod_h5pactivity.filestatenotdownloaded": "local_moodlemobileapp",
665680
"addon.mod_h5pactivity.filestateoutdated": "local_moodlemobileapp",
681+
"addon.mod_h5pactivity.maxscore": "h5pactivity",
666682
"addon.mod_h5pactivity.modulenameplural": "h5pactivity",
683+
"addon.mod_h5pactivity.myattempts": "h5pactivity",
684+
"addon.mod_h5pactivity.no_compatible_track": "h5pactivity",
667685
"addon.mod_h5pactivity.offlinedisabledwarning": "local_moodlemobileapp",
686+
"addon.mod_h5pactivity.outcome": "h5pactivity",
687+
"addon.mod_h5pactivity.result_fill-in": "h5pactivity",
688+
"addon.mod_h5pactivity.result_other": "h5pactivity",
689+
"addon.mod_h5pactivity.review_my_attempts": "h5pactivity",
690+
"addon.mod_h5pactivity.score": "h5pactivity",
691+
"addon.mod_h5pactivity.score_out_of": "h5pactivity",
692+
"addon.mod_h5pactivity.startdate": "h5pactivity",
693+
"addon.mod_h5pactivity.totalscore": "h5pactivity",
694+
"addon.mod_h5pactivity.viewattempt": "local_moodlemobileapp",
668695
"addon.mod_imscp.deploymenterror": "imscp",
669696
"addon.mod_imscp.modulenameplural": "imscp",
670697
"addon.mod_imscp.showmoduledescription": "local_moodlemobileapp",

src/addon/mod/h5pactivity/lang/en.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"all_attempts": "All user attempts",
3+
"answer_checked": "Answer checked",
4+
"answer_correct": "Your answer is correct",
5+
"answer_fail": "Incorrect answer",
6+
"answer_incorrect": "Your answer is incorrect",
7+
"answer_pass": "Correct answer",
8+
"attempt": "Attempt",
39
"attempt_completion_no": "This attempt is not marked as completed",
410
"attempt_completion_yes": "This attempt is completed",
511
"attempts_none": "This user has no attempts to display.",
@@ -15,8 +21,15 @@
1521
"maxscore": "Max score",
1622
"modulenameplural": "H5P",
1723
"myattempts": "My attempts",
24+
"no_compatible_track": "This interaction ({{$a}}) does not provide tracking information or the tracking provided is not compatible with the current activity version.",
1825
"offlinedisabledwarning": "You will need to be online to view the H5P package.",
26+
"outcome": "Outcome",
27+
"result_fill-in": "Fill-in text",
28+
"result_other": "Unkown interaction type",
1929
"review_my_attempts": "View my attempts",
2030
"score": "Score",
31+
"score_out_of": "{{$a.rawscore}} out of {{$a.maxscore}}",
32+
"startdate": "Start date",
33+
"totalscore": "Total score",
2134
"viewattempt": "View attempt {{$a}}"
2235
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<ion-header>
2+
<ion-navbar core-back-button>
3+
<ion-title><core-format-text *ngIf="h5pActivity" [text]="h5pActivity.name" contextLevel="module" [contextInstanceId]="h5pActivity.coursemodule" [courseId]="courseId"></core-format-text></ion-title>
4+
</ion-navbar>
5+
</ion-header>
6+
<ion-content>
7+
<ion-refresher [enabled]="loaded" (ionRefresh)="doRefresh($event)">
8+
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
9+
</ion-refresher>
10+
<core-loading [hideUntil]="loaded">
11+
<ng-container *ngIf="attempt">
12+
<!-- Attempt number and user that did the attempt. -->
13+
<a ion-item text-wrap *ngIf="user" core-user-link [userId]="user.id" [courseId]="courseId" [title]="user.fullname">
14+
<ion-avatar core-user-avatar [user]="user" item-start></ion-avatar>
15+
<h2>{{ 'addon.mod_h5pactivity.attempt' | translate }} #{{attempt.attempt}}: {{user.fullname}}</h2>
16+
</a>
17+
<!-- Attempt number (if user not known). -->
18+
<ion-item text-wrap *ngIf="!user">
19+
<h2>{{ 'addon.mod_h5pactivity.attempt' | translate }} #{{attempt.attempt}}</h2>
20+
</ion-item>
21+
22+
<!-- Attempt summary. -->
23+
<ion-card class="addon-mod_h5pactivity-attempt-result-summary">
24+
<ion-list>
25+
<ion-item text-wrap no-lines>
26+
<h2>{{ 'addon.mod_h5pactivity.startdate' | translate }}</h2>
27+
<p>{{ attempt.timecreated | coreFormatDate:'strftimedatetime' }}</p>
28+
</ion-item>
29+
<ion-item text-wrap no-lines>
30+
<h2>{{ 'addon.mod_h5pactivity.completion' | translate }}</h2>
31+
<p *ngIf="attempt.completion">
32+
<img src="assets/img/completion/completion-auto-y.svg" role="presentation" alt="">
33+
{{ 'addon.mod_h5pactivity.attempt_completion_yes' | translate }}
34+
</p>
35+
<p *ngIf="!attempt.completion">
36+
<img src="assets/img/completion/completion-auto-n.svg" role="presentation" alt="">
37+
{{ 'addon.mod_h5pactivity.attempt_completion_no' | translate }}
38+
</p>
39+
</ion-item>
40+
<ion-item text-wrap no-lines>
41+
<h2>{{ 'addon.mod_h5pactivity.duration' | translate }}</h2>
42+
<p>{{ attempt.durationReadable }}</p>
43+
</ion-item>
44+
<ion-item text-wrap no-lines>
45+
<h2>{{ 'addon.mod_h5pactivity.outcome' | translate }}</h2>
46+
<p *ngIf="attempt.success !== null && attempt.success" >
47+
<core-icon name="fa-check-circle"></core-icon>
48+
{{ 'addon.mod_h5pactivity.attempt_success_pass' | translate }}
49+
</p>
50+
<p *ngIf="attempt.success !== null && !attempt.success" >
51+
<core-icon name="fa-circle-o"></core-icon>
52+
{{ 'addon.mod_h5pactivity.attempt_success_fail' | translate }}
53+
</p>
54+
<p *ngIf="attempt.success === null" >
55+
{{ 'addon.mod_h5pactivity.attempt_success_unknown' | translate }}
56+
</p>
57+
</ion-item>
58+
<ion-item *ngIf="attempt.maxscore" text-wrap no-lines>
59+
<h2>{{ 'addon.mod_h5pactivity.totalscore' | translate }}</h2>
60+
<p>{{ 'addon.mod_h5pactivity.score_out_of' | translate:{$a: attempt} }}</p>
61+
</ion-item>
62+
</ion-list>
63+
</ion-card>
64+
65+
<!-- Results. -->
66+
<ng-container *ngIf="attempt.results">
67+
<ion-card *ngFor="let result of attempt.results">
68+
<ion-card-header text-wrap>
69+
<core-format-text [text]="result.description" [component]="component" [componentId]="h5pActivity.cmid" contextLevel="module" [contextInstanceId]="h5pActivity.cmid" [courseId]="courseId"></core-format-text>
70+
</ion-card-header>
71+
<ion-item *ngIf="result.content" text-wrap>
72+
<core-format-text [text]="result.content" [component]="component" [componentId]="h5pActivity.cmid" contextLevel="module" [contextInstanceId]="h5pActivity.cmid" [courseId]="courseId"></core-format-text>
73+
</ion-item>
74+
75+
<!-- Options. -->
76+
<ng-container *ngIf="result.options && result.options.length">
77+
<ion-item text-wrap class="addon-mod_h5pactivity-result-table-header">
78+
<ion-row align-items-center>
79+
<ion-col text-center>{{ result.optionslabel }}</ion-col>
80+
<ion-col text-center>{{ result.correctlabel }}</ion-col>
81+
<ion-col text-center>{{ result.answerlabel }}</ion-col>
82+
</ion-row>
83+
</ion-item>
84+
<ion-item text-wrap *ngFor="let option of result.options" class="addon-mod_h5pactivity-result-table-row">
85+
<ion-row align-items-center>
86+
<ion-col text-center>
87+
<core-format-text [text]="option.description" [component]="component" [componentId]="h5pActivity.cmid" contextLevel="module" [contextInstanceId]="h5pActivity.cmid" [courseId]="courseId"></core-format-text>
88+
</ion-col>
89+
<ion-col text-center>
90+
<ng-container *ngIf="option.correctanswer">
91+
<ng-container *ngTemplateOutlet="answerTemplate; context: {answer: option.correctanswer}"></ng-container>
92+
</ng-container>
93+
</ion-col>
94+
<ion-col text-center>
95+
<ng-container *ngIf="option.useranswer">
96+
<ng-container *ngTemplateOutlet="answerTemplate; context: {answer: option.useranswer}"></ng-container>
97+
</ng-container>
98+
</ion-col>
99+
</ion-row>
100+
</ion-item>
101+
102+
<!-- Result score. -->
103+
<ion-item *ngIf="result.maxscore" text-wrap text-end class="addon-mod_h5pactivity-result-score">
104+
<p><strong>{{ 'addon.mod_h5pactivity.score' | translate }}: {{ 'addon.mod_h5pactivity.score_out_of' | translate:{$a: result} }}</strong></p>
105+
</ion-item>
106+
</ng-container>
107+
108+
<!-- Result doesn't support tracking. -->
109+
<ion-item text-wrap class="core-warning-item" *ngIf="!result.track">
110+
<ion-icon item-start name="warning" color="warning"></ion-icon> {{ 'addon.mod_h5pactivity.no_compatible_track' | translate:{$a: result.interactiontype} }}
111+
</ion-item>
112+
</ion-card>
113+
</ng-container>
114+
</ng-container>
115+
</core-loading>
116+
</ion-content>
117+
118+
<!-- Template to render an answer. -->
119+
<ng-template #answerTemplate let-answer="answer">
120+
<p *ngIf="answer.correct">
121+
<core-icon name="fa-check" [label]="'addon.mod_h5pactivity.answer_correct' | translate" color="success"></core-icon>
122+
{{ answer.answer }}
123+
</p>
124+
<p *ngIf="answer.incorrect">
125+
<core-icon name="fa-remove" [label]="'addon.mod_h5pactivity.answer_incorrect' | translate" color="danger"></core-icon>
126+
{{ answer.answer }}
127+
</p>
128+
<p *ngIf="answer.text">
129+
{{ answer.answer }}
130+
</p>
131+
<p *ngIf="answer.checked">
132+
<core-icon name="fa-check-circle" [label]="'addon.mod_h5pactivity.answer_checked' | translate"></core-icon>
133+
</p>
134+
<p *ngIf="answer.pass">
135+
<core-icon name="fa-check" [label]="'addon.mod_h5pactivity.answer_pass' | translate" color="success"></core-icon>
136+
</p>
137+
<p *ngIf="answer.fail">
138+
<core-icon name="fa-remove" [label]="'addon.mod_h5pactivity.answer_fail' | translate" color="danger"></core-icon>
139+
</p>
140+
</ng-template>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// (C) Copyright 2015 Moodle Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { NgModule } from '@angular/core';
16+
import { IonicPageModule } from 'ionic-angular';
17+
import { TranslateModule } from '@ngx-translate/core';
18+
import { CoreComponentsModule } from '@components/components.module';
19+
import { CoreDirectivesModule } from '@directives/directives.module';
20+
import { CorePipesModule } from '@pipes/pipes.module';
21+
import { AddonModH5PActivityAttemptResultsPage } from './attempt-results';
22+
23+
@NgModule({
24+
declarations: [
25+
AddonModH5PActivityAttemptResultsPage,
26+
],
27+
imports: [
28+
CoreComponentsModule,
29+
CoreDirectivesModule,
30+
CorePipesModule,
31+
IonicPageModule.forChild(AddonModH5PActivityAttemptResultsPage),
32+
TranslateModule.forChild(),
33+
],
34+
})
35+
export class AddonModH5PActivityAttemptResultsPageModule {}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
ion-app.app-root page-addon-mod-h5pactivity-attempt-results {
2+
3+
.addon-mod_h5pactivity-attempt-result-summary {
4+
img {
5+
width: 16px;
6+
height: 16px;
7+
display: inline;
8+
@include margin-horizontal(0, 4px);
9+
}
10+
11+
.icon {
12+
font-size: 1.4em;
13+
}
14+
}
15+
16+
.addon-mod_h5pactivity-result-table-header .item-inner {
17+
font-size: 0.9em;
18+
font-weight: bold;
19+
20+
.col[text-center] {
21+
@include padding-horizontal(0);
22+
}
23+
}
24+
25+
.addon-mod_h5pactivity-result-table-header, .addon-mod_h5pactivity-result-table-row {
26+
27+
.item-inner ion-label {
28+
@include margin(null, 0, null, null);
29+
}
30+
31+
.item {
32+
@include padding(null, null, null, 0);
33+
}
34+
35+
.label {
36+
margin-top: 0;
37+
margin-bottom: 0;
38+
}
39+
40+
.icon {
41+
font-size: 1.2em;
42+
}
43+
}
44+
45+
.addon-mod_h5pactivity-result-table-row.item:nth-child(even) {
46+
background-color: $gray-lighter;
47+
@include darkmode() {
48+
background-color: $core-dark-item-divider-bg-color;
49+
}
50+
}
51+
52+
.addon-mod_h5pactivity-result-score {
53+
border-top: 1px solid black;
54+
}
55+
}

0 commit comments

Comments
 (0)