MOBILE-3651 core: Specify some nulls in WS responses
parent
1c443b183b
commit
05f5967ffc
|
@ -897,10 +897,7 @@ export class AddonMessagesProvider {
|
||||||
): Promise<{members: AddonMessagesConversationMember[]; canLoadMore: boolean}> {
|
): Promise<{members: AddonMessagesConversationMember[]; canLoadMore: boolean}> {
|
||||||
const site = await CoreSites.instance.getSite(siteId);
|
const site = await CoreSites.instance.getSite(siteId);
|
||||||
userId = userId || site.getUserId();
|
userId = userId || site.getUserId();
|
||||||
|
limitTo = limitTo ?? AddonMessagesProvider.LIMIT_MESSAGES;
|
||||||
if (typeof limitTo == 'undefined' || limitTo === null) {
|
|
||||||
limitTo = AddonMessagesProvider.LIMIT_MESSAGES;
|
|
||||||
}
|
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getCacheKeyForConversationMembers(userId, conversationId),
|
cacheKey: this.getCacheKeyForConversationMembers(userId, conversationId),
|
||||||
|
@ -948,11 +945,9 @@ export class AddonMessagesProvider {
|
||||||
|
|
||||||
options.userId = options.userId || site.getUserId();
|
options.userId = options.userId || site.getUserId();
|
||||||
options.limitFrom = options.limitFrom || 0;
|
options.limitFrom = options.limitFrom || 0;
|
||||||
options.limitTo = options.limitTo === undefined || options.limitTo === null
|
options.limitTo = options.limitTo ?? AddonMessagesProvider.LIMIT_MESSAGES;
|
||||||
? AddonMessagesProvider.LIMIT_MESSAGES
|
|
||||||
: options.limitTo;
|
|
||||||
options.timeFrom = options.timeFrom || 0;
|
options.timeFrom = options.timeFrom || 0;
|
||||||
options.newestFirst = options.newestFirst === undefined || options.newestFirst === null ? true : options.newestFirst;
|
options.newestFirst = options.newestFirst ?? true;
|
||||||
|
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getCacheKeyForConversationMessages(options.userId, conversationId),
|
cacheKey: this.getCacheKeyForConversationMessages(options.userId, conversationId),
|
||||||
|
|
|
@ -531,7 +531,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formattedData.lessonscored) {
|
if (formattedData.lessonscored) {
|
||||||
if (formattedData.numofattempts) {
|
if (formattedData.numofattempts && formattedData.avescore != null) {
|
||||||
formattedData.avescore = CoreTextUtils.instance.roundToDecimals(formattedData.avescore, 2);
|
formattedData.avescore = CoreTextUtils.instance.roundToDecimals(formattedData.avescore, 2);
|
||||||
}
|
}
|
||||||
if (formattedData.highscore != null) {
|
if (formattedData.highscore != null) {
|
||||||
|
|
|
@ -2231,14 +2231,14 @@ export class AddonModLessonProvider {
|
||||||
* @param data Data containing the user answer.
|
* @param data Data containing the user answer.
|
||||||
* @return User response.
|
* @return User response.
|
||||||
*/
|
*/
|
||||||
protected getUserResponseMultichoice(data: Record<string, unknown>): number[] | null {
|
protected getUserResponseMultichoice(data: Record<string, unknown>): number[] | undefined {
|
||||||
if (data.answer) {
|
if (data.answer) {
|
||||||
// The data is already stored as expected. If it's valid, parse the values to int.
|
// The data is already stored as expected. If it's valid, parse the values to int.
|
||||||
if (Array.isArray(data.answer)) {
|
if (Array.isArray(data.answer)) {
|
||||||
return data.answer.map((value) => parseInt(value, 10));
|
return data.answer.map((value) => parseInt(value, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data is stored in properties like 'answer[379]'. Recreate the answer array.
|
// Data is stored in properties like 'answer[379]'. Recreate the answer array.
|
||||||
|
@ -3979,12 +3979,12 @@ export type AddonModLessonGetAttemptsOverviewWSResponse = {
|
||||||
export type AddonModLessonAttemptsOverviewWSData = {
|
export type AddonModLessonAttemptsOverviewWSData = {
|
||||||
lessonscored: boolean; // True if the lesson was scored.
|
lessonscored: boolean; // True if the lesson was scored.
|
||||||
numofattempts: number; // Number of attempts.
|
numofattempts: number; // Number of attempts.
|
||||||
avescore: number; // Average score.
|
avescore: number | null; // Average score.
|
||||||
highscore: number; // High score.
|
highscore: number | null; // High score.
|
||||||
lowscore: number; // Low score.
|
lowscore: number | null; // Low score.
|
||||||
avetime: number; // Average time (spent in taking the lesson).
|
avetime: number | null; // Average time (spent in taking the lesson).
|
||||||
hightime: number; // High time.
|
hightime: number | null; // High time.
|
||||||
lowtime: number; // Low time.
|
lowtime: number | null; // Low time.
|
||||||
students?: AddonModLessonAttemptsOverviewsStudentWSData[]; // Students data, including attempts.
|
students?: AddonModLessonAttemptsOverviewsStudentWSData[]; // Students data, including attempts.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4003,7 +4003,7 @@ export type AddonModLessonAttemptsOverviewsStudentWSData = {
|
||||||
*/
|
*/
|
||||||
export type AddonModLessonAttemptsOverviewsAttemptWSData = {
|
export type AddonModLessonAttemptsOverviewsAttemptWSData = {
|
||||||
try: number; // Attempt number.
|
try: number; // Attempt number.
|
||||||
grade: number; // Attempt grade.
|
grade: number | null; // Attempt grade.
|
||||||
timestart: number; // Attempt time started.
|
timestart: number; // Attempt time started.
|
||||||
timeend: number; // Attempt last time continued.
|
timeend: number; // Attempt last time continued.
|
||||||
end: number; // Attempt time ended.
|
end: number; // Attempt time ended.
|
||||||
|
|
|
@ -85,8 +85,8 @@ export class AddonModQuizProvider {
|
||||||
* @param decimals Decimals to use.
|
* @param decimals Decimals to use.
|
||||||
* @return Grade to display.
|
* @return Grade to display.
|
||||||
*/
|
*/
|
||||||
formatGrade(grade?: number, decimals?: number): string {
|
formatGrade(grade?: number | null, decimals?: number): string {
|
||||||
if (typeof grade == 'undefined' || grade == -1 || grade === null || isNaN(grade)) {
|
if (grade === undefined || grade == -1 || grade === null || isNaN(grade)) {
|
||||||
return Translate.instance.instant('addon.mod_quiz.notyetgraded');
|
return Translate.instance.instant('addon.mod_quiz.notyetgraded');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1796,14 +1796,14 @@ export class AddonModQuizProvider {
|
||||||
* @return Grade to display.
|
* @return Grade to display.
|
||||||
*/
|
*/
|
||||||
rescaleGrade(
|
rescaleGrade(
|
||||||
rawGrade: string | number | undefined,
|
rawGrade: string | number | undefined | null,
|
||||||
quiz: AddonModQuizQuizWSData,
|
quiz: AddonModQuizQuizWSData,
|
||||||
format: boolean | string = true,
|
format: boolean | string = true,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
let grade: number | undefined;
|
let grade: number | undefined;
|
||||||
|
|
||||||
const rawGradeNum = typeof rawGrade == 'string' ? parseFloat(rawGrade) : rawGrade;
|
const rawGradeNum = typeof rawGrade == 'string' ? parseFloat(rawGrade) : rawGrade;
|
||||||
if (rawGradeNum !== undefined && !isNaN(rawGradeNum)) {
|
if (rawGradeNum !== undefined && rawGradeNum !== null && !isNaN(rawGradeNum)) {
|
||||||
if (quiz.sumgrades! >= 0.000005) {
|
if (quiz.sumgrades! >= 0.000005) {
|
||||||
grade = rawGradeNum * quiz.grade! / quiz.sumgrades!;
|
grade = rawGradeNum * quiz.grade! / quiz.sumgrades!;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2055,7 +2055,7 @@ export type AddonModQuizAttemptWSData = {
|
||||||
timemodified?: number; // Last modified time.
|
timemodified?: number; // Last modified time.
|
||||||
timemodifiedoffline?: number; // Last modified time via webservices.
|
timemodifiedoffline?: number; // Last modified time via webservices.
|
||||||
timecheckstate?: number; // Next time quiz cron should check attempt for state changes. NULL means never check.
|
timecheckstate?: number; // Next time quiz cron should check attempt for state changes. NULL means never check.
|
||||||
sumgrades?: number; // Total marks for this attempt.
|
sumgrades?: number | null; // Total marks for this attempt.
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2215,7 +2215,7 @@ export type AddonModQuizQuizWSData = {
|
||||||
questionsperpage?: number; // How often to insert a page break when editing the quiz, or when shuffling the question order.
|
questionsperpage?: number; // How often to insert a page break when editing the quiz, or when shuffling the question order.
|
||||||
navmethod?: string; // Any constraints on how the user is allowed to navigate around the quiz.
|
navmethod?: string; // Any constraints on how the user is allowed to navigate around the quiz.
|
||||||
shuffleanswers?: number; // Whether the parts of the question should be shuffled, in those question types that support it.
|
shuffleanswers?: number; // Whether the parts of the question should be shuffled, in those question types that support it.
|
||||||
sumgrades?: number; // The total of all the question instance maxmarks.
|
sumgrades?: number | null; // The total of all the question instance maxmarks.
|
||||||
grade?: number; // The total that the quiz overall grade is scaled to be out of.
|
grade?: number; // The total that the quiz overall grade is scaled to be out of.
|
||||||
timecreated?: number; // The time when the quiz was added to the course.
|
timecreated?: number; // The time when the quiz was added to the course.
|
||||||
timemodified?: number; // Last modified time.
|
timemodified?: number; // Last modified time.
|
||||||
|
|
|
@ -160,9 +160,9 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
let section: CoreCourseSection | undefined;
|
let section: CoreCourseSection | undefined;
|
||||||
|
|
||||||
if (typeof data.sectionId != 'undefined' && data.sectionId != null && this.sections) {
|
if (typeof data.sectionId != 'undefined' && this.sections) {
|
||||||
section = this.sections.find((section) => section.id == data.sectionId);
|
section = this.sections.find((section) => section.id == data.sectionId);
|
||||||
} else if (typeof data.sectionNumber != 'undefined' && data.sectionNumber != null && this.sections) {
|
} else if (typeof data.sectionNumber != 'undefined' && this.sections) {
|
||||||
section = this.sections.find((section) => section.section == data.sectionNumber);
|
section = this.sections.find((section) => section.section == data.sectionNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +184,8 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
this.displaySectionSelector = CoreCourseFormatDelegate.instance.displaySectionSelector(this.course);
|
this.displaySectionSelector = CoreCourseFormatDelegate.instance.displaySectionSelector(this.course);
|
||||||
this.displayBlocks = CoreCourseFormatDelegate.instance.displayBlocks(this.course);
|
this.displayBlocks = CoreCourseFormatDelegate.instance.displayBlocks(this.course);
|
||||||
this.progress = 'progress' in this.course && this.course.progress !== undefined && this.course.progress >= 0 &&
|
this.progress = 'progress' in this.course && typeof this.course.progress == 'number' &&
|
||||||
this.course.completionusertracked !== false ? this.course.progress : undefined;
|
this.course.progress >= 0 && this.course.completionusertracked !== false ? this.course.progress : undefined;
|
||||||
if ('overviewfiles' in this.course) {
|
if ('overviewfiles' in this.course) {
|
||||||
this.imageThumb = this.course.overviewfiles?.[0]?.fileurl;
|
this.imageThumb = this.course.overviewfiles?.[0]?.fileurl;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +600,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.completionChanged.emit(completionData);
|
this.completionChanged.emit(completionData);
|
||||||
|
|
||||||
if (completionData.valueused !== false || !this.course || !('progress' in this.course) ||
|
if (completionData.valueused !== false || !this.course || !('progress' in this.course) ||
|
||||||
typeof this.course.progress == 'undefined') {
|
typeof this.course.progress != 'number') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<core-format-text [text]="course.displayname || course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="course.displayname || course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h2>
|
</h2>
|
||||||
<p *ngIf="isEnrolled && course.progress != null && course.progress! >= 0 && course.completionusertracked !== false">
|
<p *ngIf="isEnrolled && course.progress! >= 0 && course.completionusertracked !== false">
|
||||||
<core-progress-bar [progress]="course.progress"></core-progress-bar>
|
<core-progress-bar [progress]="course.progress"></core-progress-bar>
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -34,7 +34,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
|
|
||||||
@Input() course!: CoreCourseSearchedData & CoreCourseWithImageAndColor & {
|
@Input() course!: CoreCourseSearchedData & CoreCourseWithImageAndColor & {
|
||||||
completionusertracked?: boolean; // If the user is completion tracked.
|
completionusertracked?: boolean; // If the user is completion tracked.
|
||||||
progress?: number; // Progress percentage.
|
progress?: number | null; // Progress percentage.
|
||||||
}; // The course to render.
|
}; // The course to render.
|
||||||
|
|
||||||
icons: CoreCoursesEnrolmentIcons[] = [];
|
icons: CoreCoursesEnrolmentIcons[] = [];
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</div>
|
</div>
|
||||||
<ion-item button lines="none" (click)="openCourse()" [title]="course.displayname || course.fullname"
|
<ion-item button lines="none" (click)="openCourse()" [title]="course.displayname || course.fullname"
|
||||||
class="core-course-header" [class.item-disabled]="course.visible == 0"
|
class="core-course-header" [class.item-disabled]="course.visible == 0"
|
||||||
[class.core-course-more-than-title]="(course.progress != null && course.progress! >= 0)">
|
[class.core-course-more-than-title]="course.progress! >= 0">
|
||||||
<ion-label
|
<ion-label
|
||||||
class="ion-text-wrap core-course-title"
|
class="ion-text-wrap core-course-title"
|
||||||
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
||||||
|
@ -50,7 +50,8 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="showAll && course.progress != null && course.progress! >= 0 && course.completionusertracked !== false" lines="none">
|
<ion-item *ngIf="showAll && course.progress! >= 0 && course.completionusertracked !== false"
|
||||||
|
lines="none">
|
||||||
<ion-label><core-progress-bar [progress]="course.progress"></core-progress-bar></ion-label>
|
<ion-label><core-progress-bar [progress]="course.progress"></core-progress-bar></ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ export type CoreEnrolledCourseData = CoreEnrolledCourseBasicData & {
|
||||||
enrolledusercount?: number; // Number of enrolled users in this course.
|
enrolledusercount?: number; // Number of enrolled users in this course.
|
||||||
completionhascriteria?: boolean; // If completion criteria is set.
|
completionhascriteria?: boolean; // If completion criteria is set.
|
||||||
completionusertracked?: boolean; // If the user is completion tracked.
|
completionusertracked?: boolean; // If the user is completion tracked.
|
||||||
progress?: number; // Progress percentage.
|
progress?: number | null; // Progress percentage.
|
||||||
completed?: boolean; // Whether the course is completed.
|
completed?: boolean; // Whether the course is completed.
|
||||||
marker?: number; // Course section marker.
|
marker?: number; // Course section marker.
|
||||||
lastaccess?: number; // Last access to the course (timestamp).
|
lastaccess?: number; // Last access to the course (timestamp).
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<p class="ion-text-wrap">{{ site.fullName }}</p>
|
<p class="ion-text-wrap">{{ site.fullName }}</p>
|
||||||
<p>{{ site.siteUrl }}</p>
|
<p>{{ site.siteUrl }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<p *ngIf="site.spaceUsage != null" slot="end">
|
<p *ngIf="site.spaceUsage !== undefined" slot="end">
|
||||||
{{ site.spaceUsage | coreBytesToSize }}
|
{{ site.spaceUsage | coreBytesToSize }}
|
||||||
</p>
|
</p>
|
||||||
<ion-button fill="clear" color="danger" slot="end" (click)="deleteSiteStorage(site)"
|
<ion-button fill="clear" color="danger" slot="end" (click)="deleteSiteStorage(site)"
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<ng-container *ngIf="!searchQuery">
|
<ng-container *ngIf="!searchQuery">
|
||||||
<h2>{{ participant.fullname }}</h2>
|
<h2>{{ participant.fullname }}</h2>
|
||||||
<p *ngIf="participant.lastcourseaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastcourseaccess | coreTimeAgo }}</p>
|
<p *ngIf="participant.lastcourseaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastcourseaccess | coreTimeAgo }}</p>
|
||||||
<p *ngIf="participant.lastcourseaccess == null && participant.lastaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastaccess | coreTimeAgo }}</p>
|
<p *ngIf="!participant.lastcourseaccess && participant.lastaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastaccess | coreTimeAgo }}</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="searchQuery">
|
<ng-container *ngIf="searchQuery">
|
||||||
|
|
|
@ -964,7 +964,7 @@ export type CoreUserParticipant = CoreUserBasicData & {
|
||||||
interests?: string; // User interests (separated by commas).
|
interests?: string; // User interests (separated by commas).
|
||||||
firstaccess?: number; // First access to the site (0 if never).
|
firstaccess?: number; // First access to the site (0 if never).
|
||||||
lastaccess?: number; // Last access to the site (0 if never).
|
lastaccess?: number; // Last access to the site (0 if never).
|
||||||
lastcourseaccess?: number; // Last access to the course (0 if never).
|
lastcourseaccess?: number | null; // Last access to the course (0 if never).
|
||||||
description?: string; // User profile description.
|
description?: string; // User profile description.
|
||||||
descriptionformat?: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
descriptionformat?: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||||
city?: string; // Home city of the user.
|
city?: string; // Home city of the user.
|
||||||
|
@ -1114,4 +1114,3 @@ type CoreEnrolSearchUsersWSParams = {
|
||||||
* Data returned by core_enrol_search_users WS.
|
* Data returned by core_enrol_search_users WS.
|
||||||
*/
|
*/
|
||||||
type CoreEnrolSearchUsersWSResponse = CoreUserData[];
|
type CoreEnrolSearchUsersWSResponse = CoreUserData[];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue