MOBILE-3320 routing: Refactor NavHelper
parent
554a6d7717
commit
09adbb7fbf
|
@ -19,7 +19,7 @@ import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
// @todo import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
// @todo import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ export class AddonBadgesUserBadgesPage implements OnInit {
|
||||||
const params = { courseId: this.courseId, userId: this.userId, badgeHash: badgeHash };
|
const params = { courseId: this.courseId, userId: this.userId, badgeHash: badgeHash };
|
||||||
// @todo use splitview.
|
// @todo use splitview.
|
||||||
// this.splitviewCtrl.push('AddonBadgesIssuedBadgePage', params);
|
// this.splitviewCtrl.push('AddonBadgesIssuedBadgePage', params);
|
||||||
CoreNavHelper.instance.goInSite('/badges/issue', params);
|
CoreNavigator.instance.navigateToSitePath('/badges/issue', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonBadges } from '../badges';
|
import { AddonBadges } from '../badges';
|
||||||
|
|
||||||
|
@ -43,10 +43,12 @@ export class AddonBadgesBadgeLinkHandlerService extends CoreContentLinksHandlerB
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
action: (siteId: string): void => {
|
action: (siteId: string): void => {
|
||||||
CoreNavHelper.instance.goInSite(
|
CoreNavigator.instance.navigateToSitePath(
|
||||||
'/badges/issue',
|
'/badges/issue',
|
||||||
{ courseId: 0, badgeHash: params.hash },
|
{
|
||||||
siteId,
|
siteId,
|
||||||
|
params: { courseId: 0, badgeHash: params.hash },
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonBadges } from '../badges';
|
import { AddonBadges } from '../badges';
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export class AddonBadgesMyBadgesLinkHandlerService extends CoreContentLinksHandl
|
||||||
getActions(): CoreContentLinksAction[] {
|
getActions(): CoreContentLinksAction[] {
|
||||||
return [{
|
return [{
|
||||||
action: (siteId: string): void => {
|
action: (siteId: string): void => {
|
||||||
CoreNavHelper.instance.goInSite('/badges/user', {}, siteId);
|
CoreNavigator.instance.navigateToSitePath('/badges/user', { siteId });
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { CorePushNotificationsClickHandler } from '@features/pushnotifications/s
|
||||||
import { AddonBadges } from '../badges';
|
import { AddonBadges } from '../badges';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
|
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for badges push notifications clicks.
|
* Handler for badges push notifications clicks.
|
||||||
|
@ -59,7 +59,12 @@ export class AddonBadgesPushClickHandlerService implements CorePushNotifications
|
||||||
|
|
||||||
if (data.hash) {
|
if (data.hash) {
|
||||||
// We have the hash, open the badge directly.
|
// We have the hash, open the badge directly.
|
||||||
return CoreNavHelper.instance.goInSite('/badges/issue', { courseId: 0, badgeHash: data.hash }, notification.site);
|
await CoreNavigator.instance.navigateToSitePath('/badges/issue', {
|
||||||
|
siteId: notification.site,
|
||||||
|
params: { courseId: 0, badgeHash: data.hash },
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No hash, open the list of user badges.
|
// No hash, open the list of user badges.
|
||||||
|
@ -71,7 +76,7 @@ export class AddonBadgesPushClickHandlerService implements CorePushNotifications
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await CoreNavHelper.instance.goInSite('/badges/user', {}, notification.site);
|
await CoreNavigator.instance.navigateToSitePath('/badges/user', { siteId: notification.site });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses';
|
import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses';
|
||||||
import { CoreUserProfile } from '@features/user/services/user';
|
import { CoreUserProfile } from '@features/user/services/user';
|
||||||
import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate';
|
import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonBadges } from '../badges';
|
import { AddonBadges } from '../badges';
|
||||||
|
|
||||||
|
@ -72,7 +72,10 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler {
|
||||||
action: (event, user, courseId): void => {
|
action: (event, user, courseId): void => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
CoreNavHelper.instance.goInSite('/badges/user', { courseId: courseId || 0, userId: user.id });
|
CoreNavigator.instance.navigateToSitePath(
|
||||||
|
'/badges/user',
|
||||||
|
{ params: { courseId: courseId || 0, userId: user.id } },
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
// @todo Decide which navCtrl to use. If this component is inside a split view, use the split view's master nav.
|
// @todo Decide which navCtrl to use. If this component is inside a split view, use the split view's master nav.
|
||||||
this.navCtrl.navigateForward(['user'], {
|
this.navCtrl.navigateForward(['user'], {
|
||||||
relativeTo: this.route,
|
relativeTo: this.route,
|
||||||
queryParams: CoreObject.removeUndefined({
|
queryParams: CoreObject.withoutEmpty({
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
courseId: this.courseId,
|
courseId: this.courseId,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NavController } from '@ionic/angular';
|
import { NavController } from '@ionic/angular';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
import { CoreObject } from '@singletons/object';
|
import { CoreObject } from '@singletons/object';
|
||||||
|
|
||||||
|
@ -54,10 +54,12 @@ export class CoreUserLinkDirective implements OnInit {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
// @todo If this directive is inside a split view, use the split view's master nav.
|
// @todo If this directive is inside a split view, use the split view's master nav.
|
||||||
CoreNavHelper.instance.goInCurrentMainMenuTab('user', CoreObject.removeUndefined({
|
CoreNavigator.instance.navigateToSitePath('user', {
|
||||||
userId: this.userId,
|
params: CoreObject.withoutEmpty({
|
||||||
courseId: this.courseId,
|
userId: this.userId,
|
||||||
}));
|
courseId: this.courseId,
|
||||||
|
}),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { OnInit, Component } from '@angular/core';
|
import { OnInit, Component } from '@angular/core';
|
||||||
import { CoreBlockBaseComponent } from '../../classes/base-block-component';
|
import { CoreBlockBaseComponent } from '../../classes/base-block-component';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to render blocks with only a title and link.
|
* Component to render blocks with only a title and link.
|
||||||
|
@ -24,7 +24,7 @@ import { CoreNavHelper } from '@services/nav-helper';
|
||||||
templateUrl: 'core-block-only-title.html',
|
templateUrl: 'core-block-only-title.html',
|
||||||
styleUrls: ['only-title-block.scss'],
|
styleUrls: ['only-title-block.scss'],
|
||||||
})
|
})
|
||||||
export class CoreBlockOnlyTitleComponent extends CoreBlockBaseComponent implements OnInit {
|
export class CoreBlockOnlyTitleComponent extends CoreBlockBaseComponent implements OnInit {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('CoreBlockOnlyTitleComponent');
|
super('CoreBlockOnlyTitleComponent');
|
||||||
|
@ -43,7 +43,8 @@ export class CoreBlockOnlyTitleComponent extends CoreBlockBaseComponent impleme
|
||||||
* Go to the block page.
|
* Go to the block page.
|
||||||
*/
|
*/
|
||||||
gotoBlock(): void {
|
gotoBlock(): void {
|
||||||
CoreNavHelper.instance.goInSite(this.link!, this.linkParams!, undefined, true);
|
// @todo test that this is working properly.
|
||||||
|
CoreNavigator.instance.navigateToSitePath(this.link!, { params: this.linkParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { CoreContentLinksHandlerBase } from './base-handler';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to handle URLs pointing to a list of a certain type of modules.
|
* Handler to handle URLs pointing to a list of a certain type of modules.
|
||||||
|
@ -56,14 +55,16 @@ export class CoreContentLinksModuleListHandler extends CoreContentLinksHandlerBa
|
||||||
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
action: (siteId): void => {
|
action: (siteId): void => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const stateParams = {
|
const stateParams = {
|
||||||
courseId: params.id,
|
courseId: params.id,
|
||||||
modName: this.modName,
|
modName: this.modName,
|
||||||
title: this.title || Translate.instance.instant('addon.mod_' + this.modName + '.modulenameplural'),
|
title: this.title || Translate.instance.instant('addon.mod_' + this.modName + '.modulenameplural'),
|
||||||
};
|
};
|
||||||
|
|
||||||
CoreNavHelper.instance.goInSite('CoreCourseListModTypePage @todo', stateParams, siteId);
|
// @todo CoreNavigator.instance.goInSite('CoreCourseListModTypePage', stateParams, siteId);
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { CoreContentLinksAction } from '../../services/contentlinks-delegate';
|
||||||
import { CoreContentLinksHelper } from '../../services/contentlinks-helper';
|
import { CoreContentLinksHelper } from '../../services/contentlinks-helper';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to display the list of sites to choose one to perform a content link action.
|
* Page to display the list of sites to choose one to perform a content link action.
|
||||||
|
@ -102,7 +102,7 @@ export class CoreContentLinksChooseSitePage implements OnInit {
|
||||||
*/
|
*/
|
||||||
siteClicked(siteId: string): void {
|
siteClicked(siteId: string): void {
|
||||||
if (this.isRootURL) {
|
if (this.isRootURL) {
|
||||||
CoreNavHelper.instance.openInSiteMainMenu('', {}, siteId);
|
CoreNavigator.instance.navigateToSiteHome({ siteId });
|
||||||
} else if (this.action) {
|
} else if (this.action) {
|
||||||
this.action.action(siteId);
|
this.action.action(siteId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
|
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
|
||||||
import { CoreSite } from '@classes/site';
|
import { CoreSite } from '@classes/site';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { Params } from '@angular/router';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that provides some features regarding content links.
|
* Service that provides some features regarding content links.
|
||||||
|
@ -92,10 +91,11 @@ export class CoreContentLinksHelperProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @param checkMenu If true, check if the root page of a main menu tab. Only the page name will be checked.
|
* @param checkMenu If true, check if the root page of a main menu tab. Only the page name will be checked.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.goInSite instead.
|
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSitePath instead.
|
||||||
*/
|
*/
|
||||||
goInSite(pageName: string, pageParams: Params, siteId?: string, checkMenu?: boolean): Promise<void> {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
return CoreNavHelper.instance.goInSite(pageName, pageParams, siteId, checkMenu);
|
async goInSite(navCtrl: NavController, pageName: string, pageParams: any, siteId?: string): Promise<void> {
|
||||||
|
await CoreNavigator.instance.navigateToSitePath(pageName, { params: pageParams, siteId });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -192,7 +192,7 @@ export class CoreContentLinksHelperProvider {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Login in the site.
|
// Login in the site.
|
||||||
return CoreNavHelper.instance.openInSiteMainMenu('', {}, site.getId());
|
await CoreNavigator.instance.navigateToSiteHome({ siteId: site.getId() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses
|
||||||
import { CoreArray } from '@singletons/array';
|
import { CoreArray } from '@singletons/array';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
||||||
import { CoreCourseOffline } from './course-offline';
|
import { CoreCourseOffline } from './course-offline';
|
||||||
import { CoreNavHelper, CoreNavHelperService } from '@services/nav-helper';
|
|
||||||
import {
|
import {
|
||||||
CoreCourseOptionsDelegate,
|
CoreCourseOptionsDelegate,
|
||||||
CoreCourseOptionsHandlerToDisplay,
|
CoreCourseOptionsHandlerToDisplay,
|
||||||
|
@ -979,7 +978,7 @@ export class CoreCourseHelperProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
openCourse(course: CoreEnrolledCourseBasicData | { id: number }, params?: Params, siteId?: string): Promise<void> {
|
async openCourse(course: CoreEnrolledCourseBasicData | { id: number }, params?: Params, siteId?: string): Promise<void> {
|
||||||
if (!siteId || siteId == CoreSites.instance.getCurrentSiteId()) {
|
if (!siteId || siteId == CoreSites.instance.getCurrentSiteId()) {
|
||||||
// Current site, we can open the course.
|
// Current site, we can open the course.
|
||||||
return CoreCourse.instance.openCourse(course, params);
|
return CoreCourse.instance.openCourse(course, params);
|
||||||
|
@ -988,7 +987,9 @@ export class CoreCourseHelperProvider {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
Object.assign(params, { course: course });
|
Object.assign(params, { course: course });
|
||||||
|
|
||||||
return CoreNavHelper.instance.openInSiteMainMenu(CoreNavHelperService.OPEN_COURSE, params, siteId);
|
// @todo implement open course.
|
||||||
|
// await CoreNavigator.instance.navigateToSitePath('/course/.../...', { siteId, queryParams: params });
|
||||||
|
// return CoreNavigator.instance.openInSiteMainMenu(CoreNavigatorService.OPEN_COURSE, params, siteId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';
|
import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';
|
||||||
import { IonRefresher, NavController } from '@ionic/angular';
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
|
||||||
import { CoreCourses, CoreCoursesProvider } from '../../services/courses';
|
import { CoreCourses, CoreCoursesProvider } from '../../services/courses';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
|
@ -22,6 +22,7 @@ import { CoreCoursesDashboard } from '@features/courses/services/dashboard';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreCourseBlock } from '@features/course/services/course';
|
import { CoreCourseBlock } from '@features/course/services/course';
|
||||||
import { CoreBlockComponent } from '@features/block/components/block/block';
|
import { CoreBlockComponent } from '@features/block/components/block/block';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the dashboard page.
|
* Page that displays the dashboard page.
|
||||||
|
@ -35,7 +36,6 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@ViewChildren(CoreBlockComponent) blocksComponents?: QueryList<CoreBlockComponent>;
|
@ViewChildren(CoreBlockComponent) blocksComponents?: QueryList<CoreBlockComponent>;
|
||||||
|
|
||||||
|
|
||||||
searchEnabled = false;
|
searchEnabled = false;
|
||||||
downloadEnabled = false;
|
downloadEnabled = false;
|
||||||
downloadCourseEnabled = false;
|
downloadCourseEnabled = false;
|
||||||
|
@ -47,10 +47,6 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
protected updateSiteObserver?: CoreEventObserver;
|
protected updateSiteObserver?: CoreEventObserver;
|
||||||
|
|
||||||
constructor(
|
|
||||||
protected navCtrl: NavController,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the component.
|
* Initialize the component.
|
||||||
*/
|
*/
|
||||||
|
@ -171,8 +167,8 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
||||||
/**
|
/**
|
||||||
* Go to search courses.
|
* Go to search courses.
|
||||||
*/
|
*/
|
||||||
openSearch(): void {
|
async openSearch(): Promise<void> {
|
||||||
this.navCtrl.navigateForward(['/main/home/courses/search']);
|
CoreNavigator.instance.navigateToSitePath('/courses/search');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that shows instructions to change the password.
|
* Page that shows instructions to change the password.
|
||||||
|
@ -63,7 +63,7 @@ export class CoreLoginChangePasswordPage {
|
||||||
* Login the user.
|
* Login the user.
|
||||||
*/
|
*/
|
||||||
login(): void {
|
login(): void {
|
||||||
CoreNavHelper.instance.goToSiteInitialPage();
|
CoreNavigator.instance.navigateToSiteHome();
|
||||||
this.changingPassword = false;
|
this.changingPassword = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { CoreConstants } from '@/core/constants';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site';
|
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to enter the user credentials.
|
* Page to enter the user credentials.
|
||||||
|
@ -245,7 +245,8 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.siteId = id;
|
this.siteId = id;
|
||||||
|
|
||||||
await CoreNavHelper.instance.goToSiteInitialPage({ urlToOpen: this.urlToOpen });
|
// @todo test that this is working properly.
|
||||||
|
await CoreNavigator.instance.navigateToSiteHome({ params: { urlToOpen: this.urlToOpen } });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreLoginHelper.instance.treatUserTokenError(siteUrl, error, username, password);
|
CoreLoginHelper.instance.treatUserTokenError(siteUrl, error, username, password);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { ApplicationInit, SplashScreen } from '@singletons';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a "splash screen" while the app is being initialized.
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
@ -32,6 +32,8 @@ import { CoreNavHelper } from '@services/nav-helper';
|
||||||
})
|
})
|
||||||
export class CoreLoginInitPage implements OnInit {
|
export class CoreLoginInitPage implements OnInit {
|
||||||
|
|
||||||
|
// @todo this page should be removed in favor of native splash
|
||||||
|
// or a splash component rendered in the root app component
|
||||||
constructor(protected navCtrl: NavController) {}
|
constructor(protected navCtrl: NavController) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,17 +82,21 @@ export class CoreLoginInitPage implements OnInit {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreNavHelper.instance.goToSiteInitialPage({
|
await CoreNavigator.instance.navigateToSiteHome({
|
||||||
redirectPage: redirectData.page,
|
params: {
|
||||||
redirectParams: redirectData.params,
|
redirectPath: redirectData.page,
|
||||||
|
redirectParams: redirectData.params,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Site doesn't exist.
|
// Site doesn't exist.
|
||||||
return this.loadPage();
|
return this.loadPage();
|
||||||
}
|
}
|
||||||
} else if (redirectData.page) {
|
} else if (redirectData.page) {
|
||||||
// No site to load, open the page.
|
// No site to load, open the page.
|
||||||
return CoreNavHelper.instance.goToNoSitePage(redirectData.page, redirectData.params);
|
// @todo return CoreNavigator.instance.goToNoSitePage(redirectData.page, redirectData.params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +116,9 @@ export class CoreLoginInitPage implements OnInit {
|
||||||
return this.loadPage();
|
return this.loadPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreNavHelper.instance.goToSiteInitialPage();
|
await CoreNavigator.instance.navigateToSiteHome();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.navCtrl.navigateRoot('/login/sites');
|
await this.navCtrl.navigateRoot('/login/sites');
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site';
|
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to enter the user password to reconnect to a site.
|
* Page to enter the user password to reconnect to a site.
|
||||||
|
@ -207,9 +207,12 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||||
this.credForm.controls['password'].reset();
|
this.credForm.controls['password'].reset();
|
||||||
|
|
||||||
// Go to the site initial page.
|
// Go to the site initial page.
|
||||||
await CoreNavHelper.instance.goToSiteInitialPage({
|
// @todo test that this is working properly (could we use navigateToSitePath instead?).
|
||||||
redirectPage: this.page,
|
await CoreNavigator.instance.navigateToSiteHome({
|
||||||
redirectParams: this.pageParams,
|
params: {
|
||||||
|
redirectPath: this.page,
|
||||||
|
redirectParams: this.pageParams,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreLoginHelper.instance.treatUserTokenError(this.siteUrl, error, this.username, password);
|
CoreLoginHelper.instance.treatUserTokenError(this.siteUrl, error, this.username, password);
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreSite } from '@classes/site';
|
import { CoreSite } from '@classes/site';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to accept a site policy.
|
* Page to accept a site policy.
|
||||||
|
@ -129,7 +129,7 @@ export class CoreLoginSitePolicyPage implements OnInit {
|
||||||
// Invalidate cache since some WS don't return error if site policy is not accepted.
|
// Invalidate cache since some WS don't return error if site policy is not accepted.
|
||||||
await CoreUtils.instance.ignoreErrors(this.currentSite!.invalidateWsCache());
|
await CoreUtils.instance.ignoreErrors(this.currentSite!.invalidateWsCache());
|
||||||
|
|
||||||
await CoreNavHelper.instance.goToSiteInitialPage();
|
await CoreNavigator.instance.navigateToSiteHome();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.instance.showErrorModalDefault(error, 'Error accepting site policy.');
|
CoreDomUtils.instance.showErrorModalDefault(error, 'Error accepting site policy.');
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -31,7 +31,7 @@ import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUrlUtils } from '@services/utils/url';
|
import { CoreUrlUtils } from '@services/utils/url';
|
||||||
import { CoreLoginSiteHelpComponent } from '@features/login/components/site-help/site-help';
|
import { CoreLoginSiteHelpComponent } from '@features/login/components/site-help/site-help';
|
||||||
import { CoreLoginSiteOnboardingComponent } from '@features/login/components/site-onboarding/site-onboarding';
|
import { CoreLoginSiteOnboardingComponent } from '@features/login/components/site-onboarding/site-onboarding';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a "splash screen" while the app is being initialized.
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
@ -329,7 +329,9 @@ export class CoreLoginSitePage implements OnInit {
|
||||||
|
|
||||||
CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true);
|
CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true);
|
||||||
|
|
||||||
return CoreNavHelper.instance.goToSiteInitialPage();
|
await CoreNavigator.instance.navigateToSiteHome();
|
||||||
|
|
||||||
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreLoginHelper.instance.treatUserTokenError(siteData.url, error, siteData.username, siteData.password);
|
CoreLoginHelper.instance.treatUserTokenError(siteData.url, error, siteData.username, siteData.password);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { Component, OnInit } from '@angular/core';
|
||||||
import { CoreSiteBasicInfo, CoreSites } from '@services/sites';
|
import { CoreSiteBasicInfo, CoreSites } from '@services/sites';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a "splash screen" while the app is being initialized.
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
@ -125,7 +125,9 @@ export class CoreLoginSitesPage implements OnInit {
|
||||||
const loggedIn = await CoreSites.instance.loadSite(siteId);
|
const loggedIn = await CoreSites.instance.loadSite(siteId);
|
||||||
|
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
return CoreNavHelper.instance.goToSiteInitialPage();
|
await CoreNavigator.instance.navigateToSiteHome();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('Error loading site ' + siteId, error);
|
this.logger.error('Error loading site ' + siteId, error);
|
||||||
|
|
|
@ -34,7 +34,7 @@ import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreObject } from '@singletons/object';
|
import { CoreObject } from '@singletons/object';
|
||||||
import { CoreNavHelper, CoreNavHelperOpenMainMenuOptions, CoreNavHelperService } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper provider that provides some common features regarding authentication.
|
* Helper provider that provides some common features regarding authentication.
|
||||||
|
@ -42,7 +42,11 @@ import { CoreNavHelper, CoreNavHelperOpenMainMenuOptions, CoreNavHelperService }
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CoreLoginHelperProvider {
|
export class CoreLoginHelperProvider {
|
||||||
|
|
||||||
static readonly OPEN_COURSE = CoreNavHelperService.OPEN_COURSE; // @deprecated since 3.9.5.
|
/**
|
||||||
|
* @deprecated since 3.9.5.
|
||||||
|
*/
|
||||||
|
static readonly OPEN_COURSE = 'open_course';
|
||||||
|
|
||||||
static readonly ONBOARDING_DONE = 'onboarding_done';
|
static readonly ONBOARDING_DONE = 'onboarding_done';
|
||||||
static readonly FAQ_URL_IMAGE_HTML = '<img src="assets/img/login/faq_url.png" role="presentation">';
|
static readonly FAQ_URL_IMAGE_HTML = '<img src="assets/img/login/faq_url.png" role="presentation">';
|
||||||
static readonly FAQ_QRCODE_IMAGE_HTML = '<img src="assets/img/login/faq_qrcode.png" role="presentation">';
|
static readonly FAQ_QRCODE_IMAGE_HTML = '<img src="assets/img/login/faq_qrcode.png" role="presentation">';
|
||||||
|
@ -111,9 +115,12 @@ export class CoreLoginHelperProvider {
|
||||||
*/
|
*/
|
||||||
checkLogout(): void {
|
checkLogout(): void {
|
||||||
const currentSite = CoreSites.instance.getCurrentSite();
|
const currentSite = CoreSites.instance.getCurrentSite();
|
||||||
const currentPage = CoreNavHelper.instance.getCurrentPage();
|
|
||||||
|
|
||||||
if (!CoreApp.instance.isSSOAuthenticationOngoing() && currentSite?.isLoggedOut() && currentPage == '/login/reconnect') {
|
if (
|
||||||
|
!CoreApp.instance.isSSOAuthenticationOngoing() &&
|
||||||
|
currentSite?.isLoggedOut() &&
|
||||||
|
CoreNavigator.instance.isCurrent('/login/reconnect')
|
||||||
|
) {
|
||||||
// User must reauthenticate but he closed the InAppBrowser without doing so, logout him.
|
// User must reauthenticate but he closed the InAppBrowser without doing so, logout him.
|
||||||
CoreSites.instance.logout();
|
CoreSites.instance.logout();
|
||||||
}
|
}
|
||||||
|
@ -436,21 +443,33 @@ export class CoreLoginHelperProvider {
|
||||||
* @param page Page to open.
|
* @param page Page to open.
|
||||||
* @param params Params of the page.
|
* @param params Params of the page.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.goToNoSitePage instead.
|
* @deprecated since 3.9.5. Use CoreNavigator.navigateToLoginCredentials instead.
|
||||||
*/
|
*/
|
||||||
goToNoSitePage(page: string, params?: Params): Promise<void> {
|
async goToNoSitePage(page: string, params?: Params): Promise<void> {
|
||||||
return CoreNavHelper.instance.goToNoSitePage(page, params);
|
await CoreNavigator.instance.navigateToLoginCredentials(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go to the initial page of a site depending on 'userhomepage' setting.
|
* Go to the initial page of a site depending on 'userhomepage' setting.
|
||||||
*
|
*
|
||||||
* @param options Options.
|
* @param navCtrl NavController to use. Defaults to app root NavController.
|
||||||
|
* @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.
|
||||||
|
* @param url URL to open once the main menu is loaded.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.goToSiteInitialPage instead.
|
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSiteHome or CoreNavigator.navigateToSitePath instead.
|
||||||
*/
|
*/
|
||||||
goToSiteInitialPage(options?: CoreNavHelperOpenMainMenuOptions): Promise<void> {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
return CoreNavHelper.instance.goToSiteInitialPage(options);
|
async goToSiteInitialPage(navCtrl?: NavController, page?: string, params?: any, options?: any, url?: string): Promise<void> {
|
||||||
|
await CoreNavigator.instance.navigateToSiteHome({
|
||||||
|
...options,
|
||||||
|
params: {
|
||||||
|
redirectPath: page,
|
||||||
|
redirectParams: params,
|
||||||
|
urlToOpen: url,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -606,10 +625,10 @@ export class CoreLoginHelperProvider {
|
||||||
*
|
*
|
||||||
* @param page Name of the page to load.
|
* @param page Name of the page to load.
|
||||||
* @param params Params to pass to the page.
|
* @param params Params to pass to the page.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.loadPageInMainMenu instead.
|
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSitepath instead.
|
||||||
*/
|
*/
|
||||||
loadPageInMainMenu(page: string, params?: Params): void {
|
loadPageInMainMenu(page: string, params?: Params): void {
|
||||||
CoreNavHelper.instance.loadPageInMainMenu(page, params);
|
CoreNavigator.instance.navigateToSitePath(page, { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -767,10 +786,8 @@ export class CoreLoginHelperProvider {
|
||||||
return; // Site that triggered the event is not current site.
|
return; // Site that triggered the event is not current site.
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentPage = CoreNavHelper.instance.getCurrentPage();
|
|
||||||
|
|
||||||
// If current page is already change password, stop.
|
// If current page is already change password, stop.
|
||||||
if (currentPage == '/login/changepassword') {
|
if (CoreNavigator.instance.isCurrent('/login/changepassword')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,14 +843,14 @@ export class CoreLoginHelperProvider {
|
||||||
/**
|
/**
|
||||||
* Redirect to a new page, setting it as the root page and loading the right site if needed.
|
* Redirect to a new page, setting it as the root page and loading the right site if needed.
|
||||||
*
|
*
|
||||||
* @param page Name of the page to load. Special cases: CoreNavHelperService.OPEN_COURSE (to open course page).
|
* @param page Name of the page to load.
|
||||||
* @param params Params to pass to the page.
|
* @param params Params to pass to the page.
|
||||||
* @param siteId Site to load. If not defined, current site.
|
* @param siteId Site to load. If not defined, current site.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.openInSiteMainMenu instead.
|
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSitePath instead.
|
||||||
*/
|
*/
|
||||||
redirect(page: string, params?: Params, siteId?: string): Promise<void> {
|
async redirect(page: string, params?: Params, siteId?: string): Promise<void> {
|
||||||
return CoreNavHelper.instance.openInSiteMainMenu(page, params, siteId);
|
await CoreNavigator.instance.navigateToSitePath(page, { params, siteId });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -959,14 +976,14 @@ export class CoreLoginHelperProvider {
|
||||||
const info = currentSite.getInfo();
|
const info = currentSite.getInfo();
|
||||||
if (typeof info != 'undefined' && typeof info.username != 'undefined' && !this.isOpeningReconnect) {
|
if (typeof info != 'undefined' && typeof info.username != 'undefined' && !this.isOpeningReconnect) {
|
||||||
// If current page is already reconnect, stop.
|
// If current page is already reconnect, stop.
|
||||||
if (CoreNavHelper.instance.getCurrentPage() == '/login/reconnect') {
|
if (CoreNavigator.instance.isCurrent('/login/reconnect')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isOpeningReconnect = true;
|
this.isOpeningReconnect = true;
|
||||||
|
|
||||||
await CoreUtils.instance.ignoreErrors(this.navCtrl.navigateRoot('/login/reconnect', {
|
await CoreUtils.instance.ignoreErrors(this.navCtrl.navigateRoot('/login/reconnect', {
|
||||||
queryParams: CoreObject.removeUndefined({
|
queryParams: CoreObject.withoutEmpty({
|
||||||
siteId,
|
siteId,
|
||||||
pageName: data.pageName,
|
pageName: data.pageName,
|
||||||
pageParams: data.params,
|
pageParams: data.params,
|
||||||
|
@ -1127,7 +1144,7 @@ export class CoreLoginHelperProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If current page is already site policy, stop.
|
// If current page is already site policy, stop.
|
||||||
if (CoreNavHelper.instance.getCurrentPage() == '/login/sitepolicy') {
|
if (CoreNavigator.instance.isCurrent('/login/sitepolicy')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
<ion-tab-bar slot="bottom" [hidden]="hidden">
|
<ion-tab-bar slot="bottom" [hidden]="hidden">
|
||||||
<ion-spinner *ngIf="!loaded"></ion-spinner>
|
<ion-spinner *ngIf="!loaded"></ion-spinner>
|
||||||
|
|
||||||
<ion-tab-button tab="redirect" [disabled]="true" [hidden]="true"></ion-tab-button>
|
|
||||||
<!-- @todo: [root]="redirectPage" [rootParams]="redirectParams" -->
|
|
||||||
|
|
||||||
<ion-tab-button (ionTabButtonClick)="tabClicked($event, tab.page)" [hidden]="!loaded && tab.hide" *ngFor="let tab of tabs"
|
<ion-tab-button (ionTabButtonClick)="tabClicked($event, tab.page)" [hidden]="!loaded && tab.hide" *ngFor="let tab of tabs"
|
||||||
[tab]="tab.page" [disabled]="tab.hide" layout="label-hide" class="{{tab.class}}">
|
[tab]="tab.page" [disabled]="tab.hide" layout="label-hide" class="{{tab.class}}">
|
||||||
<ion-icon [name]="tab.icon"></ion-icon>
|
<ion-icon [name]="tab.icon"></ion-icon>
|
||||||
|
|
|
@ -13,19 +13,19 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { NavController, IonTabs } from '@ionic/angular';
|
import { NavController, IonTabs } from '@ionic/angular';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { CoreApp } from '@services/app';
|
import { CoreApp } from '@services/app';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreTextUtils } from '@services/utils/text';
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
import { CoreEvents, CoreEventObserver, CoreEventLoadPageMainMenuData } from '@singletons/events';
|
import { CoreEvents, CoreEventObserver } from '@singletons/events';
|
||||||
import { CoreMainMenu } from '../../services/mainmenu';
|
import { CoreMainMenu } from '../../services/mainmenu';
|
||||||
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../services/mainmenu-delegate';
|
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../services/mainmenu-delegate';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreRedirectPayload } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the main menu of the app.
|
* Page that displays the main menu of the app.
|
||||||
|
@ -40,17 +40,14 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
||||||
tabs: CoreMainMenuHandlerToDisplay[] = [];
|
tabs: CoreMainMenuHandlerToDisplay[] = [];
|
||||||
allHandlers?: CoreMainMenuHandlerToDisplay[];
|
allHandlers?: CoreMainMenuHandlerToDisplay[];
|
||||||
loaded = false;
|
loaded = false;
|
||||||
redirectPage?: string;
|
|
||||||
redirectParams?: Params;
|
|
||||||
showTabs = false;
|
showTabs = false;
|
||||||
tabsPlacement = 'bottom';
|
tabsPlacement = 'bottom';
|
||||||
hidden = false;
|
hidden = false;
|
||||||
|
|
||||||
protected subscription?: Subscription;
|
protected subscription?: Subscription;
|
||||||
protected redirectObs?: CoreEventObserver;
|
protected redirectObs?: CoreEventObserver;
|
||||||
protected pendingRedirect?: CoreEventLoadPageMainMenuData;
|
protected pendingRedirect?: CoreRedirectPayload;
|
||||||
protected urlToOpen?: string;
|
protected urlToOpen?: string;
|
||||||
protected mainMenuId: number;
|
|
||||||
protected keyboardObserver?: CoreEventObserver;
|
protected keyboardObserver?: CoreEventObserver;
|
||||||
|
|
||||||
@ViewChild('mainTabs') mainTabs?: IonTabs;
|
@ViewChild('mainTabs') mainTabs?: IonTabs;
|
||||||
|
@ -60,44 +57,32 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
||||||
protected navCtrl: NavController,
|
protected navCtrl: NavController,
|
||||||
protected changeDetector: ChangeDetectorRef,
|
protected changeDetector: ChangeDetectorRef,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
) {
|
) {}
|
||||||
this.mainMenuId = CoreNavHelper.instance.getMainMenuId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the component.
|
* Initialize the component.
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
// @TODO this should be handled by route guards and can be removed
|
||||||
if (!CoreSites.instance.isLoggedIn()) {
|
if (!CoreSites.instance.isLoggedIn()) {
|
||||||
this.navCtrl.navigateRoot('/login/init');
|
this.navCtrl.navigateRoot('/login/init');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.route.queryParams.subscribe(params => {
|
this.route.queryParams.subscribe((params: Partial<CoreRedirectPayload> & { urlToOpen?: string }) => {
|
||||||
const redirectPage = params['redirectPage'];
|
if (params.redirectPath) {
|
||||||
if (redirectPage) {
|
|
||||||
this.pendingRedirect = {
|
this.pendingRedirect = {
|
||||||
redirectPage: redirectPage,
|
redirectPath: params.redirectPath,
|
||||||
redirectParams: params['redirectParams'],
|
redirectParams: params.redirectParams,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.urlToOpen = params['urlToOpen'];
|
this.urlToOpen = params.urlToOpen;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showTabs = true;
|
this.showTabs = true;
|
||||||
|
|
||||||
this.redirectObs = CoreEvents.on(CoreEvents.LOAD_PAGE_MAIN_MENU, (data: CoreEventLoadPageMainMenuData) => {
|
|
||||||
if (!this.loaded) {
|
|
||||||
// View isn't ready yet, wait for it to be ready.
|
|
||||||
this.pendingRedirect = data;
|
|
||||||
} else {
|
|
||||||
delete this.pendingRedirect;
|
|
||||||
this.handleRedirect(data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.subscription = CoreMainMenuDelegate.instance.getHandlersObservable().subscribe((handlers) => {
|
this.subscription = CoreMainMenuDelegate.instance.getHandlersObservable().subscribe((handlers) => {
|
||||||
// Remove the handlers that should only appear in the More menu.
|
// Remove the handlers that should only appear in the More menu.
|
||||||
this.allHandlers = handlers.filter((handler) => !handler.onlyInMore);
|
this.allHandlers = handlers.filter((handler) => !handler.onlyInMore);
|
||||||
|
@ -131,8 +116,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreNavHelper.instance.setMainMenuOpen(this.mainMenuId, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,13 +184,13 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param data Data received.
|
* @param data Data received.
|
||||||
*/
|
*/
|
||||||
protected handleRedirect(data: CoreEventLoadPageMainMenuData): void {
|
protected handleRedirect(data: CoreRedirectPayload): void {
|
||||||
// Check if the redirect page is the root page of any of the tabs.
|
// Check if the redirect page is the root page of any of the tabs.
|
||||||
const i = this.tabs.findIndex((tab) => tab.page == data.redirectPage);
|
const i = this.tabs.findIndex((tab) => tab.page == data.redirectPath);
|
||||||
|
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
// Tab found. Open it with the params.
|
// Tab found. Open it with the params.
|
||||||
this.navCtrl.navigateForward(data.redirectPage, {
|
this.navCtrl.navigateForward(data.redirectPath, {
|
||||||
queryParams: data.redirectParams,
|
queryParams: data.redirectParams,
|
||||||
animated: false,
|
animated: false,
|
||||||
});
|
});
|
||||||
|
@ -227,7 +210,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
||||||
this.subscription?.unsubscribe();
|
this.subscription?.unsubscribe();
|
||||||
this.redirectObs?.off();
|
this.redirectObs?.off();
|
||||||
window.removeEventListener('resize', this.initHandlers.bind(this));
|
window.removeEventListener('resize', this.initHandlers.bind(this));
|
||||||
CoreNavHelper.instance.setMainMenuOpen(this.mainMenuId, false);
|
|
||||||
this.keyboardObserver?.off();
|
this.keyboardObserver?.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import { Injectable } from '@angular/core';
|
||||||
import { CoreApp } from '@services/app';
|
import { CoreApp } from '@services/app';
|
||||||
import { CoreLang } from '@services/lang';
|
import { CoreLang } from '@services/lang';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from './mainmenu-delegate';
|
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from './mainmenu-delegate';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
@ -42,20 +41,10 @@ export class CoreMainMenuProvider {
|
||||||
*
|
*
|
||||||
* @return Promise resolved with the current main menu handlers.
|
* @return Promise resolved with the current main menu handlers.
|
||||||
*/
|
*/
|
||||||
getCurrentMainMenuHandlers(): Promise<CoreMainMenuHandlerToDisplay[]> {
|
getCurrentMainMenuHandlers(): CoreMainMenuHandlerToDisplay[] {
|
||||||
const deferred = CoreUtils.instance.promiseDefer<CoreMainMenuHandlerToDisplay[]>();
|
return CoreMainMenuDelegate.instance.getHandlers()
|
||||||
|
.filter(handler => !handler.onlyInMore)
|
||||||
const subscription = CoreMainMenuDelegate.instance.getHandlersObservable().subscribe((handlers) => {
|
.slice(0, this.getNumItems());
|
||||||
subscription?.unsubscribe();
|
|
||||||
|
|
||||||
// Remove the handlers that should only appear in the More menu.
|
|
||||||
handlers = handlers.filter(handler => !handler.onlyInMore);
|
|
||||||
|
|
||||||
// Return main handlers.
|
|
||||||
deferred.resolve(handlers.slice(0, this.getNumItems()));
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreSiteHome } from '../sitehome';
|
import { CoreSiteHome } from '../sitehome';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to treat links to site home index.
|
* Handler to treat links to site home index.
|
||||||
|
@ -43,7 +43,8 @@ export class CoreSiteHomeIndexLinkHandlerService extends CoreContentLinksHandler
|
||||||
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
return [{
|
return [{
|
||||||
action: (siteId: string): void => {
|
action: (siteId: string): void => {
|
||||||
CoreNavHelper.instance.goInSite('sitehome', [], siteId);
|
// @todo This should open the 'sitehome' setting as well.
|
||||||
|
CoreNavigator.instance.navigateToSiteHome({ siteId });
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CoreTag } from '../tag';
|
import { CoreTag } from '../tag';
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ export class CoreTagIndexLinkHandlerService extends CoreContentLinksHandlerBase
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!pageParams.tagId && (!pageParams.tagName || !pageParams.collectionId)) {
|
if (!pageParams.tagId && (!pageParams.tagName || !pageParams.collectionId)) {
|
||||||
CoreNavHelper.instance.goInSite('/tag/search', {}, siteId);
|
CoreNavigator.instance.navigateToSitePath('/tag/search', { siteId });
|
||||||
} else if (pageParams.areaId) {
|
} else if (pageParams.areaId) {
|
||||||
CoreNavHelper.instance.goInSite('/tag/index-area', pageParams, siteId);
|
CoreNavigator.instance.navigateToSitePath('/tag/index-area', { params: pageParams, siteId });
|
||||||
} else {
|
} else {
|
||||||
CoreNavHelper.instance.goInSite('/tag/index', pageParams, siteId);
|
CoreNavigator.instance.navigateToSitePath('/tag/index', { params: pageParams, siteId });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CoreTag } from '../tag';
|
import { CoreTag } from '../tag';
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export class CoreTagSearchLinkHandlerService extends CoreContentLinksHandlerBase
|
||||||
query: params.query || '',
|
query: params.query || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
CoreNavHelper.instance.goInSite('/tag/search', pageParams, siteId);
|
CoreNavigator.instance.navigateToSitePath('/tag/search', { params: pageParams, siteId });
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { Params } from '@angular/router';
|
||||||
|
|
||||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreNavHelper } from '@services/nav-helper';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +54,7 @@ export class CoreUserProfileLinkHandlerService extends CoreContentLinksHandlerBa
|
||||||
userId: parseInt(params.id, 10),
|
userId: parseInt(params.id, 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
CoreNavHelper.instance.goInSite('/user', pageParams, siteId);
|
CoreNavigator.instance.navigateToSitePath('/user', { params: pageParams, siteId });
|
||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import { makeSingleton, Keyboard, Network, StatusBar, Platform, Device } from '@
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreColors } from '@singletons/colors';
|
import { CoreColors } from '@singletons/colors';
|
||||||
import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/database/app';
|
import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/database/app';
|
||||||
import { CoreNavHelper } from './nav-helper';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object responsible of managing schema versions.
|
* Object responsible of managing schema versions.
|
||||||
|
@ -178,10 +177,10 @@ export class CoreAppProvider {
|
||||||
* Get an ID for a main menu.
|
* Get an ID for a main menu.
|
||||||
*
|
*
|
||||||
* @return Main menu ID.
|
* @return Main menu ID.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.getMainMenuId instead.
|
* @deprecated since 3.9.5. No longer supported.
|
||||||
*/
|
*/
|
||||||
getMainMenuId(): number {
|
getMainMenuId(): number {
|
||||||
return CoreNavHelper.instance.getMainMenuId();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,10 +305,10 @@ export class CoreAppProvider {
|
||||||
* Check if the main menu is open.
|
* Check if the main menu is open.
|
||||||
*
|
*
|
||||||
* @return Whether the main menu is open.
|
* @return Whether the main menu is open.
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.isMainMenuOpen instead.
|
* @deprecated since 3.9.5. No longer supported.
|
||||||
*/
|
*/
|
||||||
isMainMenuOpen(): boolean {
|
isMainMenuOpen(): boolean {
|
||||||
return CoreNavHelper.instance.isMainMenuOpen();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,17 +444,6 @@ export class CoreAppProvider {
|
||||||
this.keyboardClosing = false;
|
this.keyboardClosing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a main menu as open or not.
|
|
||||||
*
|
|
||||||
* @param id Main menu ID.
|
|
||||||
* @param open Whether it's open or not.
|
|
||||||
* @deprecated since 3.9.5. Use CoreNavHelperService.setMainMenuOpen instead.
|
|
||||||
*/
|
|
||||||
setMainMenuOpen(id: number, open: boolean): void {
|
|
||||||
CoreNavHelper.instance.setMainMenuOpen(id, open);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an SSO authentication process.
|
* Start an SSO authentication process.
|
||||||
* Please notice that this function should be called when the app receives the new token from the browser,
|
* Please notice that this function should be called when the app receives the new token from the browser,
|
||||||
|
|
|
@ -1,364 +0,0 @@
|
||||||
// (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, Router } from '@angular/router';
|
|
||||||
import { CoreMainMenu } from '@features/mainmenu/services/mainmenu';
|
|
||||||
import { NavController } from '@ionic/angular';
|
|
||||||
import { NavigationOptions } from '@ionic/angular/providers/nav-controller';
|
|
||||||
|
|
||||||
import { makeSingleton } from '@singletons';
|
|
||||||
import { CoreEvents } from '@singletons/events';
|
|
||||||
import { CoreConstants } from '../constants';
|
|
||||||
import { CoreSites } from './sites';
|
|
||||||
import { CoreDomUtils } from './utils/dom';
|
|
||||||
import { CoreTextUtils } from './utils/text';
|
|
||||||
import { CoreUrlUtils } from './utils/url';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider to provide some helper functions regarding navigation.
|
|
||||||
*/
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class CoreNavHelperService {
|
|
||||||
|
|
||||||
static readonly OPEN_COURSE = 'open_course';
|
|
||||||
|
|
||||||
protected pageToLoad?: {page: string; params?: Params; time: number}; // Page to load once main menu is opened.
|
|
||||||
protected mainMenuOpen?: number;
|
|
||||||
protected mainMenuId = 0;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
protected router: Router,
|
|
||||||
protected navCtrl: NavController,
|
|
||||||
) {
|
|
||||||
CoreEvents.on(CoreEvents.MAIN_MENU_OPEN, () => {
|
|
||||||
/* If there is any page pending to be opened, do it now. Don't open pages stored more than 5 seconds ago, probably
|
|
||||||
the function to open the page was called when it shouldn't. */
|
|
||||||
if (this.pageToLoad && Date.now() - this.pageToLoad.time < 5000) {
|
|
||||||
this.loadPageInMainMenu(this.pageToLoad.page, this.pageToLoad.params);
|
|
||||||
delete this.pageToLoad;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current page route without params.
|
|
||||||
*
|
|
||||||
* @return Current page route.
|
|
||||||
*/
|
|
||||||
getCurrentPage(): string {
|
|
||||||
return CoreUrlUtils.instance.removeUrlParams(this.router.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a new page in the current main menu tab.
|
|
||||||
*
|
|
||||||
* @param page Page to open.
|
|
||||||
* @param pageParams Params to send to the page.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
async goInCurrentMainMenuTab(page: string, pageParams: Params): Promise<void> {
|
|
||||||
const currentPage = this.getCurrentPage();
|
|
||||||
|
|
||||||
const routeMatch = currentPage.match(/^\/main\/([^/]+)/);
|
|
||||||
if (!routeMatch || !routeMatch[0]) {
|
|
||||||
// Not in a tab. Stop.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = '';
|
|
||||||
if (routeMatch[1] && page.match(new RegExp(`^/${routeMatch[1]}(/|$)`))) {
|
|
||||||
path = CoreTextUtils.instance.concatenatePaths('/main', page);
|
|
||||||
} else {
|
|
||||||
path = CoreTextUtils.instance.concatenatePaths(routeMatch[0], page);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.navCtrl.navigateForward(path, {
|
|
||||||
queryParams: pageParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Goes to a certain page in a certain site. If the site is current site it will perform a regular navigation,
|
|
||||||
* otherwise it will load the other site and open the page in main menu.
|
|
||||||
*
|
|
||||||
* @param path Path to go.
|
|
||||||
* @param pageParams Params to send to the page.
|
|
||||||
* @param siteId Site ID. If not defined, current site.
|
|
||||||
* @param checkMenu If true, check if the root page is on a main menu tab. Only the path will be checked.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
async goInSite(path: string, pageParams: Params, siteId?: string, checkMenu?: boolean): Promise<void> {
|
|
||||||
|
|
||||||
siteId = siteId || CoreSites.instance.getCurrentSiteId();
|
|
||||||
|
|
||||||
// @todo: When this function was in ContentLinksHelper, this code was inside NgZone. Check if it's needed.
|
|
||||||
|
|
||||||
if (!CoreSites.instance.isLoggedIn() || siteId != CoreSites.instance.getCurrentSiteId()) {
|
|
||||||
await this.openInSiteMainMenu(path, pageParams, siteId);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkMenu) {
|
|
||||||
let isInMenu = false;
|
|
||||||
// Check if the page is in the main menu.
|
|
||||||
try {
|
|
||||||
isInMenu = await CoreMainMenu.instance.isCurrentMainMenuHandler(path);
|
|
||||||
} catch {
|
|
||||||
isInMenu = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInMenu) {
|
|
||||||
// Just select the tab. @todo test.
|
|
||||||
CoreNavHelper.instance.loadPageInMainMenu(path, pageParams);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.goInCurrentMainMenuTab(path, pageParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an ID for a main menu.
|
|
||||||
*
|
|
||||||
* @return Main menu ID.
|
|
||||||
*/
|
|
||||||
getMainMenuId(): number {
|
|
||||||
return this.mainMenuId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a page that doesn't belong to any site.
|
|
||||||
*
|
|
||||||
* @param page Page to open.
|
|
||||||
* @param params Params of the page.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
async goToNoSitePage(page: string, params?: Params): Promise<void> {
|
|
||||||
const currentPage = this.getCurrentPage();
|
|
||||||
|
|
||||||
if (currentPage == page) {
|
|
||||||
// Already at page, nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page == '/login/sites') {
|
|
||||||
// Just open the page as root.
|
|
||||||
await this.navCtrl.navigateRoot(page, { queryParams: params });
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page == '/login/credentials' && currentPage == '/login/site') {
|
|
||||||
// Just open the new page to keep the navigation history.
|
|
||||||
await this.navCtrl.navigateForward(page, { queryParams: params });
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there is any site stored.
|
|
||||||
const hasSites = await CoreSites.instance.hasSites();
|
|
||||||
|
|
||||||
if (!hasSites) {
|
|
||||||
// There are sites stored, open sites page first to be able to go back.
|
|
||||||
await this.navCtrl.navigateRoot('/login/sites');
|
|
||||||
|
|
||||||
await this.navCtrl.navigateForward(page, { queryParams: params });
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page != '/login/site') {
|
|
||||||
// Open the new site page to be able to go back.
|
|
||||||
await this.navCtrl.navigateRoot('/login/site');
|
|
||||||
|
|
||||||
await this.navCtrl.navigateForward(page, { queryParams: params });
|
|
||||||
} else {
|
|
||||||
// Just open the page as root.
|
|
||||||
await this.navCtrl.navigateRoot(page, { queryParams: params });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to the initial page of a site depending on 'userhomepage' setting.
|
|
||||||
*
|
|
||||||
* @param options Options.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
goToSiteInitialPage(options?: CoreNavHelperOpenMainMenuOptions): Promise<void> {
|
|
||||||
return this.openMainMenu(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the main menu is open.
|
|
||||||
*
|
|
||||||
* @return Whether the main menu is open.
|
|
||||||
*/
|
|
||||||
isMainMenuOpen(): boolean {
|
|
||||||
return typeof this.mainMenuOpen != 'undefined';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a certain page in the main menu.
|
|
||||||
*
|
|
||||||
* @param page Route of the page to load.
|
|
||||||
* @param params Params to pass to the page.
|
|
||||||
*/
|
|
||||||
loadPageInMainMenu(page: string, params?: Params): void {
|
|
||||||
if (!this.isMainMenuOpen()) {
|
|
||||||
// Main menu not open. Store the page to be loaded later.
|
|
||||||
this.pageToLoad = {
|
|
||||||
page: page,
|
|
||||||
params: params,
|
|
||||||
time: Date.now(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page == CoreNavHelperService.OPEN_COURSE) {
|
|
||||||
// @todo Use the openCourse function.
|
|
||||||
} else {
|
|
||||||
CoreEvents.trigger(CoreEvents.LOAD_PAGE_MAIN_MENU, { redirectPage: page, redirectParams: params });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a site and load a certain page in that site.
|
|
||||||
*
|
|
||||||
* @param siteId Site to load.
|
|
||||||
* @param page Name of the page to load.
|
|
||||||
* @param params Params to pass to the page.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async loadSiteAndPage(siteId: string, page: string, params?: Params): Promise<void> {
|
|
||||||
if (siteId == CoreConstants.NO_SITE_ID) {
|
|
||||||
// Page doesn't belong to a site, just load the page.
|
|
||||||
await this.navCtrl.navigateRoot(page, params);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const loggedIn = await CoreSites.instance.loadSite(siteId, page, params);
|
|
||||||
|
|
||||||
if (!loggedIn) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.openMainMenu({
|
|
||||||
redirectPage: page,
|
|
||||||
redirectParams: params,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
// Site doesn't exist.
|
|
||||||
await this.navCtrl.navigateRoot('/login/sites');
|
|
||||||
} finally {
|
|
||||||
modal.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the main menu, loading a certain page.
|
|
||||||
*
|
|
||||||
* @param options Options.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async openMainMenu(options?: CoreNavHelperOpenMainMenuOptions): Promise<void> {
|
|
||||||
|
|
||||||
// Due to DeepLinker, we need to remove the path from the URL before going to main menu.
|
|
||||||
// IonTabs checks the URL to determine which path to load for deep linking, so we clear the URL.
|
|
||||||
// @todo this.location.replaceState('');
|
|
||||||
|
|
||||||
if (options?.redirectPage == CoreNavHelperService.OPEN_COURSE) {
|
|
||||||
// Load the main menu first, and then open the course.
|
|
||||||
try {
|
|
||||||
await this.navCtrl.navigateRoot('/');
|
|
||||||
} finally {
|
|
||||||
// @todo: Open course.
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Open the main menu.
|
|
||||||
const queryParams: Params = Object.assign({}, options);
|
|
||||||
delete queryParams.navigationOptions;
|
|
||||||
|
|
||||||
await this.navCtrl.navigateRoot('/', {
|
|
||||||
queryParams,
|
|
||||||
...options?.navigationOptions,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a new page, setting it as the root page and loading the right site if needed.
|
|
||||||
*
|
|
||||||
* @param page Name of the page to load. Special cases: OPEN_COURSE (to open course page).
|
|
||||||
* @param params Params to pass to the page.
|
|
||||||
* @param siteId Site to load. If not defined, current site.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
async openInSiteMainMenu(page: string, params?: Params, siteId?: string): Promise<void> {
|
|
||||||
siteId = siteId || CoreSites.instance.getCurrentSiteId();
|
|
||||||
|
|
||||||
if (!CoreSites.instance.isLoggedIn()) {
|
|
||||||
if (siteId) {
|
|
||||||
await this.loadSiteAndPage(siteId, page, params);
|
|
||||||
} else {
|
|
||||||
await this.navCtrl.navigateRoot('/login/sites');
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (siteId && siteId != CoreSites.instance.getCurrentSiteId()) {
|
|
||||||
// Target page belongs to a different site. Change site.
|
|
||||||
// @todo: Check site plugins.
|
|
||||||
await CoreSites.instance.logout();
|
|
||||||
|
|
||||||
await this.loadSiteAndPage(siteId, page, params);
|
|
||||||
} else {
|
|
||||||
// Current page, open it in main menu.
|
|
||||||
this.loadPageInMainMenu(page, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a main menu as open or not.
|
|
||||||
*
|
|
||||||
* @param id Main menu ID.
|
|
||||||
* @param open Whether it's open or not.
|
|
||||||
*/
|
|
||||||
setMainMenuOpen(id: number, open: boolean): void {
|
|
||||||
if (open) {
|
|
||||||
this.mainMenuOpen = id;
|
|
||||||
CoreEvents.trigger(CoreEvents.MAIN_MENU_OPEN);
|
|
||||||
} else if (this.mainMenuOpen == id) {
|
|
||||||
delete this.mainMenuOpen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CoreNavHelper extends makeSingleton(CoreNavHelperService) {}
|
|
||||||
|
|
||||||
export type CoreNavHelperOpenMainMenuOptions = {
|
|
||||||
redirectPage?: string; // Route of the page to open in main menu. If not defined, default tab will be selected.
|
|
||||||
redirectParams?: Params; // Params to pass to the selected tab if any.
|
|
||||||
urlToOpen?: string; // URL to open once the main menu is loaded.
|
|
||||||
navigationOptions?: NavigationOptions; // Navigation options.
|
|
||||||
};
|
|
|
@ -0,0 +1,247 @@
|
||||||
|
// (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 { ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
import { NavigationOptions } from '@ionic/angular/providers/nav-controller';
|
||||||
|
|
||||||
|
import { CoreConstants } from '@/core/constants';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreMainMenu } from '@features/mainmenu/services/mainmenu';
|
||||||
|
import { CoreMainMenuHomeHandlerService } from '@features/mainmenu/services/handlers/mainmenu';
|
||||||
|
import { CoreObject } from '@singletons/object';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { CoreUrlUtils } from '@services/utils/url';
|
||||||
|
import { makeSingleton, NavController, Router } from '@singletons';
|
||||||
|
|
||||||
|
const DEFAULT_MAIN_MENU_TAB = CoreMainMenuHomeHandlerService.PAGE_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect payload.
|
||||||
|
*/
|
||||||
|
export type CoreRedirectPayload = {
|
||||||
|
redirectPath: string;
|
||||||
|
redirectParams?: Params;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation options.
|
||||||
|
*/
|
||||||
|
export type CoreNavigationOptions = {
|
||||||
|
animated?: boolean;
|
||||||
|
params?: Params;
|
||||||
|
reset?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to provide some helper functions regarding navigation.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class CoreNavigatorService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the active route is using the given path.
|
||||||
|
*
|
||||||
|
* @param path Path.
|
||||||
|
* @return Whether the active route is using the given path.
|
||||||
|
*/
|
||||||
|
isCurrent(path: string): boolean {
|
||||||
|
return this.getCurrentPath() === path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current main menu tab.
|
||||||
|
*
|
||||||
|
* @return Current main menu tab or null if the current route is not using the main menu.
|
||||||
|
*/
|
||||||
|
getCurrentMainMenuTab(): string | null {
|
||||||
|
const currentPath = this.getCurrentPath();
|
||||||
|
const matches = /^\/main\/([^/]+).*$/.exec(currentPath);
|
||||||
|
|
||||||
|
return matches?.[1] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to a new path.
|
||||||
|
*
|
||||||
|
* @param path Path to navigate to.
|
||||||
|
* @param options Navigation options.
|
||||||
|
* @return Whether navigation suceeded.
|
||||||
|
*/
|
||||||
|
async navigate(path: string, options: CoreNavigationOptions = {}): Promise<boolean> {
|
||||||
|
const url: string[] = [/^[./]/.test(path) ? path : `./${path}`];
|
||||||
|
const navigationOptions: NavigationOptions = CoreObject.withoutEmpty({
|
||||||
|
animated: options.animated,
|
||||||
|
queryParams: CoreObject.isEmpty(options.params ?? {}) ? null : options.params,
|
||||||
|
relativeTo: path.startsWith('/') ? null : this.getCurrentRoute(),
|
||||||
|
});
|
||||||
|
const navigationResult = (options.reset ?? false)
|
||||||
|
? await NavController.instance.navigateRoot(url, navigationOptions)
|
||||||
|
: await NavController.instance.navigateForward(url, navigationOptions);
|
||||||
|
|
||||||
|
return navigationResult !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to the login credentials route.
|
||||||
|
*
|
||||||
|
* @param params Page params.
|
||||||
|
* @return Whether navigation suceeded.
|
||||||
|
*/
|
||||||
|
async navigateToLoginCredentials(params: Params = {}): Promise<boolean> {
|
||||||
|
// If necessary, open the previous path to keep the navigation history.
|
||||||
|
if (!this.isCurrent('/login/site') && !this.isCurrent('/login/sites')) {
|
||||||
|
const hasSites = await CoreSites.instance.hasSites();
|
||||||
|
|
||||||
|
await this.navigate(hasSites ? '/login/sites' : '/login/site', { reset: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to login credentials page.
|
||||||
|
return this.navigate('/login/credentials', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to the home route of the current site.
|
||||||
|
*
|
||||||
|
* @param options Navigation options.
|
||||||
|
* @return Whether navigation suceeded.
|
||||||
|
*/
|
||||||
|
async navigateToSiteHome(options: Omit<CoreNavigationOptions, 'reset'> & { siteId?: string } = {}): Promise<boolean> {
|
||||||
|
return this.navigateToSitePath(DEFAULT_MAIN_MENU_TAB, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to a site path, loading the site if necessary.
|
||||||
|
*
|
||||||
|
* @param path Site path to visit.
|
||||||
|
* @param options Navigation and site options.
|
||||||
|
* @return Whether navigation suceeded.
|
||||||
|
*/
|
||||||
|
async navigateToSitePath(
|
||||||
|
path: string,
|
||||||
|
options: Omit<CoreNavigationOptions, 'reset'> & { siteId?: string } = {},
|
||||||
|
): Promise<boolean> {
|
||||||
|
const siteId = options.siteId ?? CoreSites.instance.getCurrentSiteId();
|
||||||
|
const navigationOptions: CoreNavigationOptions = CoreObject.without(options, ['siteId']);
|
||||||
|
|
||||||
|
// @todo: When this function was in ContentLinksHelper, this code was inside NgZone. Check if it's needed.
|
||||||
|
|
||||||
|
// If the path doesn't belong to a site, call standard navigation.
|
||||||
|
if (siteId === CoreConstants.NO_SITE_ID) {
|
||||||
|
return this.navigate(path, {
|
||||||
|
...navigationOptions,
|
||||||
|
reset: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are logged into a different site, log out first.
|
||||||
|
if (CoreSites.instance.isLoggedIn() && CoreSites.instance.getCurrentSiteId() !== siteId) {
|
||||||
|
// @todo: Check site plugins and store redirect.
|
||||||
|
|
||||||
|
await CoreSites.instance.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are not logged into the site, load the site.
|
||||||
|
if (!CoreSites.instance.isLoggedIn()) {
|
||||||
|
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const loggedIn = await CoreSites.instance.loadSite(siteId, path, options.params);
|
||||||
|
|
||||||
|
if (!loggedIn) {
|
||||||
|
// User has been redirected to the login page and will be redirected to the site path after login.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Site doesn't exist.
|
||||||
|
return this.navigate('/login/sites', { reset: true });
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// User is logged in, navigate to the site path.
|
||||||
|
return this.navigateToMainMenuPath(path, navigationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the active route path.
|
||||||
|
*
|
||||||
|
* @return Current path.
|
||||||
|
*/
|
||||||
|
protected getCurrentPath(): string {
|
||||||
|
return CoreUrlUtils.instance.removeUrlParams(Router.instance.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current activated route.
|
||||||
|
*
|
||||||
|
* @param route Parent route.
|
||||||
|
* @return Current activated route.
|
||||||
|
*/
|
||||||
|
protected getCurrentRoute(route?: ActivatedRoute): ActivatedRoute {
|
||||||
|
route = route ?? Router.instance.routerState.root;
|
||||||
|
|
||||||
|
return route.children.length === 0 ? route : this.getCurrentRoute(route.children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to a path within the main menu.
|
||||||
|
* If the path belongs to a visible tab, that tab will be selected.
|
||||||
|
* If it doesn't, the current tab or the default tab will be used instead.
|
||||||
|
*
|
||||||
|
* @param options Navigation options.
|
||||||
|
* @return Whether navigation suceeded.
|
||||||
|
*/
|
||||||
|
protected async navigateToMainMenuPath(path: string, options: Omit<CoreNavigationOptions, 'reset'> = {}): Promise<boolean> {
|
||||||
|
// Due to DeepLinker, we need to remove the path from the URL before going to main menu.
|
||||||
|
// IonTabs checks the URL to determine which path to load for deep linking, so we clear the URL.
|
||||||
|
// @todo this.location.replaceState('');
|
||||||
|
|
||||||
|
path = path.replace(/^(\.|\/main)?\//, '');
|
||||||
|
|
||||||
|
// Open the path within the corresponding main tab.
|
||||||
|
const pathRoot = /^[^/]+/.exec(path)?.[0] ?? '';
|
||||||
|
const isCurrentMainMenuHandler = await CoreUtils.instance.ignoreErrors(
|
||||||
|
CoreMainMenu.instance.isCurrentMainMenuHandler(pathRoot),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isCurrentMainMenuHandler) {
|
||||||
|
return this.navigate(`/main/${path}`, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the path within the current main tab.
|
||||||
|
const currentMainMenuTab = this.getCurrentMainMenuTab();
|
||||||
|
|
||||||
|
if (currentMainMenuTab) {
|
||||||
|
return this.navigate(`/main/${currentMainMenuTab}/${path}`, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the path within the default main tab.
|
||||||
|
// @todo test that this is working as expected
|
||||||
|
return this.navigate(`/main/${DEFAULT_MAIN_MENU_TAB}`, {
|
||||||
|
...options,
|
||||||
|
params: {
|
||||||
|
redirectPath: `/main/${DEFAULT_MAIN_MENU_TAB}/${path}`,
|
||||||
|
redirectParams: options.params,
|
||||||
|
} as CoreRedirectPayload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CoreNavigator extends makeSingleton(CoreNavigatorService) {}
|
|
@ -0,0 +1,154 @@
|
||||||
|
// (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 { NavController as NavControllerService } from '@ionic/angular';
|
||||||
|
|
||||||
|
import { mock, mockSingleton } from '@/testing/utils';
|
||||||
|
|
||||||
|
import { CoreNavigatorService } from '@services/navigator';
|
||||||
|
import { CoreUtils, CoreUtilsProvider } from '@services/utils/utils';
|
||||||
|
import { CoreUrlUtils, CoreUrlUtilsProvider } from '@services/utils/url';
|
||||||
|
import { NavController, Router } from '@singletons';
|
||||||
|
import { ActivatedRoute, RouterState } from '@angular/router';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreMainMenu } from '@features/mainmenu/services/mainmenu';
|
||||||
|
|
||||||
|
describe('CoreNavigator', () => {
|
||||||
|
|
||||||
|
let router: {
|
||||||
|
url?: string;
|
||||||
|
routerState?: Partial<RouterState>;
|
||||||
|
};
|
||||||
|
let currentMainMenuHandlers: string[];
|
||||||
|
let navigator: CoreNavigatorService;
|
||||||
|
let navControllerMock: NavControllerService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
router = { url: '/' };
|
||||||
|
currentMainMenuHandlers = ['home'];
|
||||||
|
navigator = new CoreNavigatorService();
|
||||||
|
navControllerMock = mockSingleton(NavController, ['navigateRoot', 'navigateForward']);
|
||||||
|
|
||||||
|
mockSingleton(Router, router);
|
||||||
|
mockSingleton(CoreUtils, new CoreUtilsProvider(mock()));
|
||||||
|
mockSingleton(CoreUrlUtils, new CoreUrlUtilsProvider());
|
||||||
|
mockSingleton(CoreSites, { getCurrentSiteId: () => 42, isLoggedIn: () => true });
|
||||||
|
mockSingleton(CoreMainMenu, { isCurrentMainMenuHandler: path => Promise.resolve(currentMainMenuHandlers.includes(path)) });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches against current path', () => {
|
||||||
|
router.url = '/main/foo';
|
||||||
|
|
||||||
|
expect(navigator.isCurrent('/main/foo')).toBe(true);
|
||||||
|
expect(navigator.isCurrent('/main')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gets the current main menu tab', () => {
|
||||||
|
expect(navigator.getCurrentMainMenuTab()).toBeNull();
|
||||||
|
|
||||||
|
router.url = '/main/foo';
|
||||||
|
expect(navigator.getCurrentMainMenuTab()).toBe('foo');
|
||||||
|
|
||||||
|
router.url = '/main/foo/bar';
|
||||||
|
expect(navigator.getCurrentMainMenuTab()).toBe('foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to absolute paths', async () => {
|
||||||
|
const success = await navigator.navigate('/main/foo/bar', { reset: true });
|
||||||
|
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateRoot).toHaveBeenCalledWith(['/main/foo/bar'], {});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to relative paths', async () => {
|
||||||
|
// Arrange.
|
||||||
|
const mainOutletRoute = { routeConfig: { path: 'foo' }, children: [] };
|
||||||
|
const primaryOutletRoute = { routeConfig: { path: 'main' }, children: [mainOutletRoute] };
|
||||||
|
const rootRoute = { children: [primaryOutletRoute] };
|
||||||
|
|
||||||
|
router.routerState = { root: rootRoute as unknown as ActivatedRoute };
|
||||||
|
|
||||||
|
// Act.
|
||||||
|
const success = await navigator.navigate('./bar');
|
||||||
|
|
||||||
|
// Assert.
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith(['./bar'], { relativeTo: mainOutletRoute });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to site paths', async () => {
|
||||||
|
// Arrange
|
||||||
|
router.url = '/main/foo';
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const success = await navigator.navigateToSitePath('/user/42');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith(['/main/foo/user/42'], {});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to site paths using tabs', async () => {
|
||||||
|
// Arrange
|
||||||
|
currentMainMenuHandlers.push('users');
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const success = await navigator.navigateToSitePath('/users/user/42');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith(['/main/users/user/42'], {});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to site paths using the default tab', async () => {
|
||||||
|
const success = await navigator.navigateToSitePath('/user/42');
|
||||||
|
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith(['/main/home'], {
|
||||||
|
queryParams: {
|
||||||
|
redirectPath: '/main/home/user/42',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to site paths ussing different path formats', async () => {
|
||||||
|
currentMainMenuHandlers.push('users');
|
||||||
|
|
||||||
|
const assertNavigation = async (currentPath, sitePath, expectedPath) => {
|
||||||
|
router.url = currentPath;
|
||||||
|
|
||||||
|
const success = await navigator.navigateToSitePath(sitePath);
|
||||||
|
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith([expectedPath], {});
|
||||||
|
};
|
||||||
|
|
||||||
|
await assertNavigation('/main/users', '/main/users/user/42', '/main/users/user/42');
|
||||||
|
await assertNavigation('/main/users', '/users/user/42', '/main/users/user/42');
|
||||||
|
await assertNavigation('/main/users', '/user/42', '/main/users/user/42');
|
||||||
|
await assertNavigation('/main/home', '/users/user/42', '/main/users/user/42');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('navigates to site home', async () => {
|
||||||
|
const success = await navigator.navigateToSiteHome();
|
||||||
|
|
||||||
|
expect(success).toBe(true);
|
||||||
|
expect(navControllerMock.navigateForward).toHaveBeenCalledWith(['/main/home'], {});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.todo('navigates to a different site');
|
||||||
|
it.todo('navigates to login credentials');
|
||||||
|
it.todo('navigates to NO_SITE_ID site');
|
||||||
|
|
||||||
|
});
|
|
@ -1580,15 +1580,19 @@ export class CoreUtilsProvider {
|
||||||
* Ignore errors from a promise.
|
* Ignore errors from a promise.
|
||||||
*
|
*
|
||||||
* @param promise Promise to ignore errors.
|
* @param promise Promise to ignore errors.
|
||||||
* @return Promise with ignored errors.
|
* @param fallbackResult Value to return if the promise is rejected.
|
||||||
|
* @return Promise with ignored errors, resolving to the fallback result if provided.
|
||||||
*/
|
*/
|
||||||
async ignoreErrors<T>(promise: Promise<T>): Promise<T | undefined> {
|
async ignoreErrors<Result>(promise: Promise<Result>): Promise<Result | undefined>;
|
||||||
|
async ignoreErrors<Result, Fallback>(promise: Promise<Result>, fallback: Fallback): Promise<Result | Fallback>;
|
||||||
|
async ignoreErrors<Result, Fallback>(promise: Promise<Result>, fallback?: Fallback): Promise<Result | Fallback | undefined> {
|
||||||
try {
|
try {
|
||||||
const result = await promise;
|
const result = await promise;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
|
return fallback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,7 @@ export class CoreEvents {
|
||||||
static readonly KEYBOARD_CHANGE = 'keyboard_change';
|
static readonly KEYBOARD_CHANGE = 'keyboard_change';
|
||||||
static readonly CORE_LOADING_CHANGED = 'core_loading_changed';
|
static readonly CORE_LOADING_CHANGED = 'core_loading_changed';
|
||||||
static readonly ORIENTATION_CHANGE = 'orientation_change';
|
static readonly ORIENTATION_CHANGE = 'orientation_change';
|
||||||
static readonly LOAD_PAGE_MAIN_MENU = 'load_page_main_menu';
|
|
||||||
static readonly SEND_ON_ENTER_CHANGED = 'send_on_enter_changed';
|
static readonly SEND_ON_ENTER_CHANGED = 'send_on_enter_changed';
|
||||||
static readonly MAIN_MENU_OPEN = 'main_menu_open';
|
|
||||||
static readonly SELECT_COURSE_TAB = 'select_course_tab';
|
static readonly SELECT_COURSE_TAB = 'select_course_tab';
|
||||||
static readonly WS_CACHE_INVALIDATED = 'ws_cache_invalidated';
|
static readonly WS_CACHE_INVALIDATED = 'ws_cache_invalidated';
|
||||||
static readonly SITE_STORAGE_DELETED = 'site_storage_deleted';
|
static readonly SITE_STORAGE_DELETED = 'site_storage_deleted';
|
||||||
|
@ -227,14 +225,6 @@ export type CoreEventLoadingChangedData = {
|
||||||
uniqueId: string;
|
uniqueId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Data passed to LOAD_PAGE_MAIN_MENU event.
|
|
||||||
*/
|
|
||||||
export type CoreEventLoadPageMainMenuData = {
|
|
||||||
redirectPage: string;
|
|
||||||
redirectParams?: Params;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data passed to COURSE_STATUS_CHANGED event.
|
* Data passed to COURSE_STATUS_CHANGED event.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { ApplicationRef, ApplicationInitStatus, Injector, NgZone as NgZoneService, Type } from '@angular/core';
|
import { ApplicationRef, ApplicationInitStatus, Injector, NgZone as NgZoneService, Type } from '@angular/core';
|
||||||
|
import { Router as RouterService } from '@angular/router';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -23,6 +24,7 @@ import {
|
||||||
ToastController as ToastControllerService,
|
ToastController as ToastControllerService,
|
||||||
GestureController as GestureControllerService,
|
GestureController as GestureControllerService,
|
||||||
ActionSheetController as ActionSheetControllerService,
|
ActionSheetController as ActionSheetControllerService,
|
||||||
|
NavController as NavControllerService,
|
||||||
} from '@ionic/angular';
|
} from '@ionic/angular';
|
||||||
|
|
||||||
import { Badge as BadgeService } from '@ionic-native/badge/ngx';
|
import { Badge as BadgeService } from '@ionic-native/badge/ngx';
|
||||||
|
@ -150,6 +152,8 @@ export class ToastController extends makeSingleton(ToastControllerService) {}
|
||||||
export class GestureController extends makeSingleton(GestureControllerService) {}
|
export class GestureController extends makeSingleton(GestureControllerService) {}
|
||||||
export class ApplicationInit extends makeSingleton(ApplicationInitStatus) {}
|
export class ApplicationInit extends makeSingleton(ApplicationInitStatus) {}
|
||||||
export class Application extends makeSingleton(ApplicationRef) {}
|
export class Application extends makeSingleton(ApplicationRef) {}
|
||||||
|
export class NavController extends makeSingleton(NavControllerService) {}
|
||||||
|
export class Router extends makeSingleton(RouterService) {}
|
||||||
|
|
||||||
// Convert external libraries injectables.
|
// Convert external libraries injectables.
|
||||||
export class Translate extends makeSingleton(TranslateService) {}
|
export class Translate extends makeSingleton(TranslateService) {}
|
||||||
|
|
|
@ -12,24 +12,60 @@
|
||||||
// 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.
|
||||||
|
|
||||||
|
export type CoreObjectWithoutEmpty<T> = {
|
||||||
|
[k in keyof T]: T[k] extends undefined | null ? never : T[k];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for objects.
|
* Singleton with helper functions for objects.
|
||||||
*/
|
*/
|
||||||
export class CoreObject {
|
export class CoreObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all keys from an object whose value are null or undefined.
|
* Check whether the given object is empty.
|
||||||
*
|
*
|
||||||
* @param object Object to modify.
|
* @param object Object.
|
||||||
|
* @return Whether the given object is empty.
|
||||||
*/
|
*/
|
||||||
static removeUndefined<T>(object: T): T {
|
static isEmpty(object: Record<string, unknown>): boolean {
|
||||||
for (const name in object) {
|
return Object.keys(object).length === 0;
|
||||||
if (object[name] === undefined) {
|
}
|
||||||
delete object[name];
|
|
||||||
}
|
/**
|
||||||
|
* Create a new object without the specified keys.
|
||||||
|
*
|
||||||
|
* @param obj Object.
|
||||||
|
* @param keys Keys to remove from the new object.
|
||||||
|
* @return New object without the specified keys.
|
||||||
|
*/
|
||||||
|
static without<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, keyof { [k in K]: unknown }> {
|
||||||
|
const newObject: T = { ...obj };
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
delete newObject[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new object without empty values (null or undefined).
|
||||||
|
*
|
||||||
|
* @param obj Objet.
|
||||||
|
* @return New object without empty values.
|
||||||
|
*/
|
||||||
|
static withoutEmpty<T>(obj: T): CoreObjectWithoutEmpty<T> {
|
||||||
|
const cleanObj = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanObj[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanObj as CoreObjectWithoutEmpty<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,22 +47,26 @@ export function mock<T>(
|
||||||
return instance as T;
|
return instance as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockSingleton(singletonClass: CoreSingletonClass<unknown>, instance?: Record<string, unknown>): void;
|
export function mockSingleton<T>(singletonClass: CoreSingletonClass<T>, instance: T): T;
|
||||||
export function mockSingleton(
|
export function mockSingleton<T>(singletonClass: CoreSingletonClass<unknown>, instance?: Record<string, unknown>): T;
|
||||||
|
export function mockSingleton<T>(
|
||||||
singletonClass: CoreSingletonClass<unknown>,
|
singletonClass: CoreSingletonClass<unknown>,
|
||||||
methods: string[],
|
methods: string[],
|
||||||
instance?: Record<string, unknown>,
|
instance?: Record<string, unknown>,
|
||||||
): void;
|
): T;
|
||||||
export function mockSingleton(
|
export function mockSingleton<T>(
|
||||||
singletonClass: CoreSingletonClass<unknown>,
|
singletonClass: CoreSingletonClass<T>,
|
||||||
methodsOrInstance: string[] | Record<string, unknown> = [],
|
methodsOrInstance: string[] | Record<string, unknown> = [],
|
||||||
instance: Record<string, unknown> = {},
|
instance: Record<string, unknown> = {},
|
||||||
): void {
|
): T {
|
||||||
instance = Array.isArray(methodsOrInstance) ? instance : methodsOrInstance;
|
instance = Array.isArray(methodsOrInstance) ? instance : methodsOrInstance;
|
||||||
|
|
||||||
const methods = Array.isArray(methodsOrInstance) ? methodsOrInstance : [];
|
const methods = Array.isArray(methodsOrInstance) ? methodsOrInstance : [];
|
||||||
|
const mockInstance = mock<T>(methods, instance);
|
||||||
|
|
||||||
singletonClass.setInstance(mock(methods, instance));
|
singletonClass.setInstance(mockInstance);
|
||||||
|
|
||||||
|
return mockInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renderComponent<T>(component: Type<T>, config: Partial<RenderConfig> = {}): Promise<ComponentFixture<T>> {
|
export async function renderComponent<T>(component: Type<T>, config: Partial<RenderConfig> = {}): Promise<ComponentFixture<T>> {
|
||||||
|
|
Loading…
Reference in New Issue