Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions src/addon/block/myoverview/components/myoverview/myoverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Searchbar } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events';
import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreSitesProvider } from '@providers/sites';
import { CoreCoursesProvider } from '@core/courses/providers/courses';
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData } from '@core/courses/providers/courses';
import { CoreCoursesHelperProvider } from '@core/courses/providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
Expand Down Expand Up @@ -112,8 +112,12 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem

}, this.sitesProvider.getCurrentSiteId());

this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
this.refreshContent();
this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
(data: CoreCoursesMyCoursesUpdatedEventData) => {

if (data.action == CoreCoursesProvider.ACTION_ENROL || data.action == CoreCoursesProvider.ACTION_STATE_CHANGED) {
this.refreshCourseList();
}
}, this.sitesProvider.getCurrentSiteId());

this.currentSite = this.sitesProvider.getCurrentSite();
Expand Down Expand Up @@ -151,12 +155,9 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem

promises.push(this.coursesProvider.invalidateUserCourses().finally(() => {
// Invalidate course completion data.
promises.push(this.coursesProvider.invalidateUserCourses().finally(() => {
// Invalidate course completion data.
return this.utils.allPromises(this.courseIds.map((courseId) => {
return this.courseCompletionProvider.invalidateCourseCompletion(courseId);
}));
}));
return this.utils.allPromises(this.courseIds.map((courseId) => {
return this.courseCompletionProvider.invalidateCourseCompletion(courseId);
}));
}));

promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
Expand Down Expand Up @@ -318,6 +319,23 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
});
}

/**
* Refresh the list of courses.
*
* @return Promise resolved when done.
*/
protected async refreshCourseList(): Promise<void> {
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);

try {
await this.coursesProvider.invalidateUserCourses();
} catch (error) {
// Ignore errors.
}

await this.loadContent(true);
}

/**
* The selected courses filter have changed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import { Component, OnInit, OnDestroy, Injector, Input, OnChanges, SimpleChange } from '@angular/core';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreCoursesProvider } from '@core/courses/providers/courses';
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData } from '@core/courses/providers/courses';
import { CoreCoursesHelperProvider } from '@core/courses/providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
Expand Down Expand Up @@ -72,8 +72,12 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom

}, this.sitesProvider.getCurrentSiteId());

this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
this.refreshContent();
this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
(data: CoreCoursesMyCoursesUpdatedEventData) => {

if (this.shouldRefreshOnUpdatedEvent(data)) {
this.refreshCourseList();
}
}, this.sitesProvider.getCurrentSiteId());

super.ngOnInit();
Expand Down Expand Up @@ -130,6 +134,23 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
});
}

/**
* Refresh the list of courses.
*
* @return Promise resolved when done.
*/
protected async refreshCourseList(): Promise<void> {
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);

try {
await this.coursesProvider.invalidateUserCourses();
} catch (error) {
// Ignore errors.
}

await this.loadContent(true);
}

/**
* Initialize the prefetch icon for selected courses.
*/
Expand All @@ -146,6 +167,49 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
});
}

/**
* Whether list should be refreshed based on a EVENT_MY_COURSES_UPDATED event.
*
* @param data Event data.
* @return Whether to refresh.
*/
protected shouldRefreshOnUpdatedEvent(data: CoreCoursesMyCoursesUpdatedEventData): boolean {
if (data.action == CoreCoursesProvider.ACTION_ENROL) {
// Always update if user enrolled in a course.
return true;
}

if (data.action == CoreCoursesProvider.ACTION_VIEW && data.courseId != this.sitesProvider.getCurrentSiteHomeId() &&
this.courses[0] && data.courseId != this.courses[0].id) {
// Update list if user viewed a course that isn't the most recent one and isn't site home.
return true;
}

if (data.action == CoreCoursesProvider.ACTION_STATE_CHANGED && data.state == CoreCoursesProvider.STATE_FAVOURITE &&
this.hasCourse(data.courseId)) {
// Update list if a visible course is now favourite or unfavourite.
return true;
}

return false;
}

/**
* Check if a certain course is in the list of courses.
*
* @param courseId Course ID to search.
* @return Whether it's in the list.
*/
protected hasCourse(courseId: number): boolean {
if (!this.courses) {
return false;
}

return !!this.courses.find((course) => {
return course.id == courseId;
});
}

/**
* Prefetch all the shown courses.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import { Component, OnInit, OnDestroy, Injector, Input, OnChanges, SimpleChange } from '@angular/core';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreCoursesProvider } from '@core/courses/providers/courses';
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData } from '@core/courses/providers/courses';
import { CoreCoursesHelperProvider } from '@core/courses/providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
Expand Down Expand Up @@ -72,7 +72,12 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im

}, this.sitesProvider.getCurrentSiteId());

this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
(data: CoreCoursesMyCoursesUpdatedEventData) => {

if (this.shouldRefreshOnUpdatedEvent(data)) {
this.refreshCourseList();
}
this.refreshContent();
}, this.sitesProvider.getCurrentSiteId());

Expand Down Expand Up @@ -130,6 +135,44 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
});
}

/**
* Refresh the list of courses.
*
* @return Promise resolved when done.
*/
protected async refreshCourseList(): Promise<void> {
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);

try {
await this.coursesProvider.invalidateUserCourses();
} catch (error) {
// Ignore errors.
}

await this.loadContent(true);
}

/**
* Whether list should be refreshed based on a EVENT_MY_COURSES_UPDATED event.
*
* @param data Event data.
* @return Whether to refresh.
*/
protected shouldRefreshOnUpdatedEvent(data: CoreCoursesMyCoursesUpdatedEventData): boolean {
if (data.action == CoreCoursesProvider.ACTION_ENROL) {
// Always update if user enrolled in a course.
// New courses shouldn't be favourite by default, but just in case.
return true;
}

if (data.action == CoreCoursesProvider.ACTION_STATE_CHANGED && data.state == CoreCoursesProvider.STATE_FAVOURITE) {
// Update list when making a course favourite or not.
return true;
}

return false;
}

/**
* Initialize the prefetch icon for selected courses.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ <h2>{{ dayEvents.dayTimestamp * 1000 | coreFormatDate:"strftimedayshort" }}</h2>
<ng-container *ngFor="let event of dayEvents.events">
<a ion-item text-wrap detail-none class="core-course-module-handler item-media" (click)="action($event, event.url)" [title]="event.name">
<img item-start [src]="event.iconUrl" alt="" role="presentation" *ngIf="event.iconUrl" class="core-module-icon">
<h2><core-format-text [text]="event.name" contextLevel="module" [contextInstanceId]="event.id" [courseId]="event.course.id"></core-format-text></h2>
<p *ngIf="showCourse">
<h2><core-format-text [text]="event.name" contextLevel="module" [contextInstanceId]="event.id" [courseId]="event.course && event.course.id"></core-format-text></h2>
<p *ngIf="showCourse && event.course">
<core-format-text [text]="event.course.fullnamedisplay" contextLevel="course" [contextInstanceId]="event.course.id"></core-format-text>
</p>

Expand Down
6 changes: 4 additions & 2 deletions src/core/course/providers/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,10 @@ export class CoreCourseProvider {
if (!response.status) {
return Promise.reject(null);
} else {
this.eventsProvider.trigger(
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: courseId}, site.getId());
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
courseId: courseId,
action: CoreCoursesProvider.ACTION_VIEW,
}, site.getId());
}
});
});
Expand Down
12 changes: 9 additions & 3 deletions src/core/course/providers/options-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,17 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
*/
protected clearCoursesHandlers(courseId?: number): void {
if (courseId) {
if (!this.loaded[courseId]) {
// Don't clear if not loaded, it's probably an ongoing load and it could cause JS errors.
return;
}

this.loaded[courseId] = false;
delete this.coursesHandlers[courseId];
} else {
this.loaded = {};
this.coursesHandlers = {};
for (const courseId in this.coursesHandlers) {
this.clearCoursesHandlers(Number(courseId));
}
}
}

Expand Down Expand Up @@ -484,7 +490,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
const promises = [],
courseData = this.coursesHandlers[courseId];

if (!courseData) {
if (!courseData || !courseData.enabledHandlers) {
return Promise.resolve();
}

Expand Down
18 changes: 14 additions & 4 deletions src/core/courses/components/course-progress/course-progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,13 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
// We should use null to unset the preference.
this.userProvider.updateUserPreference('block_myoverview_hidden_course_' + this.course.id, hide ? 1 : null).then(() => {
this.course.hidden = hide;
this.eventsProvider.trigger(
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
courseId: this.course.id,
course: this.course,
action: CoreCoursesProvider.ACTION_STATE_CHANGED,
state: CoreCoursesProvider.STATE_HIDDEN,
value: hide,
}, this.sitesProvider.getCurrentSiteId());
}).catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'Error changing course visibility.');
Expand All @@ -239,8 +244,13 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {

this.coursesProvider.setFavouriteCourse(this.course.id, favourite).then(() => {
this.course.isfavourite = favourite;
this.eventsProvider.trigger(
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
courseId: this.course.id,
course: this.course,
action: CoreCoursesProvider.ACTION_STATE_CHANGED,
state: CoreCoursesProvider.STATE_FAVOURITE,
value: favourite,
}, this.sitesProvider.getCurrentSiteId());
}).catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'Error changing course favourite attribute.');
Expand Down
11 changes: 8 additions & 3 deletions src/core/courses/components/my-courses/my-courses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Searchbar } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreCoursesProvider } from '../../providers/courses';
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData } from '../../providers/courses';
import { CoreCoursesHelperProvider } from '../../providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
Expand Down Expand Up @@ -63,8 +63,13 @@ export class CoreCoursesMyCoursesComponent implements OnInit, OnDestroy {
this.coursesLoaded = true;
});

this.myCoursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
this.fetchCourses();
// Update list if user enrols in a course.
this.myCoursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
(data: CoreCoursesMyCoursesUpdatedEventData) => {

if (data.action == CoreCoursesProvider.ACTION_ENROL) {
this.fetchCourses();
}
}, this.sitesProvider.getCurrentSiteId());

// Refresh the enabled flags if site is updated.
Expand Down
7 changes: 5 additions & 2 deletions src/core/courses/pages/course-preview/course-preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,11 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
this.waitForEnrolled(true).then(() => {
this.refreshData().finally(() => {
// My courses have been updated, trigger event.
this.eventsProvider.trigger(
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
this.eventsProvider.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
courseId: this.course.id,
course: this.course,
action: CoreCoursesProvider.ACTION_ENROL,
}, this.sitesProvider.getCurrentSiteId());
});
});
}).catch((error) => {
Expand Down
20 changes: 20 additions & 0 deletions src/core/courses/providers/courses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider, CoreSitesReadingStrategy } from '@providers/sites';
import { CoreSite } from '@classes/site';

/**
* Data sent to the EVENT_MY_COURSES_UPDATED.
*/
export type CoreCoursesMyCoursesUpdatedEventData = {
action: string; // Action performed.
courseId?: number; // Course ID affected (if any).
course?: any; // Course affected (if any).
state?: string; // Only for ACTION_STATE_CHANGED. The state that changed (hidden, favourite).
value?: boolean; // The new value for the state changed.
};

/**
* Service that provides some features regarding lists of courses and categories.
*/
Expand All @@ -30,6 +41,15 @@ export class CoreCoursesProvider {
static EVENT_MY_COURSES_REFRESHED = 'courses_my_courses_refreshed';
static EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED = 'dashboard_download_enabled_changed';

// Actions for event EVENT_MY_COURSES_UPDATED.
static ACTION_ENROL = 'enrol'; // User enrolled in a course.
static ACTION_STATE_CHANGED = 'state_changed'; // Course state changed (hidden, favourite).
static ACTION_VIEW = 'view'; // Course viewed.

// Possible states changed.
static STATE_HIDDEN = 'hidden';
static STATE_FAVOURITE = 'favourite';

protected ROOT_CACHE_KEY = 'mmCourses:';
protected logger;
protected userCoursesIds: {[id: number]: boolean}; // Use an object to make it faster to search.
Expand Down