Merge pull request #2953 from dpalou/MOBILE-3848
MOBILE-3848 dashboard: Support guest courses in recently accessedmain
commit
24e4f5797d
|
@ -16,7 +16,7 @@ import { Component, OnInit, OnDestroy, Input, OnChanges, SimpleChange } from '@a
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData, CoreCourses } from '@features/courses/services/courses';
|
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData, CoreCourses } from '@features/courses/services/courses';
|
||||||
import { CoreCoursesHelper, CoreEnrolledCourseDataWithOptions } from '@features/courses/services/courses-helper';
|
import { CoreCourseSearchedDataWithExtraInfoAndOptions, CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
|
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
|
||||||
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
|
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
|
||||||
|
@ -35,7 +35,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
||||||
|
|
||||||
@Input() downloadEnabled = false;
|
@Input() downloadEnabled = false;
|
||||||
|
|
||||||
courses: CoreEnrolledCourseDataWithOptions [] = [];
|
courses: CoreCourseSearchedDataWithExtraInfoAndOptions[] = [];
|
||||||
prefetchCoursesData: CorePrefetchStatusInfo = {
|
prefetchCoursesData: CorePrefetchStatusInfo = {
|
||||||
icon: '',
|
icon: '',
|
||||||
statusTranslatable: 'core.loading',
|
statusTranslatable: 'core.loading',
|
||||||
|
@ -112,7 +112,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
||||||
protected async invalidateContent(): Promise<void> {
|
protected async invalidateContent(): Promise<void> {
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
promises.push(CoreCourses.invalidateUserCourses().finally(() =>
|
promises.push(CoreCourses.invalidateRecentCourses().finally(() =>
|
||||||
// Invalidate course completion data.
|
// Invalidate course completion data.
|
||||||
CoreUtils.allPromises(this.courseIds.map((courseId) =>
|
CoreUtils.allPromises(this.courseIds.map((courseId) =>
|
||||||
AddonCourseCompletion.invalidateCourseCompletion(courseId)))));
|
AddonCourseCompletion.invalidateCourseCompletion(courseId)))));
|
||||||
|
@ -136,7 +136,33 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
||||||
const showCategories = this.block.configsRecord && this.block.configsRecord.displaycategories &&
|
const showCategories = this.block.configsRecord && this.block.configsRecord.displaycategories &&
|
||||||
this.block.configsRecord.displaycategories.value == '1';
|
this.block.configsRecord.displaycategories.value == '1';
|
||||||
|
|
||||||
this.courses = await CoreCoursesHelper.getUserCoursesWithOptions('lastaccess', 10, undefined, showCategories);
|
const recentCourses = await CoreCourses.getRecentCourses();
|
||||||
|
const courseIds = recentCourses.map((course) => course.id);
|
||||||
|
|
||||||
|
// Get the courses using getCoursesByField to get more info about each course.
|
||||||
|
const courses: CoreCourseSearchedDataWithExtraInfoAndOptions[] = await CoreCourses.getCoursesByField(
|
||||||
|
'ids',
|
||||||
|
courseIds.join(','),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sort them in the original order.
|
||||||
|
courses.sort((courseA, courseB) => courseIds.indexOf(courseA.id) - courseIds.indexOf(courseB.id));
|
||||||
|
|
||||||
|
// Get course options and extra info.
|
||||||
|
const options = await CoreCourses.getCoursesAdminAndNavOptions(courseIds);
|
||||||
|
courses.forEach((course) => {
|
||||||
|
course.navOptions = options.navOptions[course.id];
|
||||||
|
course.admOptions = options.admOptions[course.id];
|
||||||
|
|
||||||
|
if (!showCategories) {
|
||||||
|
course.categoryname = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await CoreCoursesHelper.loadCoursesColorAndImage(courses);
|
||||||
|
|
||||||
|
this.courses = courses;
|
||||||
|
|
||||||
this.initPrefetchCoursesIcons();
|
this.initPrefetchCoursesIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +174,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
||||||
protected async refreshCourseList(): Promise<void> {
|
protected async refreshCourseList(): Promise<void> {
|
||||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);
|
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);
|
||||||
|
|
||||||
try {
|
await CoreUtils.ignoreErrors(CoreCourses.invalidateRecentCourses());
|
||||||
await CoreCourses.invalidateUserCourses();
|
|
||||||
} catch (error) {
|
|
||||||
// Ignore errors.
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.loadContent(true);
|
await this.loadContent(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ import {
|
||||||
CoreCourseSearchedData,
|
CoreCourseSearchedData,
|
||||||
CoreEnrolledCourseData,
|
CoreEnrolledCourseData,
|
||||||
} from '@features/courses/services/courses';
|
} from '@features/courses/services/courses';
|
||||||
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper';
|
|
||||||
import { CoreArray } from '@singletons/array';
|
import { CoreArray } from '@singletons/array';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
||||||
import { CoreCourseOffline } from './course-offline';
|
import { CoreCourseOffline } from './course-offline';
|
||||||
|
@ -424,7 +423,7 @@ export class CoreCourseHelperProvider {
|
||||||
* @return Resolved when downloaded, rejected if error or canceled.
|
* @return Resolved when downloaded, rejected if error or canceled.
|
||||||
*/
|
*/
|
||||||
async confirmAndPrefetchCourses(
|
async confirmAndPrefetchCourses(
|
||||||
courses: CoreEnrolledCourseDataWithExtraInfoAndOptions[],
|
courses: CoreCourseAnyCourseData[],
|
||||||
options: CoreCourseConfirmPrefetchCoursesOptions = {},
|
options: CoreCourseConfirmPrefetchCoursesOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const siteId = CoreSites.getCurrentSiteId();
|
const siteId = CoreSites.getCurrentSiteId();
|
||||||
|
@ -1302,7 +1301,7 @@ export class CoreCourseHelperProvider {
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async prefetchCourses(
|
async prefetchCourses(
|
||||||
courses: CoreEnrolledCourseDataWithExtraInfoAndOptions[],
|
courses: CoreCourseAnyCourseData[],
|
||||||
prefetch: CorePrefetchStatusInfo,
|
prefetch: CorePrefetchStatusInfo,
|
||||||
options: CoreCoursePrefetchCoursesOptions = {},
|
options: CoreCoursePrefetchCoursesOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</div>
|
</div>
|
||||||
<ion-item button lines="none" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
|
<ion-item button lines="none" (click)="openCourse()" [attr.aria-label]="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-only-title]="!showAll || course.progress! < 0 && course.completionusertracked === false"
|
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false"
|
||||||
detail="false">
|
detail="false">
|
||||||
<ion-label
|
<ion-label
|
||||||
class="ion-text-wrap core-course-title"
|
class="ion-text-wrap core-course-title"
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<ion-icon name="fas-star" *ngIf="course.isfavourite" [attr.aria-label]="'core.courses.favourite' | translate">
|
<ion-icon name="fas-star" *ngIf="isFavourite" [attr.aria-label]="'core.courses.favourite' | translate">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<span class="sr-only" *ngIf="course.isfavourite">{{ 'core.courses.aria:favourite' | translate }}</span>
|
<span class="sr-only" *ngIf="isFavourite">{{ 'core.courses.aria:favourite' | translate }}</span>
|
||||||
<span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span>
|
<span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span>
|
||||||
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"></core-format-text>
|
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"></core-format-text>
|
||||||
</p>
|
</p>
|
||||||
|
@ -61,10 +61,10 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="showAll && course.progress! >= 0 && course.completionusertracked !== false" lines="none"
|
<ion-item *ngIf="showAll && progress >= 0 && completionUserTracked !== false" lines="none"
|
||||||
class="core-course-progress">
|
class="core-course-progress">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-progress-bar [progress]="course.progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
|
<core-progress-bar [progress]="progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
import { Component, Input, OnInit, OnDestroy, OnChanges } from '@angular/core';
|
||||||
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -21,7 +21,10 @@ import { CoreCourse, CoreCourseProvider } from '@features/course/services/course
|
||||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
|
import {
|
||||||
|
CoreCourseAnyCourseDataWithExtraInfoAndOptions,
|
||||||
|
CoreEnrolledCourseDataWithExtraInfoAndOptions,
|
||||||
|
} from '../../services/courses-helper';
|
||||||
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
||||||
import { CoreUser } from '@features/user/services/user';
|
import { CoreUser } from '@features/user/services/user';
|
||||||
|
|
||||||
|
@ -38,9 +41,10 @@ import { CoreUser } from '@features/user/services/user';
|
||||||
templateUrl: 'core-courses-course-progress.html',
|
templateUrl: 'core-courses-course-progress.html',
|
||||||
styleUrls: ['course-progress.scss'],
|
styleUrls: ['course-progress.scss'],
|
||||||
})
|
})
|
||||||
export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
|
|
||||||
@Input() course!: CoreEnrolledCourseDataWithExtraInfoAndOptions; // The course to render.
|
// The course to render.
|
||||||
|
@Input() course!: CoreCourseAnyCourseDataWithExtraInfoAndOptions;
|
||||||
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
||||||
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
||||||
|
|
||||||
|
@ -56,13 +60,16 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
showSpinner = false;
|
showSpinner = false;
|
||||||
downloadCourseEnabled = false;
|
downloadCourseEnabled = false;
|
||||||
courseOptionMenuEnabled = false;
|
courseOptionMenuEnabled = false;
|
||||||
|
isFavourite = false;
|
||||||
|
progress = -1;
|
||||||
|
completionUserTracked: boolean | undefined = false;
|
||||||
|
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
protected courseStatusObserver?: CoreEventObserver;
|
protected courseStatusObserver?: CoreEventObserver;
|
||||||
protected siteUpdatedObserver?: CoreEventObserver;
|
protected siteUpdatedObserver?: CoreEventObserver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
@ -73,7 +80,8 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This field is only available from 3.6 onwards.
|
// This field is only available from 3.6 onwards.
|
||||||
this.courseOptionMenuEnabled = this.showAll && typeof this.course.isfavourite != 'undefined';
|
this.courseOptionMenuEnabled = this.showAll && 'isfavourite' in this.course &&
|
||||||
|
typeof this.course.isfavourite != 'undefined';
|
||||||
|
|
||||||
// Refresh the enabled flag if site is updated.
|
// Refresh the enabled flag if site is updated.
|
||||||
this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
||||||
|
@ -88,6 +96,15 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
}, CoreSites.getCurrentSiteId());
|
}, CoreSites.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnChanges(): void {
|
||||||
|
this.isFavourite = 'isfavourite' in this.course && !!this.course.isfavourite;
|
||||||
|
this.progress = 'progress' in this.course ? this.course.progress || -1 : -1;
|
||||||
|
this.completionUserTracked = 'completionusertracked' in this.course && this.course.completionusertracked;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize prefetch course.
|
* Initialize prefetch course.
|
||||||
*/
|
*/
|
||||||
|
@ -255,7 +272,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
hide ? '1' : undefined,
|
hide ? '1' : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.course.hidden = hide;
|
(<CoreEnrolledCourseDataWithExtraInfoAndOptions> this.course).hidden = hide;
|
||||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
||||||
courseId: this.course.id,
|
courseId: this.course.id,
|
||||||
course: this.course,
|
course: this.course,
|
||||||
|
@ -284,7 +301,8 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
try {
|
try {
|
||||||
await CoreCourses.setFavouriteCourse(this.course.id, favourite);
|
await CoreCourses.setFavouriteCourse(this.course.id, favourite);
|
||||||
|
|
||||||
this.course.isfavourite = favourite;
|
(<CoreEnrolledCourseDataWithExtraInfoAndOptions> this.course).isfavourite = favourite;
|
||||||
|
this.isFavourite = favourite;
|
||||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
||||||
courseId: this.course.id,
|
courseId: this.course.id,
|
||||||
course: this.course,
|
course: this.course,
|
||||||
|
|
|
@ -15,7 +15,13 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreCourses, CoreCourseSearchedData, CoreCourseUserAdminOrNavOptionIndexed, CoreEnrolledCourseData } from './courses';
|
import {
|
||||||
|
CoreCourseAnyCourseDataWithOptions,
|
||||||
|
CoreCourses,
|
||||||
|
CoreCourseSearchedData,
|
||||||
|
CoreCourseUserAdminOrNavOptionIndexed,
|
||||||
|
CoreEnrolledCourseData,
|
||||||
|
} from './courses';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreWSExternalFile } from '@services/ws';
|
import { CoreWSExternalFile } from '@services/ws';
|
||||||
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
|
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
|
||||||
|
@ -83,6 +89,31 @@ export class CoreCoursesHelperProvider {
|
||||||
this.loadCourseColorAndImage(course, colors);
|
this.loadCourseColorAndImage(course, colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a list of courses returned by core_enrol_get_users_courses, load some extra data using the WebService
|
||||||
|
* core_course_get_courses_by_field if available.
|
||||||
|
*
|
||||||
|
* @param courses List of courses.
|
||||||
|
* @param loadCategoryNames Whether load category names or not.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Loads the color of courses or the thumb image.
|
||||||
|
*
|
||||||
|
* @param courses List of courses.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async loadCoursesColorAndImage(courses: CoreCourseSearchedData[]): Promise<void> {
|
||||||
|
if (!courses.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const colors = await this.loadCourseSiteColors();
|
||||||
|
|
||||||
|
courses.forEach((course) => {
|
||||||
|
this.loadCourseColorAndImage(course, colors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of courses returned by core_enrol_get_users_courses, load some extra data using the WebService
|
* Given a list of courses returned by core_enrol_get_users_courses, load some extra data using the WebService
|
||||||
* core_course_get_courses_by_field if available.
|
* core_course_get_courses_by_field if available.
|
||||||
|
@ -301,7 +332,27 @@ export type CoreEnrolledCourseDataWithOptions = CoreEnrolledCourseData & {
|
||||||
admOptions?: CoreCourseUserAdminOrNavOptionIndexed;
|
admOptions?: CoreCourseUserAdminOrNavOptionIndexed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Course summary data with admin and navigation option availability.
|
||||||
|
*/
|
||||||
|
export type CoreCourseSearchedDataWithOptions = CoreCourseSearchedData & {
|
||||||
|
navOptions?: CoreCourseUserAdminOrNavOptionIndexed;
|
||||||
|
admOptions?: CoreCourseUserAdminOrNavOptionIndexed;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enrolled course data with admin and navigation option availability and extra rendering info.
|
* Enrolled course data with admin and navigation option availability and extra rendering info.
|
||||||
*/
|
*/
|
||||||
export type CoreEnrolledCourseDataWithExtraInfoAndOptions = CoreEnrolledCourseDataWithExtraInfo & CoreEnrolledCourseDataWithOptions;
|
export type CoreEnrolledCourseDataWithExtraInfoAndOptions = CoreEnrolledCourseDataWithExtraInfo & CoreEnrolledCourseDataWithOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searched course data with admin and navigation option availability and extra rendering info.
|
||||||
|
*/
|
||||||
|
export type CoreCourseSearchedDataWithExtraInfoAndOptions = CoreCourseWithImageAndColor & CoreCourseSearchedDataWithOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any course data with admin and navigation option availability and extra rendering info.
|
||||||
|
*/
|
||||||
|
export type CoreCourseAnyCourseDataWithExtraInfoAndOptions = CoreCourseWithImageAndColor & CoreCourseAnyCourseDataWithOptions & {
|
||||||
|
categoryname?: string; // Category name,
|
||||||
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
||||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CoreStatusWithWarningsWSResponse, CoreWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
import { CoreStatusWithWarningsWSResponse, CoreWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||||
|
@ -45,6 +45,7 @@ declare module '@singletons/events' {
|
||||||
export class CoreCoursesProvider {
|
export class CoreCoursesProvider {
|
||||||
|
|
||||||
static readonly SEARCH_PER_PAGE = 20;
|
static readonly SEARCH_PER_PAGE = 20;
|
||||||
|
static readonly RECENT_PER_PAGE = 10;
|
||||||
static readonly ENROL_INVALID_KEY = 'CoreCoursesEnrolInvalidKey';
|
static readonly ENROL_INVALID_KEY = 'CoreCoursesEnrolInvalidKey';
|
||||||
static readonly EVENT_MY_COURSES_CHANGED = 'courses_my_courses_changed'; // User course list changed while app is running.
|
static readonly EVENT_MY_COURSES_CHANGED = 'courses_my_courses_changed'; // User course list changed while app is running.
|
||||||
// A course was hidden/favourite, or user enroled in a course.
|
// A course was hidden/favourite, or user enroled in a course.
|
||||||
|
@ -566,7 +567,7 @@ export class CoreCoursesProvider {
|
||||||
customFieldName: string,
|
customFieldName: string,
|
||||||
customFieldValue: string,
|
customFieldValue: string,
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
): Promise<CoreCourseGetEnrolledCoursesByTimelineClassification[]> {
|
): Promise<CoreCourseSummaryData[]> {
|
||||||
const site = await CoreSites.getSite(siteId);
|
const site = await CoreSites.getSite(siteId);
|
||||||
const params: CoreCourseGetEnrolledCoursesByTimelineClassificationWSParams = {
|
const params: CoreCourseGetEnrolledCoursesByTimelineClassificationWSParams = {
|
||||||
classification: 'customfield',
|
classification: 'customfield',
|
||||||
|
@ -648,6 +649,40 @@ export class CoreCoursesProvider {
|
||||||
return ({ navOptions: navOptions, admOptions: admOptions });
|
return ({ navOptions: navOptions, admOptions: admOptions });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cache key for get recent courses WS call.
|
||||||
|
*
|
||||||
|
* @param userId User ID.
|
||||||
|
* @return Cache key.
|
||||||
|
*/
|
||||||
|
protected getRecentCoursesCacheKey(userId: number): string {
|
||||||
|
return `${ROOT_CACHE_KEY}:recentcourses:${userId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get recent courses.
|
||||||
|
*
|
||||||
|
* @param options Options.
|
||||||
|
* @return Promise resolved with courses.
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
async getRecentCourses(options: CoreCourseGetRecentCoursesOptions = {}): Promise<CoreCourseSummaryData[]> {
|
||||||
|
const site = await CoreSites.getSite(options.siteId);
|
||||||
|
|
||||||
|
const userId = options.userId || site.getUserId();
|
||||||
|
const params: CoreCourseGetRecentCoursesWSParams = {
|
||||||
|
userid: userId,
|
||||||
|
offset: options.offset || 0,
|
||||||
|
limit: options.limit || CoreCoursesProvider.RECENT_PER_PAGE,
|
||||||
|
sort: options.sort,
|
||||||
|
};
|
||||||
|
const preSets: CoreSiteWSPreSets = {
|
||||||
|
cacheKey: this.getRecentCoursesCacheKey(userId),
|
||||||
|
};
|
||||||
|
|
||||||
|
return await site.read<CoreCourseSummaryData[]>('core_course_get_recent_courses', params, preSets);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the common part of the cache keys for user administration options WS calls.
|
* Get the common part of the cache keys for user administration options WS calls.
|
||||||
*
|
*
|
||||||
|
@ -995,6 +1030,19 @@ export class CoreCoursesProvider {
|
||||||
return site.invalidateWsCacheForKey(this.getCoursesByFieldCacheKey(field, value));
|
return site.invalidateWsCacheForKey(this.getCoursesByFieldCacheKey(field, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates get recent courses WS call.
|
||||||
|
*
|
||||||
|
* @param userId User ID. If not defined, current user.
|
||||||
|
* @param siteId Site Id. If not defined, use current site.
|
||||||
|
* @return Promise resolved when the data is invalidated.
|
||||||
|
*/
|
||||||
|
async invalidateRecentCourses(userId?: number, siteId?: string): Promise<void> {
|
||||||
|
const site = await CoreSites.getSite(siteId);
|
||||||
|
|
||||||
|
await site.invalidateWsCacheForKey(this.getRecentCoursesCacheKey(userId || site.getUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates all user administration options.
|
* Invalidates all user administration options.
|
||||||
*
|
*
|
||||||
|
@ -1428,13 +1476,15 @@ type CoreCourseGetCoursesWSParams = {
|
||||||
export type CoreCourseGetCoursesWSResponse = CoreCourseGetCoursesData[];
|
export type CoreCourseGetCoursesWSResponse = CoreCourseGetCoursesData[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Course type exported in CoreCourseGetEnrolledCoursesByTimelineClassificationWSResponse;
|
* Course data exported by course_summary_exporter;
|
||||||
*/
|
*/
|
||||||
export type CoreCourseGetEnrolledCoursesByTimelineClassification = CoreCourseBasicData & { // Course.
|
export type CoreCourseSummaryData = CoreCourseBasicData & { // Course.
|
||||||
idnumber: string; // Idnumber.
|
idnumber: string; // Idnumber.
|
||||||
startdate: number; // Startdate.
|
startdate: number; // Startdate.
|
||||||
enddate: number; // Enddate.
|
enddate: number; // Enddate.
|
||||||
visible: boolean; // Visible.
|
visible: boolean; // Visible.
|
||||||
|
showactivitydates: boolean; // Showactivitydates.
|
||||||
|
showcompletionconditions: boolean; // Showcompletionconditions.
|
||||||
fullnamedisplay: string; // Fullnamedisplay.
|
fullnamedisplay: string; // Fullnamedisplay.
|
||||||
viewurl: string; // Viewurl.
|
viewurl: string; // Viewurl.
|
||||||
courseimage: string; // Courseimage.
|
courseimage: string; // Courseimage.
|
||||||
|
@ -1463,7 +1513,7 @@ type CoreCourseGetEnrolledCoursesByTimelineClassificationWSParams = {
|
||||||
* Data returned by core_course_get_enrolled_courses_by_timeline_classification WS.
|
* Data returned by core_course_get_enrolled_courses_by_timeline_classification WS.
|
||||||
*/
|
*/
|
||||||
export type CoreCourseGetEnrolledCoursesByTimelineClassificationWSResponse = {
|
export type CoreCourseGetEnrolledCoursesByTimelineClassificationWSResponse = {
|
||||||
courses: CoreCourseGetEnrolledCoursesByTimelineClassification[];
|
courses: CoreCourseSummaryData[];
|
||||||
nextoffset: number; // Offset for the next request.
|
nextoffset: number; // Offset for the next request.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1588,6 +1638,26 @@ export type EnrolGuestGetInstanceInfoWSResponse = {
|
||||||
warnings?: CoreWSExternalWarning[];
|
warnings?: CoreWSExternalWarning[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params of core_course_get_recent_courses WS.
|
||||||
|
*/
|
||||||
|
export type CoreCourseGetRecentCoursesWSParams = {
|
||||||
|
userid?: number; // Id of the user, default to current user.
|
||||||
|
limit?: number; // Result set limit.
|
||||||
|
offset?: number; // Result set offset.
|
||||||
|
sort?: string; // Sort string.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for getRecentCourses.
|
||||||
|
*/
|
||||||
|
export type CoreCourseGetRecentCoursesOptions = CoreSitesCommonWSOptions & {
|
||||||
|
userId?: number; // Id of the user, default to current user.
|
||||||
|
limit?: number; // Result set limit.
|
||||||
|
offset?: number; // Result set offset.
|
||||||
|
sort?: string; // Sort string.
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Course guest enrolment method.
|
* Course guest enrolment method.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue