MOBILE-3923 starredcourses: Use fallback WS if timemodified not present

main
Pau Ferrer Ocaña 2021-12-03 11:10:44 +01:00
parent ac08c758ce
commit 297df38744
5 changed files with 160 additions and 11 deletions

View File

@ -16,11 +16,17 @@ import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData, CoreCourses } from '@features/courses/services/courses';
import { CoreCoursesHelper, CoreEnrolledCourseDataWithOptions } from '@features/courses/services/courses-helper';
import {
CoreCourseSearchedDataWithExtraInfoAndOptions,
CoreCoursesHelper,
CoreEnrolledCourseDataWithOptions,
} from '@features/courses/services/courses-helper';
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
import { CoreUtils } from '@services/utils/utils';
import { CoreSite } from '@classes/site';
import { AddonBlockStarredCourse, AddonBlockStarredCourses } from '../../services/starredcourses';
/**
* Component to render a starred courses block.
@ -33,11 +39,12 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
@Input() downloadEnabled = false;
courses: CoreEnrolledCourseDataWithOptions [] = [];
courses: AddonBlockStarredCoursesCourse[] = [];
downloadCourseEnabled = false;
scrollElementId!: string;
protected site!: CoreSite;
protected isDestroyed = false;
protected coursesObserver?: CoreEventObserver;
protected updateSiteObserver?: CoreEventObserver;
@ -45,6 +52,8 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
constructor() {
super('AddonBlockStarredCoursesComponent');
this.site = CoreSites.getRequiredCurrentSite();
}
/**
@ -94,8 +103,12 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
protected async invalidateCourses(courseIds: number[]): Promise<void> {
const promises: Promise<void>[] = [];
const invalidateCoursePromise = this.site.isVersionGreaterEqualThan('4.0')
? CoreCourses.invalidateUserCourses()
: AddonBlockStarredCourses.invalidateStarredCourses();
// Invalidate course completion data.
promises.push(CoreCourses.invalidateUserCourses().finally(() =>
promises.push(invalidateCoursePromise.finally(() =>
CoreUtils.allPromises(courseIds.map((courseId) =>
AddonCourseCompletion.invalidateCourseCompletion(courseId)))));
@ -118,8 +131,36 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
const showCategories = this.block.configsRecord && this.block.configsRecord.displaycategories &&
this.block.configsRecord.displaycategories.value == '1';
// @TODO: Sort won't coincide with website because timemodified is not informed.
this.courses = await CoreCoursesHelper.getUserCoursesWithOptions('timemodified', 0, 'isfavourite', showCategories);
if (this.site.isVersionGreaterEqualThan('4.0')) {
this.courses = await CoreCoursesHelper.getUserCoursesWithOptions('timemodified', 0, 'isfavourite', showCategories);
return;
}
// Timemodified not present, use the block WS to retrieve the info.
const starredCourses = await AddonBlockStarredCourses.getStarredCourses();
const courseIds = starredCourses.map((course) => course.id);
// Get the courses using getCoursesByField to get more info about each course.
const courses = await CoreCourses.getCoursesByField('ids', courseIds.join(','));
this.courses = starredCourses.map((recentCourse) => {
const course = courses.find((course) => recentCourse.id == course.id);
return Object.assign(recentCourse, course);
});
// Get course options and extra info.
const options = await CoreCourses.getCoursesAdminAndNavOptions(courseIds);
this.courses.forEach((course) => {
course.navOptions = options.navOptions[course.id];
course.admOptions = options.admOptions[course.id];
if (!showCategories) {
course.categoryname = '';
}
});
}
/**
@ -155,7 +196,6 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
}
await this.invalidateCourses([course.id]);
}
}
@ -169,3 +209,9 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
}
}
type AddonBlockStarredCoursesCourse =
(AddonBlockStarredCourse & CoreCourseSearchedDataWithExtraInfoAndOptions) |
(CoreEnrolledCourseDataWithOptions & {
categoryname?: string; // Category name,
});

View File

@ -0,0 +1,101 @@
// (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 { Injectable } from '@angular/core';
import { CoreSites } from '@services/sites';
import { CoreSiteWSPreSets } from '@classes/site';
import { makeSingleton } from '@singletons';
const ROOT_CACHE_KEY = 'AddonBlockStarredCourses:';
/**
* Service that provides some features regarding starred courses.
*/
@Injectable( { providedIn: 'root' })
export class AddonBlockStarredCoursesProvider {
/**
* Get cache key for get starred courrses value WS call.
*
* @return Cache key.
*/
protected getStarredCoursesCacheKey(): string {
return ROOT_CACHE_KEY + ':starredcourses';
}
/**
* Get starred courrses.
*
* @param siteId Site ID. If not defined, use current site.
* @return Promise resolved when the info is retrieved.
*/
async getStarredCourses(siteId?: string): Promise<AddonBlockStarredCourse[]> {
const site = await CoreSites.getSite(siteId);
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getStarredCoursesCacheKey(),
};
return await site.read<AddonBlockStarredCourse[]>('block_starredcourses_get_starred_courses', undefined, preSets);
}
/**
* Invalidates get starred courrses WS call.
*
* @param siteId Site ID to invalidate. If not defined, use current site.
* @return Promise resolved when the data is invalidated.
*/
async invalidateStarredCourses(siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
await site.invalidateWsCacheForKey(this.getStarredCoursesCacheKey());
}
}
export const AddonBlockStarredCourses = makeSingleton(AddonBlockStarredCoursesProvider);
/**
* Params of block_starredcourses_get_starred_courses WS.
*/
export type AddonBlockStarredCoursesGetStarredCoursesWSParams = {
limit?: number; // Limit.
offset?: number; // Offset.
};
/**
* Data returned by block_starredcourses_get_starred_courses WS.
*/
export type AddonBlockStarredCourse = {
id: number; // Id.
fullname: string; // Fullname.
shortname: string; // Shortname.
idnumber: string; // Idnumber.
summary: string; // Summary.
summaryformat: number; // Summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
startdate: number; // Startdate.
enddate: number; // Enddate.
visible: boolean; // Visible.
showactivitydates: boolean; // Showactivitydates.
showcompletionconditions: boolean; // Showcompletionconditions.
fullnamedisplay: string; // Fullnamedisplay.
viewurl: string; // Viewurl.
courseimage: string; // Courseimage.
progress?: number; // Progress.
hasprogress: boolean; // Hasprogress.
isfavourite: boolean; // Isfavourite.
hidden: boolean; // Hidden.
timeaccess?: number; // Timeaccess.
showshortname: boolean; // Showshortname.
coursecategory: string; // Coursecategory.
};

View File

@ -1299,6 +1299,7 @@ export type CoreCourseSummary = {
coursecategory: string; // @since 3.7. Coursecategory.
showactivitydates: boolean | null; // @since 3.11. Whether the activity dates are shown or not.
showcompletionconditions: boolean | null; // @since 3.11. Whether the activity completion conditions are shown or not.
timemodified?: number; // @since 4.0. Last time course settings were updated (timestamp).
};
/**

View File

@ -236,7 +236,7 @@ export class CoreCoursesHelperProvider {
courses = courses.filter((course) => !!course.isfavourite);
break;
default:
// Filter not implemented.
// Filter not implemented.
}
switch (sort) {
@ -251,10 +251,10 @@ export class CoreCoursesHelperProvider {
case 'lastaccess':
courses.sort((a, b) => (b.lastaccess || 0) - (a.lastaccess || 0));
break;
// @todo Time modified property is not defined in CoreEnrolledCourseDataWithOptions, so it Won't do anything.
// case 'timemodified':
// courses.sort((a, b) => b.timemodified - a.timemodified);
// break;
// Time modified property is defined on Moodle 4.0.
case 'timemodified':
courses.sort((a, b) => (b.timemodified || 0) - (a.timemodified || 0));
break;
case 'shortname':
courses.sort((a, b) => {
const compareA = a.shortname.toLowerCase();

View File

@ -1328,6 +1328,7 @@ export type CoreEnrolledCourseData = CoreEnrolledCourseBasicData & {
overviewfiles?: CoreWSExternalFile[];
showactivitydates?: boolean; // @since 3.11. Whether the activity dates are shown or not.
showcompletionconditions?: boolean; // @since 3.11. Whether the activity completion conditions are shown or not.
timemodified?: number; // @since 4.0. Last time course settings were updated (timestamp).
};
/**