MOBILE-3109 choice: Add return types to choice
parent
49deffa9dd
commit
3647b7bfa0
|
@ -19,13 +19,13 @@
|
|||
<!-- Activity availability messages -->
|
||||
<ion-card class="core-info-card" icon-start *ngIf="choiceNotOpenYet">
|
||||
<ion-icon name="information-circle"></ion-icon>
|
||||
<p *ngIf="options && options.length">{{ 'addon.mod_choice.previewonly' | translate:{$a: choice.openTimeReadable} }}</p>
|
||||
<p *ngIf="!options || !options.length">{{ 'addon.mod_choice.notopenyet' | translate:{$a: choice.openTimeReadable} }}</p>
|
||||
<p *ngIf="options && options.length">{{ 'addon.mod_choice.previewonly' | translate:{$a: openTimeReadable} }}</p>
|
||||
<p *ngIf="!options || !options.length">{{ 'addon.mod_choice.notopenyet' | translate:{$a: openTimeReadable} }}</p>
|
||||
</ion-card>
|
||||
<ion-card class="core-info-card" icon-start *ngIf="choiceClosed">
|
||||
<ion-icon name="information-circle"></ion-icon>
|
||||
<p *ngIf="options && options.length">{{ 'addon.mod_choice.yourselection' | translate }} <core-format-text [text]="options[0].text"></core-format-text></p>
|
||||
<p>{{ 'addon.mod_choice.expired' | translate:{$a: choice.closeTimeReadable} }}</p>
|
||||
<p>{{ 'addon.mod_choice.expired' | translate:{$a: closeTimeReadable} }}</p>
|
||||
</ion-card>
|
||||
|
||||
<!-- Choice done in offline but not synchronized -->
|
||||
|
@ -80,7 +80,7 @@
|
|||
<ion-item-group *ngFor="let result of results">
|
||||
<ion-item-divider text-wrap>
|
||||
<h2><core-format-text [text]="result.text"></core-format-text></h2>
|
||||
<p>{{ 'addon.mod_choice.numberofuser' | translate }}: {{ result.numberofuser }} ({{ 'core.percentagenumber' | translate: {$a: result.percentageamount} }})</p>
|
||||
<p>{{ 'addon.mod_choice.numberofuser' | translate }}: {{ result.numberofuser }} ({{ 'core.percentagenumber' | translate: {$a: result.percentageamountfixed} }})</p>
|
||||
</ion-item-divider>
|
||||
<a ion-item *ngFor="let user of result.userresponses" core-user-link [courseId]="courseid" [userId]="user.userid" [title]="user.fullname" text-wrap>
|
||||
<ion-avatar core-user-avatar [user]="user" item-start [courseId]="courseid"></ion-avatar>
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, Optional, Injector } from '@angular/core';
|
|||
import { Content } from 'ionic-angular';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
||||
import { AddonModChoiceProvider } from '../../providers/choice';
|
||||
import { AddonModChoiceProvider, AddonModChoiceChoice, AddonModChoiceOption, AddonModChoiceResult } from '../../providers/choice';
|
||||
import { AddonModChoiceOfflineProvider } from '../../providers/offline';
|
||||
import { AddonModChoiceSyncProvider } from '../../providers/sync';
|
||||
|
||||
|
@ -31,9 +31,9 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
component = AddonModChoiceProvider.COMPONENT;
|
||||
moduleName = 'choice';
|
||||
|
||||
choice: any;
|
||||
options = [];
|
||||
selectedOption: any;
|
||||
choice: AddonModChoiceChoice;
|
||||
options: AddonModChoiceOption[] = [];
|
||||
selectedOption: {id: number};
|
||||
choiceNotOpenYet = false;
|
||||
choiceClosed = false;
|
||||
canEdit = false;
|
||||
|
@ -43,6 +43,8 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
labels = [];
|
||||
results = [];
|
||||
publishInfo: string; // Message explaining the user what will happen with his choices.
|
||||
openTimeReadable: string;
|
||||
closeTimeReadable: string;
|
||||
|
||||
protected userId: number;
|
||||
protected syncEventName = AddonModChoiceSyncProvider.AUTO_SYNCED;
|
||||
|
@ -122,12 +124,12 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
|
||||
return this.choiceProvider.getChoice(this.courseId, this.module.id).then((choice) => {
|
||||
this.choice = choice;
|
||||
this.choice.timeopen = parseInt(choice.timeopen) * 1000;
|
||||
this.choice.openTimeReadable = this.timeUtils.userDate(choice.timeopen);
|
||||
this.choice.timeclose = parseInt(choice.timeclose) * 1000;
|
||||
this.choice.closeTimeReadable = this.timeUtils.userDate(choice.timeclose);
|
||||
this.choice.timeopen = choice.timeopen * 1000;
|
||||
this.choice.timeclose = choice.timeclose * 1000;
|
||||
this.openTimeReadable = this.timeUtils.userDate(choice.timeopen);
|
||||
this.closeTimeReadable = this.timeUtils.userDate(choice.timeclose);
|
||||
|
||||
this.description = choice.intro || choice.description;
|
||||
this.description = choice.intro;
|
||||
this.choiceNotOpenYet = choice.timeopen && choice.timeopen > this.now;
|
||||
this.choiceClosed = choice.timeclose && choice.timeclose <= this.now;
|
||||
|
||||
|
@ -175,7 +177,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
|
||||
if (hasOffline) {
|
||||
promise = this.choiceOffline.getResponse(this.choice.id).then((response) => {
|
||||
const optionsKeys = {};
|
||||
const optionsKeys: {[id: number]: AddonModChoiceOption} = {};
|
||||
options.forEach((option) => {
|
||||
optionsKeys[option.id] = option;
|
||||
});
|
||||
|
@ -223,7 +225,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
promise = Promise.resolve(options);
|
||||
}
|
||||
|
||||
promise.then((options) => {
|
||||
promise.then((options: AddonModChoiceOption[]) => {
|
||||
const isOpen = this.isChoiceOpen();
|
||||
|
||||
let hasAnswered = false;
|
||||
|
@ -291,11 +293,11 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
let hasVotes = false;
|
||||
this.data = [];
|
||||
this.labels = [];
|
||||
results.forEach((result) => {
|
||||
results.forEach((result: AddonModChoiceResultFormatted) => {
|
||||
if (result.numberofuser > 0) {
|
||||
hasVotes = true;
|
||||
}
|
||||
result.percentageamount = parseFloat(result.percentageamount).toFixed(1);
|
||||
result.percentageamountfixed = result.percentageamount.toFixed(1);
|
||||
this.data.push(result.numberofuser);
|
||||
this.labels.push(result.text);
|
||||
});
|
||||
|
@ -429,3 +431,10 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
return result.updated;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choice result with some calculated data.
|
||||
*/
|
||||
export type AddonModChoiceResultFormatted = AddonModChoiceResult & {
|
||||
percentageamountfixed: string; // Percentage of users answers with fixed decimals.
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
|
|||
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
||||
import { AddonModChoiceOfflineProvider } from './offline';
|
||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||
import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service that provides some features for choices.
|
||||
|
@ -118,7 +119,9 @@ export class AddonModChoiceProvider {
|
|||
responses: responses
|
||||
};
|
||||
|
||||
return site.write('mod_choice_delete_choice_responses', params).then((response) => {
|
||||
return site.write('mod_choice_delete_choice_responses', params)
|
||||
.then((response: AddonModChoiceDeleteChoiceResponsesResult) => {
|
||||
|
||||
// Other errors ocurring.
|
||||
if (!response || response.status === false) {
|
||||
return Promise.reject(this.utils.createFakeWSError(''));
|
||||
|
@ -179,7 +182,7 @@ export class AddonModChoiceProvider {
|
|||
* @return Promise resolved when the choice is retrieved.
|
||||
*/
|
||||
protected getChoiceByDataKey(siteId: string, courseId: number, key: string, value: any, forceCache?: boolean,
|
||||
ignoreCache?: boolean): Promise<any> {
|
||||
ignoreCache?: boolean): Promise<AddonModChoiceChoice> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
|
@ -198,7 +201,9 @@ export class AddonModChoiceProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('mod_choice_get_choices_by_courses', params, preSets).then((response) => {
|
||||
return site.read('mod_choice_get_choices_by_courses', params, preSets)
|
||||
.then((response: AddonModChoiceGetChoicesByCoursesResult): any => {
|
||||
|
||||
if (response && response.choices) {
|
||||
const currentChoice = response.choices.find((choice) => choice[key] == value);
|
||||
if (currentChoice) {
|
||||
|
@ -221,7 +226,8 @@ export class AddonModChoiceProvider {
|
|||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||
* @return Promise resolved when the choice is retrieved.
|
||||
*/
|
||||
getChoice(courseId: number, cmId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
|
||||
getChoice(courseId: number, cmId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean)
|
||||
: Promise<AddonModChoiceChoice> {
|
||||
return this.getChoiceByDataKey(siteId, courseId, 'coursemodule', cmId, forceCache, ignoreCache);
|
||||
}
|
||||
|
||||
|
@ -235,7 +241,8 @@ export class AddonModChoiceProvider {
|
|||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||
* @return Promise resolved when the choice is retrieved.
|
||||
*/
|
||||
getChoiceById(courseId: number, choiceId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
|
||||
getChoiceById(courseId: number, choiceId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean)
|
||||
: Promise<AddonModChoiceChoice> {
|
||||
return this.getChoiceByDataKey(siteId, courseId, 'id', choiceId, forceCache, ignoreCache);
|
||||
}
|
||||
|
||||
|
@ -247,7 +254,7 @@ export class AddonModChoiceProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with choice options.
|
||||
*/
|
||||
getOptions(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
|
||||
getOptions(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<AddonModChoiceOption[]> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
choiceid: choiceId
|
||||
|
@ -262,7 +269,9 @@ export class AddonModChoiceProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('mod_choice_get_choice_options', params, preSets).then((response) => {
|
||||
return site.read('mod_choice_get_choice_options', params, preSets)
|
||||
.then((response: AddonModChoiceGetChoiceOptionsResult): any => {
|
||||
|
||||
if (response.options) {
|
||||
return response.options;
|
||||
}
|
||||
|
@ -280,7 +289,7 @@ export class AddonModChoiceProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with choice results.
|
||||
*/
|
||||
getResults(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
|
||||
getResults(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<AddonModChoiceResult[]> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
choiceid: choiceId
|
||||
|
@ -294,7 +303,9 @@ export class AddonModChoiceProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('mod_choice_get_choice_results', params, preSets).then((response) => {
|
||||
return site.read('mod_choice_get_choice_results', params, preSets)
|
||||
.then((response: AddonModChoiceGetChoiceResults): any => {
|
||||
|
||||
if (response.options) {
|
||||
return response.options;
|
||||
}
|
||||
|
@ -456,3 +467,96 @@ export class AddonModChoiceProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choice returned by mod_choice_get_choices_by_courses.
|
||||
*/
|
||||
export type AddonModChoiceChoice = {
|
||||
id: number; // Choice instance id.
|
||||
coursemodule: number; // Course module id.
|
||||
course: number; // Course id.
|
||||
name: string; // Choice name.
|
||||
intro: string; // The choice intro.
|
||||
introformat: number; // Intro format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
introfiles?: CoreWSExternalFile[]; // @since 3.2.
|
||||
publish?: boolean; // If choice is published.
|
||||
showresults?: number; // 0 never, 1 after answer, 2 after close, 3 always.
|
||||
display?: number; // Display mode (vertical, horizontal).
|
||||
allowupdate?: boolean; // Allow update.
|
||||
allowmultiple?: boolean; // Allow multiple choices.
|
||||
showunanswered?: boolean; // Show users who not answered yet.
|
||||
includeinactive?: boolean; // Include inactive users.
|
||||
limitanswers?: boolean; // Limit unswers.
|
||||
timeopen?: number; // Date of opening validity.
|
||||
timeclose?: number; // Date of closing validity.
|
||||
showpreview?: boolean; // Show preview before timeopen.
|
||||
timemodified?: number; // Time of last modification.
|
||||
completionsubmit?: boolean; // Completion on user submission.
|
||||
section?: number; // Course section id.
|
||||
visible?: boolean; // Visible.
|
||||
groupmode?: number; // Group mode.
|
||||
groupingid?: number; // Group id.
|
||||
};
|
||||
|
||||
/**
|
||||
* Option returned by mod_choice_get_choice_options.
|
||||
*/
|
||||
export type AddonModChoiceOption = {
|
||||
id: number; // Option id.
|
||||
text: string; // Text of the choice.
|
||||
maxanswers: number; // Maximum number of answers.
|
||||
displaylayout: boolean; // True for orizontal, otherwise vertical.
|
||||
countanswers: number; // Number of answers.
|
||||
checked: boolean; // We already answered.
|
||||
disabled: boolean; // Option disabled.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result returned by mod_choice_get_choice_results.
|
||||
*/
|
||||
export type AddonModChoiceResult = {
|
||||
id: number; // Choice instance id.
|
||||
text: string; // Text of the choice.
|
||||
maxanswer: number; // Maximum number of answers.
|
||||
userresponses: {
|
||||
userid: number; // User id.
|
||||
fullname: string; // User full name.
|
||||
profileimageurl: string; // Profile user image url.
|
||||
answerid?: number; // Answer id.
|
||||
timemodified?: number; // Time of modification.
|
||||
}[];
|
||||
numberofuser: number; // Number of users answers.
|
||||
percentageamount: number; // Percentage of users answers.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS mod_choice_get_choices_by_courses.
|
||||
*/
|
||||
export type AddonModChoiceGetChoicesByCoursesResult = {
|
||||
choices: AddonModChoiceChoice[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS mod_choice_get_choice_options.
|
||||
*/
|
||||
export type AddonModChoiceGetChoiceOptionsResult = {
|
||||
options: AddonModChoiceOption[]; // Options.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS mod_choice_get_choice_results.
|
||||
*/
|
||||
export type AddonModChoiceGetChoiceResults = {
|
||||
options: AddonModChoiceResult[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS mod_choice_delete_choice_responses.
|
||||
*/
|
||||
export type AddonModChoiceDeleteChoiceResponsesResult = {
|
||||
status: boolean; // Status, true if everything went right.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue