commit
26482ea355
|
@ -1549,6 +1549,7 @@
|
||||||
"core.course.downloadcourse": "tool_mobile",
|
"core.course.downloadcourse": "tool_mobile",
|
||||||
"core.course.downloadcoursesprogressdescription": "local_moodlemobileapp",
|
"core.course.downloadcoursesprogressdescription": "local_moodlemobileapp",
|
||||||
"core.course.downloadsectionprogressdescription": "local_moodlemobileapp",
|
"core.course.downloadsectionprogressdescription": "local_moodlemobileapp",
|
||||||
|
"core.course.enddate": "moodle",
|
||||||
"core.course.errordownloadingcourse": "local_moodlemobileapp",
|
"core.course.errordownloadingcourse": "local_moodlemobileapp",
|
||||||
"core.course.errordownloadingsection": "local_moodlemobileapp",
|
"core.course.errordownloadingsection": "local_moodlemobileapp",
|
||||||
"core.course.errorgetmodule": "local_moodlemobileapp",
|
"core.course.errorgetmodule": "local_moodlemobileapp",
|
||||||
|
@ -1568,6 +1569,7 @@
|
||||||
"core.course.overriddennotice": "grades",
|
"core.course.overriddennotice": "grades",
|
||||||
"core.course.refreshcourse": "local_moodlemobileapp",
|
"core.course.refreshcourse": "local_moodlemobileapp",
|
||||||
"core.course.section": "moodle",
|
"core.course.section": "moodle",
|
||||||
|
"core.course.startdate": "moodle",
|
||||||
"core.course.thisweek": "format_weeks/currentsection",
|
"core.course.thisweek": "format_weeks/currentsection",
|
||||||
"core.course.todo": "completion",
|
"core.course.todo": "completion",
|
||||||
"core.course.useactivityonbrowser": "local_moodlemobileapp",
|
"core.course.useactivityonbrowser": "local_moodlemobileapp",
|
||||||
|
|
|
@ -32,9 +32,9 @@ const routes: Routes = [
|
||||||
loadChildren: () => import('./pages/list-mod-type/list-mod-type.module').then(m => m.CoreCourseListModTypePageModule),
|
loadChildren: () => import('./pages/list-mod-type/list-mod-type.module').then(m => m.CoreCourseListModTypePageModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':courseId/preview',
|
path: ':courseId/summary',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/preview/preview.module').then(m => m.CoreCoursePreviewPageModule),
|
import('./pages/course-summary/course-summary.module').then(m => m.CoreCourseSummaryPageModule),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"downloadcourse": "Download course",
|
"downloadcourse": "Download course",
|
||||||
"downloadcoursesprogressdescription": "Downloading courses: downloaded {{count}} out of {{total}}.",
|
"downloadcoursesprogressdescription": "Downloading courses: downloaded {{count}} out of {{total}}.",
|
||||||
"downloadsectionprogressdescription": "Downloading section: downloaded {{count}} out of {{total}}.",
|
"downloadsectionprogressdescription": "Downloading section: downloaded {{count}} out of {{total}}.",
|
||||||
|
"enddate": "Course end date",
|
||||||
"errordownloadingcourse": "Error downloading course.",
|
"errordownloadingcourse": "Error downloading course.",
|
||||||
"errordownloadingsection": "Error downloading section.",
|
"errordownloadingsection": "Error downloading section.",
|
||||||
"errorgetmodule": "Error getting activity data.",
|
"errorgetmodule": "Error getting activity data.",
|
||||||
|
@ -51,6 +52,7 @@
|
||||||
"overriddennotice": "Your final grade from this activity was manually adjusted.",
|
"overriddennotice": "Your final grade from this activity was manually adjusted.",
|
||||||
"refreshcourse": "Refresh course",
|
"refreshcourse": "Refresh course",
|
||||||
"section": "Section",
|
"section": "Section",
|
||||||
|
"startdate": "Course start date",
|
||||||
"thisweek": "This week",
|
"thisweek": "This week",
|
||||||
"todo": "To do",
|
"todo": "To do",
|
||||||
"useactivityonbrowser": "You can still use it using your device's web browser.",
|
"useactivityonbrowser": "You can still use it using your device's web browser.",
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
<core-navbar-buttons slot="end">
|
<core-navbar-buttons slot="end">
|
||||||
<core-context-menu>
|
|
||||||
<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>
|
</core-navbar-buttons>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-refresher slot="fixed" [disabled]="!dataLoaded || !displayRefresher" (ionRefresh)="doRefresh($event.target)">
|
<ion-refresher slot="fixed" [disabled]="!dataLoaded || !displayRefresher" (ionRefresh)="doRefresh($event.target)">
|
||||||
|
|
|
@ -29,10 +29,7 @@ import {
|
||||||
} from '@features/course/services/course-helper';
|
} from '@features/course/services/course-helper';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
import {
|
import { CoreCourseOptionsMenuHandlerToDisplay } from '@features/course/services/course-options-delegate';
|
||||||
CoreCourseOptionsDelegate,
|
|
||||||
CoreCourseOptionsMenuHandlerToDisplay,
|
|
||||||
} from '@features/course/services/course-options-delegate';
|
|
||||||
import { CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync';
|
import { CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync';
|
||||||
import { CoreCourseFormatComponent } from '../../components/format/format';
|
import { CoreCourseFormatComponent } from '../../components/format/format';
|
||||||
import {
|
import {
|
||||||
|
@ -69,7 +66,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
protected syncObserver?: CoreEventObserver;
|
protected syncObserver?: CoreEventObserver;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
protected modulesHaveCompletion = false;
|
protected modulesHaveCompletion = false;
|
||||||
protected isGuest = false;
|
|
||||||
protected debouncedUpdateCachedCompletion?: () => void; // Update the cached completion after a certain time.
|
protected debouncedUpdateCachedCompletion?: () => void; // Update the cached completion after a certain time.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,7 +85,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
this.sectionId = CoreNavigator.getRouteNumberParam('sectionId');
|
this.sectionId = CoreNavigator.getRouteNumberParam('sectionId');
|
||||||
this.sectionNumber = CoreNavigator.getRouteNumberParam('sectionNumber');
|
this.sectionNumber = CoreNavigator.getRouteNumberParam('sectionNumber');
|
||||||
this.moduleId = CoreNavigator.getRouteNumberParam('moduleId');
|
this.moduleId = CoreNavigator.getRouteNumberParam('moduleId');
|
||||||
this.isGuest = !!CoreNavigator.getRouteBooleanParam('isGuest');
|
|
||||||
|
|
||||||
this.debouncedUpdateCachedCompletion = CoreUtils.debounce(() => {
|
this.debouncedUpdateCachedCompletion = CoreUtils.debounce(() => {
|
||||||
if (this.modulesHaveCompletion) {
|
if (this.modulesHaveCompletion) {
|
||||||
|
@ -184,7 +179,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.loadSections(refresh),
|
this.loadSections(refresh),
|
||||||
this.loadMenuHandlers(refresh),
|
|
||||||
this.loadCourseFormatOptions(),
|
this.loadCourseFormatOptions(),
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -248,16 +242,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
this.displayRefresher = CoreCourseFormatDelegate.displayRefresher(this.course, this.sections);
|
this.displayRefresher = CoreCourseFormatDelegate.displayRefresher(this.course, this.sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the course menu handlers.
|
|
||||||
*
|
|
||||||
* @param refresh If it's refreshing content.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async loadMenuHandlers(refresh?: boolean): Promise<void> {
|
|
||||||
this.courseMenuHandlers = await CoreCourseOptionsDelegate.getMenuHandlersToDisplay(this.course, refresh, this.isGuest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load course format options if needed.
|
* Load course format options if needed.
|
||||||
*
|
*
|
||||||
|
@ -379,16 +363,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens a menu item registered to the delegate.
|
|
||||||
*
|
|
||||||
* @param item Item to open
|
|
||||||
*/
|
|
||||||
openMenuItem(item: CoreCourseOptionsMenuHandlerToDisplay): void {
|
|
||||||
const params = Object.assign({ course: this.course }, item.data.pageParams);
|
|
||||||
CoreNavigator.navigateToSitePath(item.data.page, { params });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page destroyed.
|
* Page destroyed.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
{{'core.course.coursesummary' | translate}}
|
{{'core.course.coursesummary' | translate}}
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
<ion-buttons slot="end" *ngIf="isModal">
|
||||||
|
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||||
|
<ion-icon slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
|
@ -15,12 +20,10 @@
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="dataLoaded">
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
<div *ngIf="courseImageUrl" class="core-course-thumb-parallax">
|
<div *ngIf="courseImageUrl" class="core-course-thumb">
|
||||||
<div class="core-course-thumb">
|
<img [src]="courseImageUrl" core-external-content alt="" />
|
||||||
<img [src]="courseImageUrl" core-external-content alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="core-course-thumb-parallax-content" *ngIf="course">
|
<ng-container *ngIf="course">
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p *ngIf="course.categoryname">
|
<p *ngIf="course.categoryname">
|
||||||
|
@ -31,15 +34,28 @@
|
||||||
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h2>
|
</h2>
|
||||||
<p *ngIf="course.startdate">
|
|
||||||
{{course.startdate * 1000 | coreFormatDate:"strftimedatefullshort" }}
|
|
||||||
<span *ngIf="course.enddate"> - {{course.enddate * 1000 | coreFormatDate:"strftimedatefullshort" }}</span>
|
|
||||||
</p>
|
|
||||||
<div class="core-course-progress" *ngIf="progress !== undefined">
|
<div class="core-course-progress" *ngIf="progress !== undefined">
|
||||||
<core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress">
|
<core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress">
|
||||||
</core-progress-bar>
|
</core-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="course.startdate || course.enddate" class="core-course-dates">
|
||||||
|
<p *ngIf="course.startdate">
|
||||||
|
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
||||||
|
<strong>{{ 'core.course.startdate' | translate }}: </strong> {{ course.startdate * 1000 |
|
||||||
|
coreFormatDate:'strftimedatefullshort' }}
|
||||||
|
</p>
|
||||||
|
<p *ngIf="course.enddate">
|
||||||
|
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
||||||
|
<strong>{{ 'core.course.enddate' | translate }}: </strong> {{ course.enddate * 1000 |
|
||||||
|
coreFormatDate:'strftimedatefullshort' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
<ion-button fill="clear" [href]="courseUrl" core-link [showBrowserWarning]="false" color="dark"
|
||||||
|
[attr.aria-label]="'core.openinbrowser' | translate" slot="end">
|
||||||
|
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="course.summary" detail="false">
|
<ion-item class="ion-text-wrap" *ngIf="course.summary" detail="false">
|
||||||
|
@ -55,7 +71,7 @@
|
||||||
<ion-list *ngIf="course.contacts && course.contacts.length">
|
<ion-list *ngIf="course.contacts && course.contacts.length">
|
||||||
<ion-item-divider class="ion-text-wrap">
|
<ion-item-divider class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.teachers' | translate }}</h2>
|
<p class="item-heading">{{ 'core.teachers' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item button class="ion-text-wrap" *ngFor="let contact of course.contacts" core-user-link [userId]="contact.id"
|
<ion-item button class="ion-text-wrap" *ngFor="let contact of course.contacts" core-user-link [userId]="contact.id"
|
||||||
|
@ -87,59 +103,48 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
<!-- Enrol -->
|
|
||||||
<ng-container *ngIf="!isEnrolled">
|
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let instance of selfEnrolInstances">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ instance.name }}</p>
|
|
||||||
<ion-button expand="block" class="ion-margin-top" (click)="selfEnrolClicked(instance.id)">
|
|
||||||
{{ 'core.courses.enrolme' | translate }}
|
|
||||||
</ion-button>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="paypalEnabled">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.courses.otherenrolments' | translate }}</p>
|
|
||||||
<ion-button expand="block" class="ion-margin-top" (click)="browserEnrol()">
|
|
||||||
{{ 'core.courses.completeenrolmentbrowser' | translate }}
|
|
||||||
</ion-button>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item *ngIf="!selfEnrolInstances.length && !paypalEnabled">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.courses.notenrollable' | translate }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ion-button class="ion-margin" *ngIf="canAccessCourse && downloadCourseEnabled" (click)="prefetchCourse()" expand="block"
|
|
||||||
[attr.aria-label]="prefetchCourseData.statusTranslatable | translate">
|
|
||||||
<ion-icon *ngIf="(prefetchCourseData.status != statusDownloaded) && !prefetchCourseData.loading"
|
|
||||||
[name]="prefetchCourseData.icon" slot="start" aria-hidden="true">
|
|
||||||
</ion-icon>
|
|
||||||
<ion-icon *ngIf="(prefetchCourseData.status == statusDownloaded) && !prefetchCourseData.loading" slot="start"
|
|
||||||
[name]="prefetchCourseData.icon" color="success" aria-hidden="true" role="status">
|
|
||||||
</ion-icon>
|
|
||||||
<ion-spinner *ngIf="prefetchCourseData.loading" slot="start" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
|
||||||
<ion-label *ngIf="prefetchCourseData.status != statusDownloaded">{{ 'core.course.downloadcourse' | translate }}</ion-label>
|
|
||||||
<ion-label *ngIf="prefetchCourseData.status == statusDownloaded">{{ 'core.course.refreshcourse' | translate }}</ion-label>
|
|
||||||
</ion-button>
|
|
||||||
|
|
||||||
<ion-button class="ion-margin" (click)="openCourse()" *ngIf="!avoidOpenCourse && canAccessCourse" expand="block">
|
|
||||||
<ion-icon name="fas-briefcase" slot="start" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>
|
|
||||||
{{ 'core.course' | translate }}
|
|
||||||
</ion-label>
|
|
||||||
</ion-button>
|
|
||||||
|
|
||||||
<ion-button class="ion-margin" [href]="courseUrl" core-link [showBrowserWarning]="false" expand="block">
|
|
||||||
<ion-icon name="fas-external-link-alt" slot="start" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>
|
|
||||||
{{ 'core.openinbrowser' | translate }}
|
|
||||||
</ion-label>
|
|
||||||
</ion-button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-footer *ngIf="course && dataLoaded">
|
||||||
|
<!-- Enrol -->
|
||||||
|
<ion-card *ngIf="!isEnrolled">
|
||||||
|
<ion-item class="ion-text-wrap" *ngFor="let instance of selfEnrolInstances">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ instance.name }}</p>
|
||||||
|
<ion-button expand="block" class="ion-margin-top" (click)="selfEnrolClicked(instance.id)">
|
||||||
|
{{ 'core.courses.enrolme' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="paypalEnabled">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.courses.otherenrolments' | translate }}</p>
|
||||||
|
<ion-button expand="block" class="ion-margin-top" (click)="browserEnrol()">
|
||||||
|
{{ 'core.courses.completeenrolmentbrowser' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item *ngIf="!selfEnrolInstances.length && !paypalEnabled">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.courses.notenrollable' | translate }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
|
||||||
|
<ng-container *ngIf="canAccessCourse">
|
||||||
|
<ion-button class="ion-margin" *ngFor="let item of courseMenuHandlers" (click)="openMenuItem(item)" [class]="item.data.class"
|
||||||
|
expand="block">
|
||||||
|
<ion-icon *ngIf="item.data.icon" [name]="item.data.icon" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>{{item.data.title | translate }}</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ion-button class="ion-margin" (click)="openCourse()" *ngIf="!isModal && canAccessCourse" expand="block">
|
||||||
|
<ion-icon name="fas-briefcase" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ 'core.course' | translate }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
</ion-footer>
|
|
@ -16,23 +16,30 @@ import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { CoreCoursePreviewPage } from './preview.page';
|
import { CoreCourseSummaryPage } from './course-summary';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: CoreCoursePreviewPage,
|
component: CoreCourseSummaryPage,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CoreSharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
CoreCourseSummaryPage,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class CoreCoursePreviewPageComponentModule { }
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forChild(routes),
|
RouterModule.forChild(routes),
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
],
|
CoreCoursePreviewPageComponentModule,
|
||||||
declarations: [
|
|
||||||
CoreCoursePreviewPage,
|
|
||||||
],
|
],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
export class CoreCoursePreviewPageModule { }
|
export class CoreCourseSummaryPageModule { }
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import '~theme/globals.scss';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
.core-course-thumb {
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
max-height: 35vh;
|
||||||
|
z-index: -1;
|
||||||
|
overflow: hidden;
|
||||||
|
border-bottom: 1px solid var(--stroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.core-customfieldvalue core-format-text {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.core-course-dates {
|
||||||
|
background: var(--light);
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
@include margin-horizontal(null, 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit, Input } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
import { IonRefresher } from '@ionic/angular';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -26,11 +26,12 @@ import {
|
||||||
CoreCoursesProvider,
|
CoreCoursesProvider,
|
||||||
CoreEnrolledCourseData,
|
CoreEnrolledCourseData,
|
||||||
} from '@features/courses/services/courses';
|
} from '@features/courses/services/courses';
|
||||||
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
|
import {
|
||||||
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
|
CoreCourseOptionsDelegate,
|
||||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
CoreCourseOptionsMenuHandlerToDisplay,
|
||||||
import { NgZone, Platform, Translate } from '@singletons';
|
} from '@features/course/services/course-options-delegate';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||||
|
import { ModalController, NgZone, Platform, Translate } from '@singletons';
|
||||||
import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password';
|
import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
@ -38,36 +39,31 @@ import { CoreCourseWithImageAndColor } from '@features/courses/services/courses-
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that allows "previewing" a course and enrolling in it if enabled and not enrolled.
|
* Page that shows the summary of a course including buttons to enrol and other available options.
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-core-course-preview',
|
selector: 'page-core-course-summary',
|
||||||
templateUrl: 'preview.html',
|
templateUrl: 'course-summary.html',
|
||||||
styleUrls: ['preview.scss'],
|
styleUrls: ['course-summary.scss'],
|
||||||
})
|
})
|
||||||
export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@Input() course?: CoreCourseSummaryData;
|
||||||
|
@Input() courseId = 0;
|
||||||
|
|
||||||
course?: CoreCourseSummaryData;
|
|
||||||
isEnrolled = false;
|
isEnrolled = false;
|
||||||
canAccessCourse = true;
|
canAccessCourse = true;
|
||||||
selfEnrolInstances: CoreCourseEnrolmentMethod[] = [];
|
selfEnrolInstances: CoreCourseEnrolmentMethod[] = [];
|
||||||
paypalEnabled = false;
|
paypalEnabled = false;
|
||||||
dataLoaded = false;
|
dataLoaded = false;
|
||||||
avoidOpenCourse = false;
|
isModal = false;
|
||||||
prefetchCourseData: CorePrefetchStatusInfo = {
|
|
||||||
icon: '',
|
|
||||||
statusTranslatable: 'core.loading',
|
|
||||||
status: '',
|
|
||||||
loading: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
statusDownloaded = CoreConstants.DOWNLOADED;
|
|
||||||
|
|
||||||
downloadCourseEnabled: boolean;
|
|
||||||
courseUrl = '';
|
courseUrl = '';
|
||||||
courseImageUrl?: string;
|
courseImageUrl?: string;
|
||||||
progress?: number;
|
progress?: number;
|
||||||
|
|
||||||
|
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
||||||
|
|
||||||
protected isGuestEnabled = false;
|
protected isGuestEnabled = false;
|
||||||
protected useGuestAccess = false;
|
protected useGuestAccess = false;
|
||||||
protected guestInstanceId?: number;
|
protected guestInstanceId?: number;
|
||||||
|
@ -76,22 +72,10 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
protected enrolUrl = '';
|
protected enrolUrl = '';
|
||||||
protected pageDestroyed = false;
|
protected pageDestroyed = false;
|
||||||
protected courseStatusObserver?: CoreEventObserver;
|
protected courseStatusObserver?: CoreEventObserver;
|
||||||
protected courseId!: number;
|
|
||||||
protected appResumeSubscription: Subscription;
|
protected appResumeSubscription: Subscription;
|
||||||
protected waitingForBrowserEnrol = false;
|
protected waitingForBrowserEnrol = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
|
||||||
|
|
||||||
if (this.downloadCourseEnabled) {
|
|
||||||
// Listen for status change in course.
|
|
||||||
this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data) => {
|
|
||||||
if (data.courseId == this.courseId || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) {
|
|
||||||
this.updateCourseStatus(data.status);
|
|
||||||
}
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh the view when the app is resumed.
|
// Refresh the view when the app is resumed.
|
||||||
this.appResumeSubscription = Platform.resume.subscribe(() => {
|
this.appResumeSubscription = Platform.resume.subscribe(() => {
|
||||||
if (!this.waitingForBrowserEnrol || !this.dataLoaded) {
|
if (!this.waitingForBrowserEnrol || !this.dataLoaded) {
|
||||||
|
@ -111,47 +95,29 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
try {
|
if (!this.courseId) {
|
||||||
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
// Opened as a page.
|
||||||
} catch (error) {
|
try {
|
||||||
CoreDomUtils.showErrorModal(error);
|
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||||
CoreNavigator.back();
|
} catch (error) {
|
||||||
|
CoreDomUtils.showErrorModal(error);
|
||||||
|
CoreNavigator.back();
|
||||||
|
this.closeModal(); // Just in case.
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.course = CoreNavigator.getRouteParam('course');
|
||||||
|
} else {
|
||||||
|
// Opened as a modal.
|
||||||
|
this.isModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.avoidOpenCourse = !!CoreNavigator.getRouteBooleanParam('avoidOpenCourse');
|
|
||||||
this.course = CoreNavigator.getRouteParam('course');
|
|
||||||
|
|
||||||
const currentSiteUrl = CoreSites.getRequiredCurrentSite().getURL();
|
const currentSiteUrl = CoreSites.getRequiredCurrentSite().getURL();
|
||||||
this.enrolUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'enrol/index.php?id=' + this.courseId);
|
this.enrolUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'enrol/index.php?id=' + this.courseId);
|
||||||
this.courseUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.courseId);
|
this.courseUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.courseId);
|
||||||
|
|
||||||
try {
|
await this.getCourse();
|
||||||
await this.getCourse();
|
|
||||||
} finally {
|
|
||||||
if (this.downloadCourseEnabled) {
|
|
||||||
|
|
||||||
// Determine course prefetch icon.
|
|
||||||
this.prefetchCourseData = await CoreCourseHelper.getCourseStatusIconAndTitle(this.courseId);
|
|
||||||
|
|
||||||
if (this.prefetchCourseData.loading) {
|
|
||||||
// Course is being downloaded. Get the download promise.
|
|
||||||
const promise = CoreCourseHelper.getCourseDownloadPromise(this.courseId);
|
|
||||||
if (promise) {
|
|
||||||
// There is a download promise. If it fails, show an error.
|
|
||||||
promise.catch((error) => {
|
|
||||||
if (!this.pageDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// No download, this probably means that the app was closed while downloading. Set previous status.
|
|
||||||
CoreCourse.setCoursePreviousStatus(this.courseId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,8 +150,10 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience function to get course. We use this to determine if a user can see the course or not.
|
* Convenience function to get course. We use this to determine if a user can see the course or not.
|
||||||
|
*
|
||||||
|
* @param refresh If it's refreshing content.
|
||||||
*/
|
*/
|
||||||
protected async getCourse(): Promise<void> {
|
protected async getCourse(refresh = false): Promise<void> {
|
||||||
// Get course enrolment methods.
|
// Get course enrolment methods.
|
||||||
this.selfEnrolInstances = [];
|
this.selfEnrolInstances = [];
|
||||||
|
|
||||||
|
@ -262,16 +230,33 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
this.progress = this.course.progress;
|
this.progress = this.course.progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.loadMenuHandlers(refresh);
|
||||||
|
|
||||||
this.dataLoaded = true;
|
this.dataLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the course menu handlers.
|
||||||
|
*
|
||||||
|
* @param refresh If it's refreshing content.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadMenuHandlers(refresh?: boolean): Promise<void> {
|
||||||
|
if (!this.course) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.courseMenuHandlers =
|
||||||
|
await CoreCourseOptionsDelegate.getMenuHandlersToDisplay(this.course, refresh, this.useGuestAccess);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the course.
|
* Open the course.
|
||||||
*
|
*
|
||||||
* @param replaceCurrentPage If current place should be replaced in the navigation stack.
|
* @param replaceCurrentPage If current place should be replaced in the navigation stack.
|
||||||
*/
|
*/
|
||||||
openCourse(replaceCurrentPage = false): void {
|
openCourse(replaceCurrentPage = false): void {
|
||||||
if (!this.canAccessCourse || !this.course || this.avoidOpenCourse) {
|
if (!this.canAccessCourse || !this.course || this.isModal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,20 +388,6 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the course status icon and title.
|
|
||||||
*
|
|
||||||
* @param status Status to show.
|
|
||||||
*/
|
|
||||||
protected updateCourseStatus(status: string): void {
|
|
||||||
const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status);
|
|
||||||
|
|
||||||
this.prefetchCourseData.status = statusData.status;
|
|
||||||
this.prefetchCourseData.icon = statusData.icon;
|
|
||||||
this.prefetchCourseData.statusTranslatable = statusData.statusTranslatable;
|
|
||||||
this.prefetchCourseData.loading = statusData.loading;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for the user to be enrolled in the course.
|
* Wait for the user to be enrolled in the course.
|
||||||
*
|
*
|
||||||
|
@ -453,18 +424,20 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefetch the course.
|
* Opens a menu item registered to the delegate.
|
||||||
|
*
|
||||||
|
* @param item Item to open
|
||||||
*/
|
*/
|
||||||
async prefetchCourse(): Promise<void> {
|
openMenuItem(item: CoreCourseOptionsMenuHandlerToDisplay): void {
|
||||||
try {
|
const params = Object.assign({ course: this.course }, item.data.pageParams);
|
||||||
await CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course as CoreEnrolledCourseData, {
|
CoreNavigator.navigateToSitePath(item.data.page, { params });
|
||||||
isGuest: this.useGuestAccess,
|
}
|
||||||
});
|
|
||||||
} catch (error) {
|
/**
|
||||||
if (!this.pageDestroyed) {
|
* Close the modal.
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
*/
|
||||||
}
|
closeModal(): void {
|
||||||
}
|
ModalController.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -19,6 +19,7 @@ import { resolveModuleRoutes } from '@/app/app-routing.module';
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { CoreCourseIndexPage } from '.';
|
import { CoreCourseIndexPage } from '.';
|
||||||
import { COURSE_INDEX_ROUTES } from './index-routing.module';
|
import { COURSE_INDEX_ROUTES } from './index-routing.module';
|
||||||
|
import { CoreCoursePreviewPageComponentModule } from '../course-summary/course-summary.module';
|
||||||
|
|
||||||
function buildRoutes(injector: Injector): Routes {
|
function buildRoutes(injector: Injector): Routes {
|
||||||
const routes = resolveModuleRoutes(injector, COURSE_INDEX_ROUTES);
|
const routes = resolveModuleRoutes(injector, COURSE_INDEX_ROUTES);
|
||||||
|
@ -42,6 +43,7 @@ function buildRoutes(injector: Injector): Routes {
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
|
CoreCoursePreviewPageComponentModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
CoreCourseIndexPage,
|
CoreCourseIndexPage,
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { CoreNavigator } from '@services/navigator';
|
||||||
import { CONTENTS_PAGE_NAME } from '@features/course/course.module';
|
import { CONTENTS_PAGE_NAME } from '@features/course/course.module';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreCollapsibleHeaderDirective } from '@directives/collapsible-header';
|
import { CoreCollapsibleHeaderDirective } from '@directives/collapsible-header';
|
||||||
|
import { CoreCourseSummaryPage } from '../course-summary/course-summary';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the list of courses the user is enrolled in.
|
* Page that displays the list of courses the user is enrolled in.
|
||||||
|
@ -279,10 +280,13 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreNavigator.navigateToSitePath(
|
CoreDomUtils.openSideModal<void>({
|
||||||
`/course/${this.course.id}/preview`,
|
component: CoreCourseSummaryPage,
|
||||||
{ params: { course: this.course, avoidOpenCourse: true } },
|
componentProps: {
|
||||||
);
|
courseId: this.course.id,
|
||||||
|
course: this.course,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
:host {
|
|
||||||
ion-content:not(.animating) {
|
|
||||||
&::part(scroll) {
|
|
||||||
perspective: 1px;
|
|
||||||
perspective-origin: center top;
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-thumb {
|
|
||||||
transform-origin: center top;
|
|
||||||
|
|
||||||
--scroll-factor: 0.5;
|
|
||||||
--translate-z: calc(-2 * var(--scroll-factor))px;
|
|
||||||
--scale: calc(1 + var(--scroll-factor) * 2);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculated with scroll-factor: 0.5;
|
|
||||||
* translate-z: -2 * $scroll-factor px;
|
|
||||||
* scale: 1 + $scroll-factor * 2;
|
|
||||||
*/
|
|
||||||
transform: translateZ(-1px) scale(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-thumb-parallax-content {
|
|
||||||
transform: translateZ(0);
|
|
||||||
-webkit-filter: drop-shadow(0px -3px 3px rgba(var(--drop-shadow)));
|
|
||||||
filter: drop-shadow(0px -3px 3px rgba(var(--drop-shadow)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-thumb-parallax {
|
|
||||||
height: 40vw;
|
|
||||||
max-height: 35vh;
|
|
||||||
z-index: -1;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-thumb {
|
|
||||||
overflow: hidden;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.core-customfieldvalue core-format-text {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -171,7 +171,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
|
||||||
CoreCourseHelper.openCourse(this.course);
|
CoreCourseHelper.openCourse(this.course);
|
||||||
} else {
|
} else {
|
||||||
CoreNavigator.navigateToSitePath(
|
CoreNavigator.navigateToSitePath(
|
||||||
`/course/${this.course.id}/preview`,
|
`/course/${this.course.id}/summary`,
|
||||||
{ params: { course: this.course } },
|
{ params: { course: this.course } },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ export class CoreCoursesEnrolPushClickHandlerService implements CorePushNotifica
|
||||||
params.selectedTab = 'participants'; // @todo: Set this when participants is done.
|
params.selectedTab = 'participants'; // @todo: Set this when participants is done.
|
||||||
} else if (!result.enrolled) {
|
} else if (!result.enrolled) {
|
||||||
// User not enrolled anymore, open the preview page.
|
// User not enrolled anymore, open the preview page.
|
||||||
page += '/preview';
|
page += '/summary';
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreNavigator.navigateToSitePath(page, { params, siteId: notification.site });
|
await CoreNavigator.navigateToSitePath(page, { params, siteId: notification.site });
|
||||||
|
|
|
@ -79,7 +79,7 @@ export class CoreCoursesRequestPushClickHandlerService implements CorePushNotifi
|
||||||
|
|
||||||
if (!result.enrolled) {
|
if (!result.enrolled) {
|
||||||
// User not enrolled (shouldn't happen), open the preview page.
|
// User not enrolled (shouldn't happen), open the preview page.
|
||||||
page += '/preview';
|
page += '/summary';
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreNavigator.navigateToSitePath(page, { params, siteId: notification.site });
|
await CoreNavigator.navigateToSitePath(page, { params, siteId: notification.site });
|
||||||
|
|
|
@ -58,7 +58,6 @@ export class CoreMainMenuUserButtonComponent implements OnInit {
|
||||||
|
|
||||||
CoreDomUtils.openSideModal<void>({
|
CoreDomUtils.openSideModal<void>({
|
||||||
component: CoreMainMenuUserMenuComponent,
|
component: CoreMainMenuUserMenuComponent,
|
||||||
cssClass: 'core-modal-lateral',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ information provided here is intended especially for developers.
|
||||||
- CoreCourseHelperProvider.openCourse parameters changed, now it admits CoreNavigationOptions + siteId on the same object that includes Params passed to page.
|
- CoreCourseHelperProvider.openCourse parameters changed, now it admits CoreNavigationOptions + siteId on the same object that includes Params passed to page.
|
||||||
- displaySectionSelector has been deprecated on CoreCourseFormatHandler, use displayCourseIndex instead.
|
- displaySectionSelector has been deprecated on CoreCourseFormatHandler, use displayCourseIndex instead.
|
||||||
- Most of the functions or callbacks that handle redirects/deeplinks have been modified to accept an object instead of just path + options. E.g.: CoreLoginHelper.isSiteLoggedOut, CoreLoginHelper.openBrowserForSSOLogin, CoreLoginHelper.openBrowserForOAuthLogin, CoreLoginHelper.prepareForSSOLogin, CoreApp.storeRedirect, CoreSites.loadSite.
|
- Most of the functions or callbacks that handle redirects/deeplinks have been modified to accept an object instead of just path + options. E.g.: CoreLoginHelper.isSiteLoggedOut, CoreLoginHelper.openBrowserForSSOLogin, CoreLoginHelper.openBrowserForOAuthLogin, CoreLoginHelper.prepareForSSOLogin, CoreApp.storeRedirect, CoreSites.loadSite.
|
||||||
|
- Course preview page route has changed from course/:courseId/preview to course/:courseId/summary to match with the page name and characteristics.
|
||||||
|
|
||||||
=== 3.9.5 ===
|
=== 3.9.5 ===
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue