MOBILE-3814 course: Style course summary page
parent
f2798ec817
commit
115ba52984
|
@ -1,12 +1,9 @@
|
||||||
<ion-header>
|
<ion-header class="no-title">
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
|
||||||
{{'core.course.coursesummary' | translate}}
|
|
||||||
</h1>
|
|
||||||
</ion-title>
|
</ion-title>
|
||||||
<ion-buttons slot="end" *ngIf="isModal">
|
<ion-buttons slot="end" *ngIf="isModal">
|
||||||
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||||
|
@ -15,27 +12,29 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content [fullscreen]="true">
|
||||||
<ion-refresher slot="fixed" [disabled]="!dataLoaded" (ionRefresh)="refreshData($event.target)">
|
<ion-refresher slot="fixed" [disabled]="!dataLoaded" (ionRefresh)="refreshData($event.target)">
|
||||||
<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">
|
<div *ngIf="course" class="core-course-thumb" #courseThumb>
|
||||||
<img [src]="courseImageUrl" core-external-content alt="" />
|
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
|
||||||
|
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" class="course-icon" aria-hidden="true">
|
||||||
|
</ion-icon>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="course">
|
<div *ngIf="course" class="course-container">
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap course-name">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname"
|
<p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname"
|
||||||
class="core-course-shortname">
|
class="core-course-shortname">
|
||||||
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</p>
|
</p>
|
||||||
<h2>
|
<h1>
|
||||||
<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 [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h2>
|
</h1>
|
||||||
<ion-chip color="primary" *ngIf="course.categoryname" class="core-course-category ion-text-nowrap">
|
<ion-chip color="primary" *ngIf="course.categoryname" class="core-course-category ion-text-nowrap">
|
||||||
<span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span>
|
<span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
@ -43,7 +42,14 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-chip>
|
</ion-chip>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button fill="clear" [href]="courseUrl" core-link [showBrowserWarning]="false"
|
||||||
|
[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 class="ion-text-wrap" *ngIf="progress !== undefined || course.startdate || course.enddate">
|
||||||
|
<ion-label>
|
||||||
<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>
|
||||||
|
@ -51,26 +57,22 @@
|
||||||
<div *ngIf="course.startdate || course.enddate" class="core-course-dates">
|
<div *ngIf="course.startdate || course.enddate" class="core-course-dates">
|
||||||
<p *ngIf="course.startdate">
|
<p *ngIf="course.startdate">
|
||||||
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
||||||
<strong>{{ 'core.course.startdate' | translate }}: </strong> {{ course.startdate * 1000 |
|
<strong>{{ 'core.course.startdate' | translate }}</strong><br>
|
||||||
coreFormatDate:'strftimedatefullshort' }}
|
{{ course.startdate * 1000 | coreFormatDate:'strftimedaydatetime' }}
|
||||||
</p>
|
</p>
|
||||||
<p *ngIf="course.enddate">
|
<p *ngIf="course.enddate">
|
||||||
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon>
|
||||||
<strong>{{ 'core.course.enddate' | translate }}: </strong> {{ course.enddate * 1000 |
|
<strong>{{ 'core.course.enddate' | translate }}</strong><br>
|
||||||
coreFormatDate:'strftimedatefullshort' }}
|
{{ course.enddate * 1000 | coreFormatDate:'strftimedaydatetime' }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-button fill="clear" [href]="courseUrl" core-link [showBrowserWarning]="false"
|
|
||||||
[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">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
{{'core.summary' | translate}}
|
{{'core.course.coursesummary' | translate}}
|
||||||
</p>
|
</p>
|
||||||
<core-format-text [text]="course.summary" collapsible-item contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="course.summary" collapsible-item contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
|
@ -78,19 +80,28 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<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 [button]="course.contacts.length >= 5" class="ion-text-wrap" (click)="toggleContacts()"
|
||||||
|
[attr.aria-label]="(contactsExpanded ? 'core.collapse' : 'core.expand') | translate" detail="false">
|
||||||
|
<ion-icon *ngIf="course.contacts.length >= 5" name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true"
|
||||||
|
class="expandable-status-icon" [class.expandable-status-icon-expanded]="contactsExpanded">
|
||||||
|
</ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.teachers' | translate }}</p>
|
<p class="item-heading">
|
||||||
</ion-label>
|
{{ 'core.teachers' | translate }}
|
||||||
</ion-item-divider>
|
</p>
|
||||||
<ion-item button class="ion-text-wrap" *ngFor="let contact of course.contacts" core-user-link [userId]="contact.id"
|
|
||||||
[courseId]="isEnrolled ? course.id : null" [attr.aria-label]="'core.viewprofile' | translate" detail="true">
|
|
||||||
<core-user-avatar [user]="contact" slot="start" [userId]="contact.id" [courseId]="isEnrolled ? course.id : null">
|
|
||||||
</core-user-avatar>
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{contact.fullname}}</p>
|
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ng-container *ngIf="contactsExpanded || course.contacts.length < 5">
|
||||||
|
<ion-item button class="ion-text-wrap" *ngFor="let contact of course.contacts" core-user-link [userId]="contact.id"
|
||||||
|
[courseId]="isEnrolled ? course.id : null" [attr.aria-label]="'core.viewprofile' | translate" detail="true">
|
||||||
|
<core-user-avatar [user]="contact" slot="start" [userId]="contact.id" [courseId]="isEnrolled ? course.id : null"
|
||||||
|
[linkProfile]="false">
|
||||||
|
</core-user-avatar>
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{contact.fullname}}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
<core-spacer></core-spacer>
|
<core-spacer></core-spacer>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
|
@ -102,23 +113,31 @@
|
||||||
<span class="core-customfieldname">
|
<span class="core-customfieldname">
|
||||||
<core-format-text [text]="field.name" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="field.name" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</span><span class="core-customfieldseparator">: </span>
|
<span class="core-customfieldseparator">: </span>
|
||||||
|
</span>
|
||||||
<span class="core-customfieldvalue">
|
<span class="core-customfieldvalue">
|
||||||
<core-format-text [text]="field.value" collapsible-item contextLevel="course"
|
<core-format-text [text]="field.value" [collapsible-item]="field.type == 'textarea' ? '' : null"
|
||||||
[contextInstanceId]="course.id">
|
contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</div>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
<ion-footer *ngIf="course && dataLoaded">
|
<ion-footer *ngIf="course && dataLoaded">
|
||||||
|
<ng-container *ngIf="canAccessCourse">
|
||||||
|
<ion-button *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>
|
||||||
|
|
||||||
<!-- Enrol -->
|
<!-- Enrol -->
|
||||||
<ion-card *ngIf="!isEnrolled">
|
<ion-card *ngIf="!isEnrolled && (selfEnrolInstances.length > 0 || paypalEnabled)">
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let instance of selfEnrolInstances">
|
<ion-item class="ion-text-wrap" *ngFor="let instance of selfEnrolInstances">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ instance.name }}</p>
|
<p class="item-heading">{{ instance.name }}</p>
|
||||||
|
@ -135,22 +154,16 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="!selfEnrolInstances.length && !paypalEnabled">
|
</ion-card>
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.courses.notenrollable' | translate }}</p>
|
<ion-card class="core-info-card" *ngIf="!isEnrolled && !selfEnrolInstances.length && !paypalEnabled">
|
||||||
</ion-label>
|
<ion-item>
|
||||||
|
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>{{ 'core.courses.notenrollable' | translate }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<ng-container *ngIf="canAccessCourse">
|
<ion-button (click)="openCourse()" *ngIf="!isModal && canAccessCourse" expand="block">
|
||||||
<ion-button *ngFor="let item of courseMenuHandlers" (click)="openMenuItem(item)" [class]="'ion-margin' + 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-icon name="fas-briefcase" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
{{ 'core.course' | translate }}
|
{{ 'core.course' | translate }}
|
||||||
|
|
|
@ -1,28 +1,99 @@
|
||||||
@import '~theme/globals.scss';
|
@import '~theme/globals.scss';
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
.core-course-thumb {
|
--thumb-height: 180px;
|
||||||
overflow: hidden;
|
|
||||||
text-align: center;
|
ion-content {
|
||||||
max-height: 35vh;
|
position: absolute;
|
||||||
z-index: -1;
|
|
||||||
overflow: hidden;
|
|
||||||
border-bottom: 1px solid var(--stroke);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-course-thumb {
|
||||||
|
background: var(--course-color, white);
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
height: var(--thumb-height);
|
||||||
|
position: fixed;
|
||||||
|
z-index: -1;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.core-customfieldvalue core-format-text {
|
@for $i from 0 to length($core-course-image-background) {
|
||||||
display: inline;
|
&.course-color-#{$i} {
|
||||||
|
--course-color: var(--core-course-color-#{$i});
|
||||||
|
--course-color-tint: var(--core-course-color-#{$i}-tint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-icon.course-icon {
|
||||||
|
padding: 24px;
|
||||||
|
font-size: calc(var(--thumb-height) - 48px);
|
||||||
|
color: var(--course-color-tint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-container {
|
||||||
|
position: relative;
|
||||||
|
top: calc(var(--thumb-height) - var(--big-radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-name {
|
||||||
|
border-radius: var(--big-radius) var(--big-radius) 0 0;
|
||||||
|
box-shadow: var(--drop-shadow-top);
|
||||||
|
ion-label {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.core-course-category {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-course-dates {
|
.core-course-dates {
|
||||||
background: var(--light);
|
background: var(--light);
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--small-radius);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
ion-icon {
|
ion-icon {
|
||||||
@include margin-horizontal(null, 8px);
|
@include margin-horizontal(null, 8px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.core-customfield {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&.core-customfield_textarea {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.core-customfieldname {
|
||||||
|
@include margin-horizontal(null, 4px);
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.core-customfieldvalue {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, Input } from '@angular/core';
|
import { Component, OnDestroy, OnInit, Input, ViewChild, ElementRef } 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';
|
||||||
|
@ -35,8 +35,9 @@ 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';
|
||||||
import { CoreCourseWithImageAndColor } from '@features/courses/services/courses-helper';
|
import { CoreCoursesHelper, CoreCourseWithImageAndColor } from '@features/courses/services/courses-helper';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { CoreColors } from '@singletons/colors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that shows the summary of a course including buttons to enrol and other available options.
|
* Page that shows the summary of a course including buttons to enrol and other available options.
|
||||||
|
@ -51,23 +52,23 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
@Input() course?: CoreCourseSummaryData;
|
@Input() course?: CoreCourseSummaryData;
|
||||||
@Input() courseId = 0;
|
@Input() courseId = 0;
|
||||||
|
|
||||||
|
@ViewChild('courseThumb') courseThumb?: ElementRef;
|
||||||
|
|
||||||
isEnrolled = false;
|
isEnrolled = false;
|
||||||
canAccessCourse = true;
|
canAccessCourse = true;
|
||||||
selfEnrolInstances: CoreCourseEnrolmentMethod[] = [];
|
selfEnrolInstances: CoreCourseEnrolmentMethod[] = [];
|
||||||
paypalEnabled = false;
|
paypalEnabled = false;
|
||||||
dataLoaded = false;
|
dataLoaded = false;
|
||||||
isModal = false;
|
isModal = false;
|
||||||
|
contactsExpanded = false;
|
||||||
|
|
||||||
courseUrl = '';
|
courseUrl = '';
|
||||||
courseImageUrl?: string;
|
|
||||||
progress?: number;
|
progress?: number;
|
||||||
|
|
||||||
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
||||||
|
|
||||||
protected isGuestEnabled = false;
|
|
||||||
protected useGuestAccess = false;
|
protected useGuestAccess = false;
|
||||||
protected guestInstanceId?: number;
|
protected guestInstanceId?: number;
|
||||||
protected enrolmentMethods: CoreCourseEnrolmentMethod[] = [];
|
|
||||||
protected waitStart = 0;
|
protected waitStart = 0;
|
||||||
protected enrolUrl = '';
|
protected enrolUrl = '';
|
||||||
protected pageDestroyed = false;
|
protected pageDestroyed = false;
|
||||||
|
@ -127,25 +128,14 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
* password is required for guest access.
|
* password is required for guest access.
|
||||||
*/
|
*/
|
||||||
protected async canAccessAsGuest(): Promise<boolean> {
|
protected async canAccessAsGuest(): Promise<boolean> {
|
||||||
if (!this.isGuestEnabled) {
|
if (this.guestInstanceId === undefined) {
|
||||||
throw Error('Guest access is not enabled.');
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search instance ID of guest enrolment method.
|
const info = await CoreCourses.getCourseGuestEnrolmentInfo(this.guestInstanceId);
|
||||||
const method = this.enrolmentMethods.find((method) => method.type == 'guest');
|
|
||||||
this.guestInstanceId = method?.id;
|
|
||||||
|
|
||||||
if (this.guestInstanceId) {
|
// Guest access with password is not supported by the app.
|
||||||
const info = await CoreCourses.getCourseGuestEnrolmentInfo(this.guestInstanceId);
|
return !!info.status && !info.passwordrequired;
|
||||||
if (!info.status) {
|
|
||||||
// Not active, reject.
|
|
||||||
throw Error('Guest access is not enabled.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.passwordrequired;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Error('Guest enrollment method not found.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,13 +148,14 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
this.selfEnrolInstances = [];
|
this.selfEnrolInstances = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.enrolmentMethods = await CoreCourses.getCourseEnrolmentMethods(this.courseId);
|
const enrolmentMethods = await CoreCourses.getCourseEnrolmentMethods(this.courseId);
|
||||||
|
this.guestInstanceId = undefined;
|
||||||
|
|
||||||
this.enrolmentMethods.forEach((method) => {
|
enrolmentMethods.forEach((method) => {
|
||||||
if (method.type === 'self') {
|
if (method.type === 'self') {
|
||||||
this.selfEnrolInstances.push(method);
|
this.selfEnrolInstances.push(method);
|
||||||
} else if (method.type === 'guest') {
|
} else if (method.type === 'guest') {
|
||||||
this.isGuestEnabled = true;
|
this.guestInstanceId = method.id;
|
||||||
} else if (method.type === 'paypal') {
|
} else if (method.type === 'paypal') {
|
||||||
this.paypalEnabled = true;
|
this.paypalEnabled = true;
|
||||||
}
|
}
|
||||||
|
@ -189,16 +180,8 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
this.useGuestAccess = false;
|
this.useGuestAccess = false;
|
||||||
} catch {
|
} catch {
|
||||||
// The user is not an admin/manager. Check if we can provide guest access to the course.
|
// The user is not an admin/manager. Check if we can provide guest access to the course.
|
||||||
try {
|
this.canAccessCourse = await this.canAccessAsGuest();
|
||||||
this.canAccessCourse = !(await this.canAccessAsGuest());
|
this.useGuestAccess = this.canAccessCourse;
|
||||||
this.useGuestAccess = this.canAccessCourse;
|
|
||||||
} catch {
|
|
||||||
this.canAccessCourse = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.course && 'overviewfiles' in this.course && this.course.overviewfiles?.length) {
|
|
||||||
this.courseImageUrl = this.course.overviewfiles[0].fileurl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -219,6 +202,8 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.setCourseColor();
|
||||||
|
|
||||||
if (!this.course ||
|
if (!this.course ||
|
||||||
!('progress' in this.course) ||
|
!('progress' in this.course) ||
|
||||||
typeof this.course.progress !== 'number' ||
|
typeof this.course.progress !== 'number' ||
|
||||||
|
@ -433,6 +418,37 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy {
|
||||||
CoreNavigator.navigateToSitePath(item.data.page, { params });
|
CoreNavigator.navigateToSitePath(item.data.page, { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set course color.
|
||||||
|
*/
|
||||||
|
protected async setCourseColor(): Promise<void> {
|
||||||
|
if (!this.course) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await CoreCoursesHelper.loadCourseColorAndImage(this.course);
|
||||||
|
|
||||||
|
if (!this.courseThumb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.course.color) {
|
||||||
|
this.courseThumb.nativeElement.style.setProperty('--course-color', this.course.color);
|
||||||
|
|
||||||
|
const tint = CoreColors.lighter(this.course.color, 50);
|
||||||
|
this.courseThumb.nativeElement.style.setProperty('--course-color-tint', tint);
|
||||||
|
} else if(this.course.colorNumber !== undefined) {
|
||||||
|
this.courseThumb.nativeElement.classList.add('course-color-' + this.course.colorNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle list of contacts.
|
||||||
|
*/
|
||||||
|
toggleContacts(): void {
|
||||||
|
this.contactsExpanded = !this.contactsExpanded;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the modal.
|
* Close the modal.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue