commit
3796654443
|
@ -18,4 +18,4 @@ jobs:
|
|||
- run: npx tslint -c ionic-migration.json -p tsconfig.json
|
||||
- run: npm run test:ci
|
||||
- run: npm run build:prod
|
||||
- run: result=$(find src -type f -iname '*.html' -exec grep -E 'class="[^"]+"[^>]+class="' {} \; | wc -l); test $result -eq 0
|
||||
- run: result=$(find src -type f -iname '*.html' -exec sh -c 'cat {} | tr "\n" " " | grep -Eo "class=\"[^\"]+\"[^>]+class=\"" ' \; | wc -l); test $result -eq 0
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { PopoverController, IonRefresher } from '@ionic/angular';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreLocalNotifications } from '@services/local-notifications';
|
||||
|
@ -35,7 +35,7 @@ import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features
|
|||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
|
||||
import moment from 'moment';
|
||||
import { Network, NgZone } from '@singletons';
|
||||
import { Network, NgZone, PopoverController } from '@singletons';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { Params } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
@ -100,9 +100,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
category: true,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private popoverCtrl: PopoverController,
|
||||
) {
|
||||
constructor() {
|
||||
this.currentSiteId = CoreSites.instance.getCurrentSiteId();
|
||||
|
||||
if (CoreLocalNotifications.instance.isAvailable()) {
|
||||
|
@ -537,7 +535,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
* @param event Event.
|
||||
*/
|
||||
async openFilter(event: MouseEvent): Promise<void> {
|
||||
const popover = await this.popoverCtrl.create({
|
||||
const popover = await PopoverController.instance.create({
|
||||
component: AddonCalendarFilterPopoverComponent,
|
||||
componentProps: {
|
||||
courses: this.courses,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { PopoverController, IonRefresher } from '@ionic/angular';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreSites } from '@services/sites';
|
||||
|
@ -23,7 +23,7 @@ import { AddonCalendar, AddonCalendarProvider, AddonCalendarUpdatedEventEvent }
|
|||
import { AddonCalendarOffline } from '../../services/calendar-offline';
|
||||
import { AddonCalendarSync, AddonCalendarSyncEvents, AddonCalendarSyncProvider } from '../../services/calendar-sync';
|
||||
import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper';
|
||||
import { Network, NgZone } from '@singletons';
|
||||
import { Network, NgZone, PopoverController } from '@singletons';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CoreEnrolledCourseData } from '@features/courses/services/courses';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
|
@ -83,7 +83,6 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
};
|
||||
|
||||
constructor(
|
||||
protected popoverCtrl: PopoverController,
|
||||
protected route: ActivatedRoute,
|
||||
) {
|
||||
this.currentSiteId = CoreSites.instance.getCurrentSiteId();
|
||||
|
@ -341,7 +340,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
* @param event Event.
|
||||
*/
|
||||
async openFilter(event: MouseEvent): Promise<void> {
|
||||
const popover = await this.popoverCtrl.create({
|
||||
const popover = await PopoverController.instance.create({
|
||||
component: AddonCalendarFilterPopoverComponent,
|
||||
componentProps: {
|
||||
courses: this.courses,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, ViewChild, OnDestroy, OnInit } from '@angular/core';
|
||||
import { PopoverController, IonContent, IonRefresher } from '@ionic/angular';
|
||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||
import {
|
||||
AddonCalendarProvider,
|
||||
AddonCalendar,
|
||||
|
@ -36,7 +36,7 @@ import { CoreConstants } from '@/core/constants';
|
|||
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
|
||||
import { Params } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Network, NgZone } from '@singletons';
|
||||
import { Network, NgZone, PopoverController } from '@singletons';
|
||||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
|
@ -101,9 +101,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy {
|
|||
category: true,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private popoverCtrl: PopoverController,
|
||||
) {
|
||||
constructor() {
|
||||
|
||||
this.siteHomeId = CoreSites.instance.getCurrentSiteHomeId();
|
||||
this.notificationsEnabled = CoreLocalNotifications.instance.isAvailable();
|
||||
|
@ -624,7 +622,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy {
|
|||
* @param event Event.
|
||||
*/
|
||||
async openFilter(event: MouseEvent): Promise<void> {
|
||||
const popover = await this.popoverCtrl.create({
|
||||
const popover = await PopoverController.instance.create({
|
||||
component: AddonCalendarFilterPopoverComponent,
|
||||
componentProps: {
|
||||
courses: this.courses,
|
||||
|
|
|
@ -34,7 +34,6 @@ import { IonRefresher } from '@ionic/angular';
|
|||
@Component({
|
||||
selector: 'page-addon-messages-settings',
|
||||
templateUrl: 'settings.html',
|
||||
styleUrls: ['settings.scss'],
|
||||
})
|
||||
export class AddonMessagesSettingsPage implements OnInit, OnDestroy {
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
:host {
|
||||
.list-header {
|
||||
margin-bottom: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
|||
* @param notification The notification to check.
|
||||
* @return Whether the notification click is handled by this handler
|
||||
*/
|
||||
async handles(notification: NotificationData): Promise<boolean> {
|
||||
async handles(notification: AddonNotificationsNotificationData): Promise<boolean> {
|
||||
if (!notification.moodlecomponent) {
|
||||
// The notification doesn't come from Moodle. Handle it.
|
||||
return true;
|
||||
|
@ -63,7 +63,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
|||
* @param notification Notification to mark.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async markAsRead(notification: NotificationData): Promise<void> {
|
||||
protected async markAsRead(notification: AddonNotificationsNotificationData): Promise<void> {
|
||||
const notifId = notification.savedmessageid || notification.id;
|
||||
|
||||
if (!notifId) {
|
||||
|
@ -81,7 +81,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
|||
* @param notification The notification to check.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async handleClick(notification: NotificationData): Promise<void> {
|
||||
async handleClick(notification: AddonNotificationsNotificationData): Promise<void> {
|
||||
|
||||
if (notification.customdata?.extendedtext) {
|
||||
// Display the text in a modal.
|
||||
|
@ -133,7 +133,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
|||
|
||||
export class AddonNotificationsPushClickHandler extends makeSingleton(AddonNotificationsPushClickHandlerService) {}
|
||||
|
||||
type NotificationData = CorePushNotificationsNotificationBasicData & {
|
||||
type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & {
|
||||
contexturl?: string; // URL related to the notification.
|
||||
savedmessageid?: number; // Notification ID (optional).
|
||||
id?: number; // Notification ID (optional).
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { NavParams, PopoverController } from '@ionic/angular';
|
||||
import { NavParams } from '@ionic/angular';
|
||||
import { PopoverController } from '@singletons';
|
||||
import { CoreContextMenuItemComponent } from './context-menu-item';
|
||||
|
||||
/**
|
||||
|
@ -32,7 +33,6 @@ export class CoreContextMenuPopoverComponent {
|
|||
|
||||
constructor(
|
||||
navParams: NavParams,
|
||||
protected popoverCtrl: PopoverController,
|
||||
) {
|
||||
this.title = navParams.get('title');
|
||||
this.items = navParams.get('items') || [];
|
||||
|
@ -43,7 +43,7 @@ export class CoreContextMenuPopoverComponent {
|
|||
* Close the popover.
|
||||
*/
|
||||
closeMenu(item?: CoreContextMenuItemComponent): void {
|
||||
this.popoverCtrl.dismiss(item);
|
||||
PopoverController.instance.dismiss(item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
import { Component, Input, OnInit, OnDestroy, ElementRef } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { auditTime } from 'rxjs/operators';
|
||||
import { PopoverController } from '@ionic/angular';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { Translate } from '@singletons';
|
||||
import { PopoverController, Translate } from '@singletons';
|
||||
import { CoreContextMenuItemComponent } from './context-menu-item';
|
||||
import { CoreContextMenuPopoverComponent } from './context-menu-popover';
|
||||
|
||||
|
@ -47,7 +46,6 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
|||
|
||||
|
||||
constructor(
|
||||
protected popoverCtrl: PopoverController,
|
||||
elementRef: ElementRef,
|
||||
) {
|
||||
// Create the stream and subscribe to it. We ignore successive changes during 250ms.
|
||||
|
@ -179,7 +177,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
async showContextMenu(event: MouseEvent): Promise<void> {
|
||||
if (!this.expanded) {
|
||||
const popover = await this.popoverCtrl.create(
|
||||
const popover = await PopoverController.instance.create(
|
||||
{
|
||||
event,
|
||||
component: CoreContextMenuPopoverComponent,
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
|
||||
|
@ -83,6 +82,7 @@ export class CoreContentLinksHelperProvider {
|
|||
* Goes to a certain page in a certain site. If the site is current site it will perform a regular navigation,
|
||||
* otherwise it will 'redirect' to the other site.
|
||||
*
|
||||
* @param navCtrlUnused Deprecated param.
|
||||
* @param pageName Name of the page to go.
|
||||
* @param pageParams Params to send to the page.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
|
@ -90,7 +90,7 @@ export class CoreContentLinksHelperProvider {
|
|||
* @return Promise resolved when done.
|
||||
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSitePath instead.
|
||||
*/
|
||||
async goInSite(navCtrl: NavController, pageName: string, pageParams: Params, siteId?: string): Promise<void> {
|
||||
async goInSite(navCtrlUnused: unknown, pageName: string, pageParams: Params, siteId?: string): Promise<void> {
|
||||
await CoreNavigator.instance.navigateToSitePath(pageName, { params: pageParams, siteId });
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
* Go to blog posts.
|
||||
*/
|
||||
async gotoBlog(): Promise<void> {
|
||||
// @todo return this.linkHelper.goInSite(this.navCtrl, 'AddonBlogEntriesPage', { cmId: this.module.id });
|
||||
// const params: Params = { cmId: this.module?.id };
|
||||
// @todo return CoreNavigator.instance.navigateToSitePath('AddonBlogEntriesPage', { params });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -162,7 +162,7 @@ export class CoreCourseProvider {
|
|||
* @return Whether the current view is a certain course.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
currentViewIsCourse(navCtrl: any, courseId: number): boolean {
|
||||
currentViewIsCourse(courseId: number): boolean {
|
||||
// @todo implement
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { PopoverController } from '@ionic/angular';
|
||||
import { CoreCourses } from '../../services/courses';
|
||||
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
|
||||
import { CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||
import { PopoverController } from '@singletons';
|
||||
|
||||
/**
|
||||
* This component is meant to display a popover with the course options.
|
||||
|
@ -32,10 +32,6 @@ export class CoreCoursesCourseOptionsMenuComponent implements OnInit {
|
|||
|
||||
downloadCourseEnabled = false;
|
||||
|
||||
constructor(
|
||||
protected popoverController: PopoverController,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
|
@ -49,7 +45,7 @@ export class CoreCoursesCourseOptionsMenuComponent implements OnInit {
|
|||
* @param action Action name to take.
|
||||
*/
|
||||
action(action: string): void {
|
||||
this.popoverController.dismiss(action);
|
||||
PopoverController.instance.dismiss(action);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { PopoverController } from '@ionic/angular';
|
||||
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
|
@ -21,7 +20,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreCourses } from '@features/courses/services/courses';
|
||||
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
|
||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||
import { Translate } from '@singletons';
|
||||
import { PopoverController, Translate } from '@singletons';
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
|
||||
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
||||
|
@ -62,10 +61,6 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
|||
protected courseStatusObserver?: CoreEventObserver;
|
||||
protected siteUpdatedObserver?: CoreEventObserver;
|
||||
|
||||
constructor(
|
||||
protected popoverCtrl: PopoverController,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
|
@ -204,7 +199,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const popover = await this.popoverCtrl.create({
|
||||
const popover = await PopoverController.instance.create({
|
||||
component: CoreCoursesCourseOptionsMenuComponent,
|
||||
componentProps: {
|
||||
course: this.course,
|
||||
|
|
|
@ -14,12 +14,19 @@
|
|||
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { Routes } from '@angular/router';
|
||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
|
||||
import { CoreMainMenuHomeRoutingModule } from '@features/mainmenu/pages/home/home-routing.module';
|
||||
import { CoreMainMenuHomeDelegate } from '@features/mainmenu/services/home-delegate';
|
||||
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
|
||||
import { CoreCoursesCourseLinkHandler } from './services/handlers/course-link';
|
||||
import { CoreCoursesIndexLinkHandler } from './services/handlers/courses-index-link';
|
||||
|
||||
import { CoreDashboardHomeHandler, CoreDashboardHomeHandlerService } from './services/handlers/dashboard-home';
|
||||
import { CoreCoursesDashboardLinkHandler } from './services/handlers/dashboard-link';
|
||||
import { CoreCoursesEnrolPushClickHandler } from './services/handlers/enrol-push-click';
|
||||
import { CoreCoursesMyCoursesHomeHandler, CoreCoursesMyCoursesHomeHandlerService } from './services/handlers/my-courses-home';
|
||||
import { CoreCoursesRequestPushClickHandler } from './services/handlers/request-push-click';
|
||||
|
||||
const mainMenuHomeChildrenRoutes: Routes = [
|
||||
{
|
||||
|
@ -59,6 +66,11 @@ const mainMenuHomeSiblingRoutes: Routes = [
|
|||
useFactory: () => () => {
|
||||
CoreMainMenuHomeDelegate.instance.registerHandler(CoreDashboardHomeHandler.instance);
|
||||
CoreMainMenuHomeDelegate.instance.registerHandler(CoreCoursesMyCoursesHomeHandler.instance);
|
||||
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesCourseLinkHandler.instance);
|
||||
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesIndexLinkHandler.instance);
|
||||
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesDashboardLinkHandler.instance);
|
||||
CorePushNotificationsDelegate.instance.registerClickHandler(CoreCoursesEnrolPushClickHandler.instance);
|
||||
CorePushNotificationsDelegate.instance.registerClickHandler(CoreCoursesRequestPushClickHandler.instance);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -161,6 +161,7 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
|||
* Open page to manage courses storage.
|
||||
*/
|
||||
manageCoursesStorage(): void {
|
||||
// AddonStorageManagerCoursesStoragePage
|
||||
// @todo this.navCtrl.navigateForward(['/main/home/courses/storage']);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,12 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
// import { PopoverController } from '@ionic/angular';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreCourses, CoreCourseSearchedData, CoreCourseUserAdminOrNavOptionIndexed, CoreEnrolledCourseData } from './courses';
|
||||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { CoreWSExternalFile } from '@services/ws';
|
||||
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
|
||||
// import { CoreCoursePickerMenuPopoverComponent } from '@components/course-picker-menu/course-picker-menu-popover';
|
||||
|
||||
/**
|
||||
* Helper to gather some common courses functions.
|
||||
|
@ -276,19 +274,6 @@ export class CoreCoursesHelperProvider {
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a context menu to select a course, and return the courseId and categoryId of the selected course (-1 for all courses).
|
||||
* Returns an empty object if popover closed without picking a course.
|
||||
*
|
||||
* @param event Click event.
|
||||
* @param courses List of courses, from CoreCoursesHelperProvider.getCoursesForPopover.
|
||||
* @param courseId The course to select at start.
|
||||
* @return Promise resolved with the course ID and category ID.
|
||||
*/
|
||||
async selectCourse(): Promise<void> {
|
||||
// @todo params and logic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesHelper extends makeSingleton(CoreCoursesHelperProvider) { }
|
||||
|
|
|
@ -1168,8 +1168,6 @@ export class CoreCourses extends makeSingleton(CoreCoursesProvider) {}
|
|||
|
||||
/**
|
||||
* Data sent to the EVENT_MY_COURSES_UPDATED.
|
||||
*
|
||||
* @todo course type.
|
||||
*/
|
||||
export type CoreCoursesMyCoursesUpdatedEventData = {
|
||||
action: string; // Action performed.
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreCourseAnyCourseData, CoreCourses, CoreCoursesProvider, CoreEnrolledCourseData } from '../courses';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course view or enrol (except site home).
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'CoreCoursesCourseLinkHandler';
|
||||
pattern = /((\/enrol\/index\.php)|(\/course\/enrol\.php)|(\/course\/view\.php)).*([?&]id=\d+)/;
|
||||
|
||||
protected waitStart = 0;
|
||||
protected logger: CoreLogger;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logger = CoreLogger.getInstance('CoreCoursesCourseLinkHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param siteIds List of sites the URL belongs to.
|
||||
* @param url The URL to treat.
|
||||
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||
* @param courseId Course ID related to the URL. Optional but recommended.
|
||||
* @return List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(
|
||||
siteIds: string[],
|
||||
url: string,
|
||||
params: Params,
|
||||
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
const courseId = parseInt(params.id, 10);
|
||||
const sectionId = params.sectionid ? parseInt(params.sectionid, 10) : null;
|
||||
const pageParams: Params = {
|
||||
sectionId: sectionId || null,
|
||||
};
|
||||
let sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN;
|
||||
|
||||
if (!sectionId && !sectionNumber) {
|
||||
// Check if the URL has a hash to navigate to the section.
|
||||
const matches = url.match(/#section-(\d+)/);
|
||||
if (matches && matches[1]) {
|
||||
sectionNumber = parseInt(matches[1], 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isNaN(sectionNumber)) {
|
||||
pageParams.sectionNumber = sectionNumber;
|
||||
}
|
||||
|
||||
return [{
|
||||
action: (siteId): void => {
|
||||
siteId = siteId || CoreSites.instance.getCurrentSiteId();
|
||||
if (siteId == CoreSites.instance.getCurrentSiteId()) {
|
||||
// Check if we already are in the course index page.
|
||||
if (CoreCourse.instance.currentViewIsCourse(courseId)) {
|
||||
// Current view is this course, just select the contents tab.
|
||||
CoreCourse.instance.selectCourseTab('', pageParams);
|
||||
|
||||
return;
|
||||
} else {
|
||||
this.actionEnrol(courseId, url, pageParams).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Make the course the new history root (to avoid "loops" in history).
|
||||
CoreCourseHelper.instance.getAndOpenCourse(courseId, pageParams, siteId);
|
||||
}
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||
* If not defined, defaults to true.
|
||||
*
|
||||
* @param siteId The site ID.
|
||||
* @param url The URL to treat.
|
||||
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||
* @param courseId Course ID related to the URL. Optional but recommended.
|
||||
* @return Whether the handler is enabled for the URL and site.
|
||||
*/
|
||||
async isEnabled(siteId: string, url: string, params: Params, courseId?: number): Promise<boolean> {
|
||||
courseId = parseInt(params.id, 10);
|
||||
|
||||
if (!courseId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the course id of Site Home.
|
||||
return CoreSites.instance.getSiteHomeId(siteId).then((siteHomeId) => courseId != siteHomeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to perform when an enrol link is clicked.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param url Treated URL.
|
||||
* @param pageParams Params to send to the new page.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async actionEnrol(courseId: number, url: string, pageParams: Params): Promise<void> {
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
let course: CoreCourseAnyCourseData | { id: number } | undefined;
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
try {
|
||||
course = await CoreCourses.instance.getUserCourse(courseId);
|
||||
} catch {
|
||||
course = await this.checkSelfUserCanSelfEnrolOrAccess(courseId, url, modal);
|
||||
}
|
||||
|
||||
// Check if we need to retrieve the course.
|
||||
if (!course) {
|
||||
try {
|
||||
const data = await CoreCourseHelper.instance.getCourse(courseId);
|
||||
course = data.course;
|
||||
} catch {
|
||||
// Cannot get course, return a "fake".
|
||||
course = { id: courseId };
|
||||
}
|
||||
}
|
||||
|
||||
modal.dismiss();
|
||||
|
||||
// Now open the course.
|
||||
CoreCourseHelper.instance.openCourse(course, pageParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user can self enrol or access the course.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param url Treated URL.
|
||||
* @param modal Modal, to dismiss when needed.
|
||||
* @return The course after self enrolling or undefined if the user has access but is not enrolled.
|
||||
*/
|
||||
protected checkSelfUserCanSelfEnrolOrAccess(
|
||||
courseId: number,
|
||||
url: string,
|
||||
modal: CoreIonLoadingElement,
|
||||
): Promise<CoreEnrolledCourseData | undefined> {
|
||||
// User is not enrolled in the course. Check if can self enrol.
|
||||
return this.canSelfEnrol(courseId).then(async () => {
|
||||
modal.dismiss();
|
||||
|
||||
const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
|
||||
|
||||
// The user can self enrol. If it's not a enrolment URL we'll ask for confirmation.
|
||||
if (!isEnrolUrl) {
|
||||
try {
|
||||
await CoreDomUtils.instance.showConfirm(Translate.instance.instant('core.courses.confirmselfenrol'));
|
||||
} catch {
|
||||
// User cancelled. Check if the user can view the course contents (guest access or similar).
|
||||
await CoreCourse.instance.getSections(courseId, false, true);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enrol URL or user confirmed.
|
||||
try {
|
||||
return this.selfEnrol(courseId);
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
CoreDomUtils.instance.showErrorModal(error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}, async (error) => {
|
||||
// Can't self enrol. Check if the user can view the course contents (guest access or similar).
|
||||
try {
|
||||
await CoreCourse.instance.getSections(courseId, false, true);
|
||||
} catch {
|
||||
// Error. Show error message and allow the user to open the link in browser.
|
||||
modal.dismiss();
|
||||
|
||||
if (error) {
|
||||
error = CoreTextUtils.instance.getErrorMessageFromError(error) || error;
|
||||
}
|
||||
if (!error) {
|
||||
error = Translate.instance.instant('core.courses.notenroled');
|
||||
}
|
||||
|
||||
const body = CoreTextUtils.instance.buildSeveralParagraphsMessage(
|
||||
[error, Translate.instance.instant('core.confirmopeninbrowser')],
|
||||
);
|
||||
|
||||
try {
|
||||
await CoreDomUtils.instance.showConfirm(body);
|
||||
|
||||
CoreSites.instance.getCurrentSite()?.openInBrowserWithAutoLogin(url);
|
||||
} catch {
|
||||
// User cancelled.
|
||||
};
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user can be "automatically" self enrolled in a course.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @return Promise resolved if user can be enrolled in a course, rejected otherwise.
|
||||
*/
|
||||
protected async canSelfEnrol(courseId: number): Promise<void> {
|
||||
// Check that the course has self enrolment enabled.
|
||||
|
||||
const methods = await CoreCourses.instance.getCourseEnrolmentMethods(courseId);
|
||||
let isSelfEnrolEnabled = false;
|
||||
let instances = 0;
|
||||
methods.forEach((method) => {
|
||||
if (method.type == 'self' && method.status) {
|
||||
isSelfEnrolEnabled = true;
|
||||
instances++;
|
||||
}
|
||||
});
|
||||
|
||||
if (!isSelfEnrolEnabled || instances != 1) {
|
||||
// Self enrol not enabled or more than one instance.
|
||||
throw new CoreError('Self enrol not enabled in course');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to self enrol a user in a course.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param password Password.
|
||||
* @return Promise resolved when the user is enrolled, rejected otherwise.
|
||||
*/
|
||||
protected async selfEnrol(courseId: number, password?: string): Promise<CoreEnrolledCourseData | undefined> {
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
|
||||
try {
|
||||
await CoreCourses.instance.selfEnrol(courseId, password);
|
||||
|
||||
// Success self enrolling the user, invalidate the courses list.
|
||||
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses());
|
||||
|
||||
try {
|
||||
// Sometimes the list of enrolled courses takes a while to be updated. Wait for it.
|
||||
return this.waitForEnrolled(courseId, true);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
} catch (error) {
|
||||
modal.dismiss();
|
||||
|
||||
if (error && error.code === CoreCoursesProvider.ENROL_INVALID_KEY) {
|
||||
// Invalid password. Allow the user to input password.
|
||||
const title = Translate.instance.instant('core.courses.selfenrolment');
|
||||
const body = ' '; // Empty message.
|
||||
const placeholder = Translate.instance.instant('core.courses.password');
|
||||
|
||||
if (typeof password != 'undefined') {
|
||||
// The user attempted a password. Show an error message.
|
||||
CoreDomUtils.instance.showErrorModal(error);
|
||||
}
|
||||
|
||||
password = await CoreDomUtils.instance.showPrompt(body, title, placeholder);
|
||||
|
||||
return this.selfEnrol(courseId, password);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the user to be enrolled in a course.
|
||||
*
|
||||
* @param courseId The course ID.
|
||||
* @param first If it's the first call (true) or it's a recursive call (false).
|
||||
* @return Promise resolved when enrolled or timeout.
|
||||
*/
|
||||
protected async waitForEnrolled(courseId: number, first?: boolean): Promise<CoreEnrolledCourseData | undefined> {
|
||||
if (first) {
|
||||
this.waitStart = Date.now();
|
||||
}
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses());
|
||||
try {
|
||||
return CoreCourses.instance.getUserCourse(courseId);
|
||||
} catch {
|
||||
|
||||
// Not enrolled, wait a bit and try again.
|
||||
if (Date.now() - this.waitStart > 60000) {
|
||||
// Max time reached, stop.
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject): void => {
|
||||
setTimeout(() => {
|
||||
this.waitForEnrolled(courseId)
|
||||
.then(resolve).catch(reject);
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesCourseLinkHandler extends makeSingleton(CoreCoursesCourseLinkHandlerService) {}
|
|
@ -0,0 +1,65 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreCourses } from '../courses';
|
||||
import { CoreCoursesMyCoursesHomeHandlerService } from './my-courses-home';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course index (list of courses).
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesIndexLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'CoreCoursesIndexLinkHandler';
|
||||
featureName = 'CoreMainMenuDelegate_CoreCourses';
|
||||
pattern = /\/course\/?(index\.php.*)?$/;
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param siteIds List of sites the URL belongs to.
|
||||
* @param url The URL to treat.
|
||||
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||
* @return List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] {
|
||||
return [{
|
||||
action: (siteId): void => {
|
||||
let pageName = CoreCoursesMyCoursesHomeHandlerService.PAGE_NAME;
|
||||
|
||||
if (CoreCourses.instance.isGetCoursesByFieldAvailable()) {
|
||||
if (params.categoryid) {
|
||||
pageName += '/categories/' + params.categoryid;
|
||||
} else {
|
||||
pageName += '/all';
|
||||
}
|
||||
} else {
|
||||
// By default, go to My Courses.
|
||||
pageName += '/my';
|
||||
}
|
||||
|
||||
CoreNavigator.instance.navigateToSitePath(pageName, { siteId });
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesIndexLinkHandler extends makeSingleton(CoreCoursesIndexLinkHandlerService) {}
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { AddonBlockTimeline } from '@addons/block/timeline/services/timeline';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreBlockDelegate } from '@features/block/services/block-delegate';
|
||||
import { CoreMainMenuHomeHandler, CoreMainMenuHomeHandlerToDisplay } from '@features/mainmenu/services/home-delegate';
|
||||
|
@ -45,9 +46,35 @@ export class CoreDashboardHomeHandlerService implements CoreMainMenuHomeHandler
|
|||
* @return Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
async isEnabledForSite(siteId?: string): Promise<boolean> {
|
||||
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
|
||||
const promises: Promise<void>[] = [];
|
||||
let blocksEnabled = false;
|
||||
let dashboardAvailable = false;
|
||||
|
||||
return CoreBlockDelegate.instance.hasSupportedBlock(blocks);
|
||||
// Check if blocks and 3.6 dashboard is enabled.
|
||||
promises.push(CoreBlockDelegate.instance.areBlocksDisabled(siteId).then((disabled) => {
|
||||
blocksEnabled = !disabled;
|
||||
|
||||
return;
|
||||
}));
|
||||
|
||||
promises.push(CoreCoursesDashboard.instance.isAvailable().then((available) => {
|
||||
dashboardAvailable = available;
|
||||
|
||||
return;
|
||||
}));
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
if (dashboardAvailable && blocksEnabled) {
|
||||
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
|
||||
|
||||
return CoreBlockDelegate.instance.hasSupportedBlock(blocks);
|
||||
}
|
||||
|
||||
// Check if my overview is enabled. If it's enabled we will fake enabled blocks.
|
||||
const timelineEnabled = await AddonBlockTimeline.instance.isAvailable();
|
||||
|
||||
return timelineEnabled && blocksEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreDashboardHomeHandler, CoreDashboardHomeHandlerService } from './dashboard-home';
|
||||
|
||||
/**
|
||||
* Handler to treat links to my overview.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesDashboardLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'CoreCoursesMyOverviewLinkHandler';
|
||||
pattern = /\/my\/?$/;
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @return List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
return [{
|
||||
action: (siteId): void => {
|
||||
// Use redirect to select the tab.
|
||||
CoreNavigator.instance.navigateToSitePath(CoreDashboardHomeHandlerService.PAGE_NAME, { siteId });
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||
*
|
||||
* @param siteId The site ID.
|
||||
* @return Whether the handler is enabled for the URL and site.
|
||||
*/
|
||||
isEnabled(siteId: string): boolean | Promise<boolean> {
|
||||
return CoreDashboardHomeHandler.instance.isEnabledForSite(siteId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesDashboardLinkHandler extends makeSingleton(CoreCoursesDashboardLinkHandlerService) {}
|
|
@ -0,0 +1,91 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
|
||||
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler for enrol push notifications clicks.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesEnrolPushClickHandlerService implements CorePushNotificationsClickHandler {
|
||||
|
||||
name = 'CoreCoursesEnrolPushClickHandler';
|
||||
priority = 200;
|
||||
|
||||
/**
|
||||
* Check if a notification click is handled by this handler.
|
||||
*
|
||||
* @param notification The notification to check.
|
||||
* @return Whether the notification click is handled by this handler
|
||||
*/
|
||||
async handles(notification: CorePushNotificationsNotificationBasicData): Promise<boolean> {
|
||||
return CoreUtils.instance.isTrueOrOne(notification.notif) && notification.moodlecomponent?.indexOf('enrol_') === 0 &&
|
||||
notification.name == 'expiry_notification';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the notification click.
|
||||
*
|
||||
* @param notification The notification to check.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async handleClick(notification: CoreCoursesEnrolNotificationData): Promise<void> {
|
||||
const courseId = notification.courseid;
|
||||
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
|
||||
try {
|
||||
const result = await CoreCourseHelper.instance.getCourse(courseId, notification.site);
|
||||
|
||||
const params: Params = {
|
||||
course: result.course,
|
||||
};
|
||||
let page: string;
|
||||
|
||||
if (notification.contexturl?.indexOf('user/index.php') != -1) {
|
||||
// Open the participants tab.
|
||||
page = 'course';
|
||||
params.selectedTab = 'user_participants'; // @todo: Set this when participants is done.
|
||||
} else if (result.enrolled) {
|
||||
// User is still enrolled, open the course.
|
||||
page = 'course';
|
||||
} else {
|
||||
// User not enrolled anymore, open the preview page.
|
||||
page = 'courses/preview';;
|
||||
}
|
||||
|
||||
await CoreNavigator.instance.navigateToSitePath(page, { params, siteId: notification.site });
|
||||
} catch (error) {
|
||||
CoreDomUtils.instance.showErrorModalDefault(error, 'Error getting course.');
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesEnrolPushClickHandler extends makeSingleton(CoreCoursesEnrolPushClickHandlerService) {}
|
||||
|
||||
type CoreCoursesEnrolNotificationData = CorePushNotificationsNotificationBasicData & {
|
||||
courseid: number; // Course ID related to the notification.
|
||||
contexturl?: string; // Context URL related to the notification.
|
||||
};
|
|
@ -17,6 +17,7 @@ import { CoreBlockDelegate } from '@features/block/services/block-delegate';
|
|||
import { CoreMainMenuHomeHandler, CoreMainMenuHomeHandlerToDisplay } from '@features/mainmenu/services/home-delegate';
|
||||
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreCourses } from '../courses';
|
||||
import { CoreCoursesDashboard } from '../dashboard';
|
||||
|
||||
/**
|
||||
|
@ -46,6 +47,12 @@ export class CoreCoursesMyCoursesHomeHandlerService implements CoreMainMenuHomeH
|
|||
* @return Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
async isEnabledForSite(siteId?: string): Promise<boolean> {
|
||||
const disabled = await CoreCourses.instance.isMyCoursesDisabled(siteId);
|
||||
|
||||
if (disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
|
||||
|
||||
return !CoreBlockDelegate.instance.hasSupportedBlock(blocks)&& !CoreSiteHome.instance.isAvailable(siteId);
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
|
||||
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreCourses } from '../courses';
|
||||
|
||||
|
||||
/**
|
||||
* Handler for course request push notifications clicks.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesRequestPushClickHandlerService implements CorePushNotificationsClickHandler {
|
||||
|
||||
name = 'CoreCoursesRequestPushClickHandler';
|
||||
priority = 200;
|
||||
|
||||
/**
|
||||
* Check if a notification click is handled by this handler.
|
||||
*
|
||||
* @param notification The notification to check.
|
||||
* @return Whether the notification click is handled by this handler
|
||||
*/
|
||||
async handles(notification: CorePushNotificationsNotificationBasicData): Promise<boolean> {
|
||||
// Don't support 'courserequestrejected', that way the app will open the notifications page.
|
||||
return CoreUtils.instance.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' &&
|
||||
(notification.name == 'courserequested' || notification.name == 'courserequestapproved');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the notification click.
|
||||
*
|
||||
* @param notification The notification to check.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async handleClick(notification: CoreCoursesRequestNotificationData): Promise<void> {
|
||||
const courseId = notification.courseid;
|
||||
|
||||
if (notification.name == 'courserequested') {
|
||||
// Feature not supported in the app, open in browser.
|
||||
const site = await CoreSites.instance.getSite(notification.site);
|
||||
const url = CoreTextUtils.instance.concatenatePaths(site.getURL(), 'course/pending.php');
|
||||
|
||||
await site.openInBrowserWithAutoLogin(url);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the course.
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
|
||||
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses(notification.site));
|
||||
|
||||
try {
|
||||
const result = await CoreCourseHelper.instance.getCourse(courseId, notification.site);
|
||||
const params: Params = {
|
||||
course: result.course,
|
||||
};
|
||||
let page: string;
|
||||
|
||||
if (result.enrolled) {
|
||||
// User is still enrolled, open the course.
|
||||
page = 'course';
|
||||
} else {
|
||||
// User not enrolled (shouldn't happen), open the preview page.
|
||||
page = 'courses/preview';
|
||||
}
|
||||
|
||||
await CoreNavigator.instance.navigateToSitePath(page, { params, siteId: notification.site });
|
||||
} catch (error) {
|
||||
CoreDomUtils.instance.showErrorModalDefault(error, 'Error getting course.');
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreCoursesRequestPushClickHandler extends makeSingleton(CoreCoursesRequestPushClickHandlerService) {}
|
||||
|
||||
type CoreCoursesRequestNotificationData = CorePushNotificationsNotificationBasicData & {
|
||||
courseid: number; // Course ID related to the notification.
|
||||
};
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
||||
|
@ -440,7 +439,6 @@ export class CoreGradesHelperProvider {
|
|||
* @param courseId Course ID to view.
|
||||
* @param userId User to view. If not defined, current user.
|
||||
* @param moduleId Module to view. If not defined, view all course grades.
|
||||
* @param navCtrl NavController to use.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
|
@ -448,11 +446,10 @@ export class CoreGradesHelperProvider {
|
|||
courseId: number,
|
||||
userId?: number,
|
||||
moduleId?: number,
|
||||
navCtrl?: NavController,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
let currentUserId;
|
||||
let currentUserId: number;
|
||||
|
||||
try {
|
||||
const site = await CoreSites.instance.getSite(siteId);
|
||||
|
@ -504,7 +501,7 @@ export class CoreGradesHelperProvider {
|
|||
}
|
||||
|
||||
// View own grades. Check if we already are in the course index page.
|
||||
if (CoreCourse.instance.currentViewIsCourse(navCtrl, courseId)) {
|
||||
if (CoreCourse.instance.currentViewIsCourse(courseId)) {
|
||||
// Current view is this course, just select the grades tab.
|
||||
CoreCourse.instance.selectCourseTab('CoreGrades');
|
||||
|
||||
|
|
|
@ -50,11 +50,11 @@ export class CoreGradesUserLinkHandlerService extends CoreContentLinksHandlerBas
|
|||
data = data || {};
|
||||
|
||||
return [{
|
||||
action: (siteId, navCtrl?): void => {
|
||||
action: (siteId): void => {
|
||||
const userId = params.userid && parseInt(params.userid, 10);
|
||||
const moduleId = data?.cmid && parseInt(data.cmid, 10) || undefined;
|
||||
|
||||
CoreGradesHelper.instance.goToGrades(courseId!, userId, moduleId, navCtrl, siteId);
|
||||
CoreGradesHelper.instance.goToGrades(courseId!, userId, moduleId, siteId);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
import { Md5 } from 'ts-md5/dist/md5';
|
||||
|
||||
import { CoreApp, CoreStoreConfig } from '@services/app';
|
||||
|
@ -447,7 +446,7 @@ export class CoreLoginHelperProvider {
|
|||
/**
|
||||
* Go to the initial page of a site depending on 'userhomepage' setting.
|
||||
*
|
||||
* @param navCtrl NavController to use. Defaults to app root NavController.
|
||||
* @param navCtrlUnused Deprecated param.
|
||||
* @param page Name of the page to load after loading the main page.
|
||||
* @param params Params to pass to the page.
|
||||
* @param options Navigation options.
|
||||
|
@ -456,7 +455,7 @@ export class CoreLoginHelperProvider {
|
|||
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSiteHome or CoreNavigator.navigateToSitePath instead.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async goToSiteInitialPage(navCtrl?: NavController, page?: string, params?: any, options?: any, url?: string): Promise<void> {
|
||||
async goToSiteInitialPage(navCtrlUnused?: unknown, page?: string, params?: any, options?: any, url?: string): Promise<void> {
|
||||
await CoreNavigator.instance.navigateToSiteHome({
|
||||
...options,
|
||||
params: {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreMainMenuHomeDelegate } from '../home-delegate';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../mainmenu-delegate';
|
||||
|
||||
/**
|
||||
|
@ -24,7 +25,7 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
|
|||
|
||||
static readonly PAGE_NAME = 'home';
|
||||
|
||||
name = 'CoreMainMenuHome';
|
||||
name = 'CoreHome';
|
||||
priority = 1100;
|
||||
|
||||
/**
|
||||
|
@ -39,13 +40,10 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
|
|||
/**
|
||||
* Check if the handler is enabled on a certain site.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async isEnabledForSite(siteId?: string): Promise<boolean> {
|
||||
// @todo
|
||||
return true;
|
||||
async isEnabledForSite(): Promise<boolean> {
|
||||
return CoreMainMenuHomeDelegate.instance.getHandlers().length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,7 +53,7 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
|
|||
*/
|
||||
getDisplayData(): CoreMainMenuHandlerData {
|
||||
return {
|
||||
icon: 'fa-home',
|
||||
icon: 'fas-home',
|
||||
title: 'core.mainmenu.home',
|
||||
page: CoreMainMenuHomeHandlerService.PAGE_NAME,
|
||||
// @todo: subPage? The page can change due to core-tabs.
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
GestureController as GestureControllerService,
|
||||
ActionSheetController as ActionSheetControllerService,
|
||||
NavController as NavControllerService,
|
||||
PopoverController as PopoverControllerService,
|
||||
} from '@ionic/angular';
|
||||
|
||||
import { Badge as BadgeService } from '@ionic-native/badge/ngx';
|
||||
|
@ -148,6 +149,7 @@ export class ActionSheetController extends makeSingleton(ActionSheetControllerSe
|
|||
export class AlertController extends makeSingleton(AlertControllerService) {}
|
||||
export class LoadingController extends makeSingleton(LoadingControllerService) {}
|
||||
export class ModalController extends makeSingleton(ModalControllerService) {}
|
||||
export class PopoverController extends makeSingleton(PopoverControllerService) {}
|
||||
export class ToastController extends makeSingleton(ToastControllerService) {}
|
||||
export class GestureController extends makeSingleton(GestureControllerService) {}
|
||||
export class ApplicationInit extends makeSingleton(ApplicationInitStatus) {}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
import { CoreFileHelper } from '@services/file-helper';
|
||||
|
@ -21,6 +22,8 @@ import { CoreUtils } from '@services/utils/utils';
|
|||
|
||||
/**
|
||||
* Options for the open function.
|
||||
*
|
||||
* @deprecated since 3.9.5
|
||||
*/
|
||||
export type CoreWindowOpenOptions = {
|
||||
/**
|
||||
|
@ -46,10 +49,9 @@ export class CoreWindow {
|
|||
*
|
||||
* @param url URL to open.
|
||||
* @param name Name of the browsing context into which to load the URL.
|
||||
* @param options Other options.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
static async open(url: string, name?: string, options?: CoreWindowOpenOptions): Promise<void> {
|
||||
static async open(url: string, name?: string): Promise<void> {
|
||||
if (CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
||||
const filename = url.substr(url.lastIndexOf('/') + 1);
|
||||
|
||||
|
@ -64,13 +66,11 @@ export class CoreWindow {
|
|||
await CoreUtils.instance.openFile(url);
|
||||
} else {
|
||||
let treated = false;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
options = options || {};
|
||||
|
||||
if (name != '_system') {
|
||||
// Check if it can be opened in the app.
|
||||
treated = false;
|
||||
// @todo await CoreContentLinksHelper.instance.handleLink(url, undefined, options.navCtrl, true, true);
|
||||
await CoreContentLinksHelper.instance.handleLink(url, undefined, true, true);
|
||||
}
|
||||
|
||||
if (!treated) {
|
||||
|
|
Loading…
Reference in New Issue