Merge pull request #1850 from sammarshallou/MOBILE-2906
MOBILE-2906 Add course option type that appears in menumain
commit
839fe09fa7
|
@ -15,6 +15,7 @@
|
|||
<core-context-menu-item *ngIf="displayEnableDownload" [priority]="2000" [content]="'core.settings.showdownloadoptions' | translate" (action)="toggleDownload()" [iconAction]="downloadEnabledIcon"></core-context-menu-item>
|
||||
<core-context-menu-item [hidden]="!downloadCourseEnabled" [priority]="1900" [content]="prefetchCourseData.title | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||
<core-context-menu-item [priority]="1800" [content]="'core.course.coursesummary' | translate" (action)="openCourseSummary()" iconAction="fa-graduation-cap"></core-context-menu-item>
|
||||
<core-context-menu-item *ngFor="let item of courseMenuHandlers" [priority]="item.priority" (action)="openMenuItem(item)" [content]="item.data.title | translate" [iconAction]="item.data.icon" [class]="item.data.class"></core-context-menu-item>
|
||||
</core-context-menu>
|
||||
</core-navbar-buttons>
|
||||
<ion-content #courseSectionContent>
|
||||
|
|
|
@ -24,7 +24,8 @@ import { CoreCourseProvider } from '../../providers/course';
|
|||
import { CoreCourseHelperProvider } from '../../providers/helper';
|
||||
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '../../providers/module-prefetch-delegate';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay } from '../../providers/options-delegate';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay,
|
||||
CoreCourseOptionsMenuHandlerToDisplay } from '../../providers/options-delegate';
|
||||
import { CoreCourseSyncProvider } from '../../providers/sync';
|
||||
import { CoreCourseFormatComponent } from '../../components/format/format';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
|
@ -49,6 +50,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
sectionId: number;
|
||||
sectionNumber: number;
|
||||
courseHandlers: CoreCourseOptionsHandlerToDisplay[];
|
||||
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
||||
dataLoaded: boolean;
|
||||
downloadEnabled: boolean;
|
||||
downloadEnabledIcon = 'square-outline'; // Disabled by default.
|
||||
|
@ -301,6 +303,11 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
}
|
||||
}));
|
||||
|
||||
// Load the course menu handlers.
|
||||
promises.push(this.courseOptionsDelegate.getMenuHandlersToDisplay(this.injector, this.course).then((handlers) => {
|
||||
this.courseMenuHandlers = handlers;
|
||||
}));
|
||||
|
||||
// Load the course format options when course completion is enabled to show completion progress on sections.
|
||||
if (this.course.enablecompletion && this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||
promises.push(this.coursesProvider.getCourseByField('id', this.course.id).catch(() => {
|
||||
|
@ -417,7 +424,8 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
* Prefetch the whole course.
|
||||
*/
|
||||
prefetchCourse(): void {
|
||||
this.courseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course, this.sections, this.courseHandlers)
|
||||
this.courseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course, this.sections,
|
||||
this.courseHandlers, this.courseMenuHandlers)
|
||||
.then(() => {
|
||||
if (this.downloadEnabled) {
|
||||
// Recalculate the status.
|
||||
|
@ -459,6 +467,16 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
this.navCtrl.push('CoreCoursesCoursePreviewPage', {course: this.course, avoidOpenCourse: true});
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a menu item registered to the delegate.
|
||||
*
|
||||
* @param {CoreCourseMenuHandlerToDisplay} item Item to open
|
||||
*/
|
||||
openMenuItem(item: CoreCourseOptionsMenuHandlerToDisplay): void {
|
||||
const params = Object.assign({ course: this.course}, item.data.pageParams);
|
||||
this.navCtrl.push(item.data.page, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page destroyed.
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,8 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay } from './options-delegate';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay,
|
||||
CoreCourseOptionsMenuHandlerToDisplay } from './options-delegate';
|
||||
import { CoreSiteHomeProvider } from '@core/sitehome/providers/sitehome';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreCourseProvider } from './course';
|
||||
|
@ -270,10 +271,11 @@ export class CoreCourseHelperProvider {
|
|||
* @param {any} course Course to prefetch.
|
||||
* @param {any[]} [sections] List of course sections.
|
||||
* @param {CoreCourseOptionsHandlerToDisplay[]} courseHandlers List of course handlers.
|
||||
* @param {CoreCourseOptionsMenuHandlerToDisplay[]} menuHandlers List of course menu handlers.
|
||||
* @return {Promise<boolean>} Promise resolved when the download finishes, rejected if an error occurs or the user cancels.
|
||||
*/
|
||||
confirmAndPrefetchCourse(data: any, course: any, sections?: any[], courseHandlers?: CoreCourseOptionsHandlerToDisplay[])
|
||||
: Promise<boolean> {
|
||||
confirmAndPrefetchCourse(data: any, course: any, sections?: any[], courseHandlers?: CoreCourseOptionsHandlerToDisplay[],
|
||||
menuHandlers?: CoreCourseOptionsMenuHandlerToDisplay[]): Promise<boolean> {
|
||||
|
||||
const initialIcon = data.prefetchCourseIcon,
|
||||
initialTitle = data.title,
|
||||
|
@ -295,15 +297,23 @@ export class CoreCourseHelperProvider {
|
|||
// Confirm the download.
|
||||
return this.confirmDownloadSizeSection(course.id, undefined, sections, true).then(() => {
|
||||
// User confirmed, get the course handlers if needed.
|
||||
if (courseHandlers) {
|
||||
promise = Promise.resolve(courseHandlers);
|
||||
} else {
|
||||
promise = this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course);
|
||||
const subPromises = [];
|
||||
if (!courseHandlers) {
|
||||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course)
|
||||
.then((cHandlers) => {
|
||||
courseHandlers = cHandlers;
|
||||
}));
|
||||
}
|
||||
if (!menuHandlers) {
|
||||
subPromises.push(this.courseOptionsDelegate.getMenuHandlersToDisplay(this.injector, course)
|
||||
.then((mHandlers) => {
|
||||
menuHandlers = mHandlers;
|
||||
}));
|
||||
}
|
||||
|
||||
return promise.then((handlers: CoreCourseOptionsHandlerToDisplay[]) => {
|
||||
return Promise.all(subPromises).then(() => {
|
||||
// Now we have all the data, download the course.
|
||||
return this.prefetchCourse(course, sections, handlers, siteId);
|
||||
return this.prefetchCourse(course, sections, courseHandlers, menuHandlers, siteId);
|
||||
}).then(() => {
|
||||
// Download successful.
|
||||
return true;
|
||||
|
@ -338,6 +348,7 @@ export class CoreCourseHelperProvider {
|
|||
const subPromises = [];
|
||||
let sections,
|
||||
handlers,
|
||||
menuHandlers,
|
||||
success = true;
|
||||
|
||||
// Get the sections and the handlers.
|
||||
|
@ -347,9 +358,12 @@ export class CoreCourseHelperProvider {
|
|||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course).then((cHandlers) => {
|
||||
handlers = cHandlers;
|
||||
}));
|
||||
subPromises.push(this.courseOptionsDelegate.getMenuHandlersToDisplay(this.injector, course).then((mHandlers) => {
|
||||
menuHandlers = mHandlers;
|
||||
}));
|
||||
|
||||
promises.push(Promise.all(subPromises).then(() => {
|
||||
return this.prefetchCourse(course, sections, handlers, siteId);
|
||||
return this.prefetchCourse(course, sections, handlers, menuHandlers, siteId);
|
||||
}).catch((error) => {
|
||||
success = false;
|
||||
|
||||
|
@ -1187,11 +1201,12 @@ export class CoreCourseHelperProvider {
|
|||
* @param {any} course The course to prefetch.
|
||||
* @param {any[]} sections List of course sections.
|
||||
* @param {CoreCourseOptionsHandlerToDisplay[]} courseHandlers List of course options handlers.
|
||||
* @param {CoreCourseOptionsMenuHandlerToDisplay[]} courseMenuHandlers List of course menu handlers.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise} Promise resolved when the download finishes.
|
||||
*/
|
||||
prefetchCourse(course: any, sections: any[], courseHandlers: CoreCourseOptionsHandlerToDisplay[], siteId?: string)
|
||||
: Promise<any> {
|
||||
prefetchCourse(course: any, sections: any[], courseHandlers: CoreCourseOptionsHandlerToDisplay[],
|
||||
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[], siteId?: string): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
if (this.courseDwnPromises[siteId] && this.courseDwnPromises[siteId][course.id]) {
|
||||
|
@ -1220,6 +1235,11 @@ export class CoreCourseHelperProvider {
|
|||
promises.push(handler.prefetch(course));
|
||||
}
|
||||
});
|
||||
courseMenuHandlers.forEach((handler) => {
|
||||
if (handler.prefetch) {
|
||||
promises.push(handler.prefetch(course));
|
||||
}
|
||||
});
|
||||
|
||||
// Prefetch other data needed to render the course.
|
||||
if (this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||
|
|
|
@ -31,6 +31,12 @@ export interface CoreCourseOptionsHandler extends CoreDelegateHandler {
|
|||
*/
|
||||
priority: number;
|
||||
|
||||
/**
|
||||
* True if this handler should appear in menu rather than as a tab.
|
||||
* @type {boolean}
|
||||
*/
|
||||
isMenuHandler?: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the handler is enabled for a certain course.
|
||||
*
|
||||
|
@ -70,6 +76,21 @@ export interface CoreCourseOptionsHandler extends CoreDelegateHandler {
|
|||
prefetch?(course: any): Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface that course options handlers implement if they appear in the menu rather than as a tab.
|
||||
*/
|
||||
export interface CoreCourseOptionsMenuHandler extends CoreCourseOptionsHandler {
|
||||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsMenuHandlerData|Promise<CoreCourseOptionsMenuHandlerData>} Data or promise resolved with data.
|
||||
*/
|
||||
getMenuDisplayData(injector: Injector, courseId: number):
|
||||
CoreCourseOptionsMenuHandlerData | Promise<CoreCourseOptionsMenuHandlerData>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data needed to render a course handler. It's returned by the handler.
|
||||
*/
|
||||
|
@ -99,6 +120,41 @@ export interface CoreCourseOptionsHandlerData {
|
|||
componentData?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data needed to render a course menu handler. It's returned by the handler.
|
||||
*/
|
||||
export interface CoreCourseOptionsMenuHandlerData {
|
||||
/**
|
||||
* Title to display for the handler.
|
||||
* @type {string}
|
||||
*/
|
||||
title: string;
|
||||
|
||||
/**
|
||||
* Class to add to the displayed handler.
|
||||
* @type {string}
|
||||
*/
|
||||
class?: string;
|
||||
|
||||
/**
|
||||
* Name of the page to load for the handler.
|
||||
* @type {string}
|
||||
*/
|
||||
page: string;
|
||||
|
||||
/**
|
||||
* Params to pass to the page (other than 'course' which is always sent).
|
||||
* @type {any}
|
||||
*/
|
||||
pageParams?: any;
|
||||
|
||||
/**
|
||||
* Name of the icon to display for the handler.
|
||||
* @type {string}
|
||||
*/
|
||||
icon: string; // Name of the icon to display in the tab.
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by the delegate for each handler.
|
||||
*/
|
||||
|
@ -130,6 +186,37 @@ export interface CoreCourseOptionsHandlerToDisplay {
|
|||
prefetch?(course: any): Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional data returned if it is a menu item.
|
||||
*/
|
||||
export interface CoreCourseOptionsMenuHandlerToDisplay {
|
||||
/**
|
||||
* Data to display.
|
||||
* @type {CoreCourseOptionsMenuHandlerData}
|
||||
*/
|
||||
data: CoreCourseOptionsMenuHandlerData;
|
||||
|
||||
/**
|
||||
* Name of the handler, or name and sub context (AddonMessages, AddonMessages:blockContact, ...).
|
||||
* @type {string}
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The highest priority is displayed first.
|
||||
* @type {number}
|
||||
*/
|
||||
priority?: number;
|
||||
|
||||
/**
|
||||
* Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline.
|
||||
*
|
||||
* @param {any} course The course.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
prefetch?(course: any): Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service to interact with plugins to be shown in each course (participants, learning plans, ...).
|
||||
*/
|
||||
|
@ -139,7 +226,8 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
protected lastUpdateHandlersForCoursesStart: any = {};
|
||||
protected coursesHandlers: {
|
||||
[courseId: number]: {
|
||||
access?: any, navOptions?: any, admOptions?: any, deferred?: PromiseDefer, enabledHandlers?: CoreCourseOptionsHandler[]
|
||||
access?: any, navOptions?: any, admOptions?: any, deferred?: PromiseDefer,
|
||||
enabledHandlers?: CoreCourseOptionsHandler[], enabledMenuHandlers?: CoreCourseOptionsMenuHandler[]
|
||||
}
|
||||
} = {};
|
||||
|
||||
|
@ -258,6 +346,43 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
*/
|
||||
getHandlersToDisplay(injector: Injector, course: any, refresh?: boolean, isGuest?: boolean, navOptions?: any, admOptions?: any):
|
||||
Promise<CoreCourseOptionsHandlerToDisplay[]> {
|
||||
return <Promise<CoreCourseOptionsHandlerToDisplay[]>> this.getHandlersToDisplayInternal(
|
||||
false, injector, course, refresh, isGuest, navOptions, admOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of menu handlers that should be displayed for a course.
|
||||
* This function should be called only when the handlers need to be displayed, since it can call several WebServices.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {boolean} [refresh] True if it should refresh the list.
|
||||
* @param {boolean} [isGuest] Whether it's guest.
|
||||
* @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions.
|
||||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {Promise<CoreCourseOptionsMenuHandlerToDisplay[]>} Promise resolved with array of handlers.
|
||||
*/
|
||||
getMenuHandlersToDisplay(injector: Injector, course: any, refresh?: boolean, isGuest?: boolean,
|
||||
navOptions?: any, admOptions?: any): Promise<CoreCourseOptionsMenuHandlerToDisplay[]> {
|
||||
return <Promise<CoreCourseOptionsMenuHandlerToDisplay[]>> this.getHandlersToDisplayInternal(
|
||||
true, injector, course, refresh, isGuest, navOptions, admOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of menu handlers that should be displayed for a course.
|
||||
* This function should be called only when the handlers need to be displayed, since it can call several WebServices.
|
||||
*
|
||||
* @param {boolean} menu If true, gets menu handlers; false, gets tab handlers
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {boolean} refresh True if it should refresh the list.
|
||||
* @param {boolean} isGuest Whether it's guest.
|
||||
* @param {any} navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions.
|
||||
* @param {any} admOptions Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {Promise<any[]>} Promise resolved with array of handlers.
|
||||
*/
|
||||
protected getHandlersToDisplayInternal(menu: boolean, injector: Injector, course: any, refresh: boolean, isGuest: boolean,
|
||||
navOptions: any, admOptions: any): Promise<any[]> {
|
||||
course.id = parseInt(course.id, 10);
|
||||
|
||||
const accessData = {
|
||||
|
@ -278,8 +403,16 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
}).then(() => {
|
||||
const promises = [];
|
||||
|
||||
this.coursesHandlers[course.id].enabledHandlers.forEach((handler) => {
|
||||
promises.push(Promise.resolve(handler.getDisplayData(injector, course)).then((data) => {
|
||||
let handlerList;
|
||||
if (menu) {
|
||||
handlerList = this.coursesHandlers[course.id].enabledMenuHandlers;
|
||||
} else {
|
||||
handlerList = this.coursesHandlers[course.id].enabledHandlers;
|
||||
}
|
||||
|
||||
handlerList.forEach((handler) => {
|
||||
const getFunction = menu ? handler.getMenuDisplayData : handler.getDisplayData;
|
||||
promises.push(Promise.resolve(getFunction.call(handler, injector, course)).then((data) => {
|
||||
handlersToDisplay.push({
|
||||
data: data,
|
||||
priority: handler.priority,
|
||||
|
@ -444,6 +577,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
updateHandlersForCourse(courseId: number, accessData: any, navOptions?: any, admOptions?: any): Promise<any> {
|
||||
const promises = [],
|
||||
enabledForCourse = [],
|
||||
enabledForCourseMenu = [],
|
||||
siteId = this.sitesProvider.getCurrentSiteId(),
|
||||
now = Date.now();
|
||||
|
||||
|
@ -456,7 +590,11 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
promises.push(Promise.resolve(handler.isEnabledForCourse(courseId, accessData, navOptions, admOptions))
|
||||
.then((enabled) => {
|
||||
if (enabled) {
|
||||
enabledForCourse.push(handler);
|
||||
if (handler.isMenuHandler) {
|
||||
enabledForCourseMenu.push(<CoreCourseOptionsMenuHandler> handler);
|
||||
} else {
|
||||
enabledForCourse.push(handler);
|
||||
}
|
||||
} else {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
@ -476,6 +614,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
if (this.isLastUpdateCourseCall(courseId, now) && this.sitesProvider.getCurrentSiteId() === siteId) {
|
||||
// Update the coursesHandlers array with the new enabled addons.
|
||||
this.coursesHandlers[courseId].enabledHandlers = enabledForCourse;
|
||||
this.coursesHandlers[courseId].enabledMenuHandlers = enabledForCourseMenu;
|
||||
this.loaded[courseId] = true;
|
||||
|
||||
// Resolve the promise.
|
||||
|
|
Loading…
Reference in New Issue