diff --git a/src/app/app.component.html b/src/app/app.component.html
index 94c506c21..9b06aaff5 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,5 +1,3 @@
-
-
diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts
index 041f192de..f48fae07b 100644
--- a/src/core/classes/tabs.ts
+++ b/src/core/classes/tabs.ts
@@ -520,12 +520,12 @@ export class CoreTabsBaseComponent implements OnInit, Aft
* @return Promise resolved when done.
*/
async selectByIndex(index: number, e?: Event): Promise {
+ e?.preventDefault();
+ e?.stopPropagation();
+
if (index < 0 || index >= this.tabs.length) {
if (this.selected) {
// Invalid index do not change tab.
- e?.preventDefault();
- e?.stopPropagation();
-
return;
}
@@ -536,9 +536,6 @@ export class CoreTabsBaseComponent implements OnInit, Aft
const tabToSelect = this.tabs[index];
if (!tabToSelect || !tabToSelect.enabled || tabToSelect.id == this.selected) {
// Already selected or not enabled.
- e?.preventDefault();
- e?.stopPropagation();
-
return;
}
diff --git a/src/core/components/split-view/split-view.ts b/src/core/components/split-view/split-view.ts
index 101719d7d..75868e2d1 100644
--- a/src/core/components/split-view/split-view.ts
+++ b/src/core/components/split-view/split-view.ts
@@ -18,7 +18,7 @@ import { IonRouterOutlet } from '@ionic/angular';
import { CoreScreen } from '@services/screen';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
-enum CoreSplitViewMode {
+export enum CoreSplitViewMode {
MenuOnly = 'menu-only', // Hides content.
ContentOnly = 'content-only', // Hides menu.
MenuAndContent = 'menu-and-content', // Shows both menu and content.
@@ -34,6 +34,7 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
@ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet;
@HostBinding('class') classes = '';
@Input() placeholderText = 'core.emptysplit';
+ @Input() mode?: CoreSplitViewMode;
isNested = false;
private outletRouteSubject: BehaviorSubject = new BehaviorSubject(null);
@@ -100,6 +101,10 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
* @return Split view mode.
*/
private getCurrentMode(): CoreSplitViewMode {
+ if (this.mode) {
+ return this.mode;
+ }
+
if (this.isNested) {
return CoreSplitViewMode.MenuOnly;
}
diff --git a/src/core/components/tabs-outlet/tabs-outlet.ts b/src/core/components/tabs-outlet/tabs-outlet.ts
index d4df2c488..7567f4619 100644
--- a/src/core/components/tabs-outlet/tabs-outlet.ts
+++ b/src/core/components/tabs-outlet/tabs-outlet.ts
@@ -43,8 +43,8 @@ import { CoreTabBase, CoreTabsBaseComponent } from '@classes/tabs';
*
* Tab contents will only be shown if that tab is selected.
*
- * @todo: Test behaviour when tabs are added late.
* @todo: Test RTL and tab history.
+ * @todo: This should behave like the split-view in relation to routing (maybe we could reuse some code from CoreItemsListManager).
*/
@Component({
selector: 'core-tabs-outlet',
diff --git a/src/core/features/course/pages/index/index.ts b/src/core/features/course/pages/index/index.ts
index 9c5b834e4..3723a5360 100644
--- a/src/core/features/course/pages/index/index.ts
+++ b/src/core/features/course/pages/index/index.ts
@@ -115,7 +115,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
// Load the course handlers.
const handlers = await CoreCourseOptionsDelegate.instance.getHandlersToDisplay(this.course!, false, false);
- this.tabs.concat(handlers.map(handler => handler.data));
+ this.tabs = [...this.tabs, ...handlers.map(handler => handler.data)];
let tabToLoad: number | undefined;
diff --git a/src/core/features/grades/grades-course-lazy.module.ts b/src/core/features/grades/grades-course-lazy.module.ts
new file mode 100644
index 000000000..e6164e920
--- /dev/null
+++ b/src/core/features/grades/grades-course-lazy.module.ts
@@ -0,0 +1,38 @@
+// (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 { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CoreGradesCoursePage } from './pages/course/course.page';
+import { CoreGradesCoursePageModule } from './pages/course/course.module';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: CoreGradesCoursePage,
+ data: {
+ useSplitView: false,
+ outsideGradesTab: true,
+ },
+ },
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(routes),
+ CoreGradesCoursePageModule,
+ ],
+})
+export class CoreGradesCourseLazyModule {}
diff --git a/src/core/features/grades/grades-lazy.module.ts b/src/core/features/grades/grades-lazy.module.ts
index 5b22bbb13..5a4ac60e5 100644
--- a/src/core/features/grades/grades-lazy.module.ts
+++ b/src/core/features/grades/grades-lazy.module.ts
@@ -18,13 +18,14 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
-import { CoreSharedModule } from '@/core/shared.module';
+import { conditionalRoutes } from '@/app/app-routing.module';
import { CoreScreen } from '@services/screen';
+import { CoreSharedModule } from '@/core/shared.module';
-import { CoreGradesCoursePage } from './pages/course/course';
+import { CoreGradesCoursePage } from './pages/course/course.page';
+import { CoreGradesCoursePageModule } from './pages/course/course.module';
import { CoreGradesCoursesPage } from './pages/courses/courses';
import { CoreGradesGradePage } from './pages/grade/grade';
-import { conditionalRoutes } from '@/app/app-routing.module';
const mobileRoutes: Routes = [
{
@@ -76,10 +77,10 @@ const routes: Routes = [
IonicModule,
TranslateModule.forChild(),
CoreSharedModule,
+ CoreGradesCoursePageModule,
],
declarations: [
CoreGradesCoursesPage,
- CoreGradesCoursePage,
CoreGradesGradePage,
],
})
diff --git a/src/core/features/grades/grades.module.ts b/src/core/features/grades/grades.module.ts
index 94ea4f04d..eea8feb79 100644
--- a/src/core/features/grades/grades.module.ts
+++ b/src/core/features/grades/grades.module.ts
@@ -15,6 +15,7 @@
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { Routes } from '@angular/router';
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
+import { CoreCourseIndexRoutingModule } from '@features/course/pages/index/index-routing.module';
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module';
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
@@ -33,10 +34,18 @@ const routes: Routes = [
},
];
+const courseIndexRoutes: Routes = [
+ {
+ path: 'grades',
+ loadChildren: () => import('@features/grades/grades-course-lazy.module').then(m => m.CoreGradesCourseLazyModule),
+ },
+];
+
@NgModule({
imports: [
CoreMainMenuTabRoutingModule.forChild(routes),
CoreMainMenuRoutingModule.forChild({ children: routes }),
+ CoreCourseIndexRoutingModule.forChild({ children: courseIndexRoutes }),
],
providers: [
{
diff --git a/src/core/features/grades/pages/course/course.html b/src/core/features/grades/pages/course/course.html
index f732a8470..579fffc6d 100644
--- a/src/core/features/grades/pages/course/course.html
+++ b/src/core/features/grades/pages/course/course.html
@@ -7,7 +7,7 @@
-
+
diff --git a/src/core/features/grades/pages/course/course.module.ts b/src/core/features/grades/pages/course/course.module.ts
new file mode 100644
index 000000000..d098cd9c8
--- /dev/null
+++ b/src/core/features/grades/pages/course/course.module.ts
@@ -0,0 +1,35 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from '@ionic/angular';
+import { NgModule } from '@angular/core';
+import { TranslateModule } from '@ngx-translate/core';
+
+import { CoreSharedModule } from '@/core/shared.module';
+
+import { CoreGradesCoursePage } from './course.page';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreSharedModule,
+ ],
+ declarations: [
+ CoreGradesCoursePage,
+ ],
+})
+export class CoreGradesCoursePageModule {}
diff --git a/src/core/features/grades/pages/course/course.ts b/src/core/features/grades/pages/course/course.page.ts
similarity index 84%
rename from src/core/features/grades/pages/course/course.ts
rename to src/core/features/grades/pages/course/course.page.ts
index ae9367d28..b0cb64d33 100644
--- a/src/core/features/grades/pages/course/course.ts
+++ b/src/core/features/grades/pages/course/course.page.ts
@@ -27,9 +27,10 @@ import {
} from '@features/grades/services/grades-helper';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
-import { CoreSplitViewComponent } from '@components/split-view/split-view';
+import { CoreSplitViewComponent, CoreSplitViewMode } from '@components/split-view/split-view';
import { CoreObject } from '@singletons/object';
import { CorePageItemsListManager } from '@classes/page-items-list-manager';
+import { CoreNavigator } from '@services/navigator';
/**
* Page that displays a course grades.
@@ -42,14 +43,18 @@ import { CorePageItemsListManager } from '@classes/page-items-list-manager';
export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
grades: CoreGradesCourseManager;
+ splitViewMode?: CoreSplitViewMode;
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
constructor(route: ActivatedRoute) {
- const courseId = parseInt(route.snapshot.params.courseId);
+ const courseId = parseInt(route.snapshot.params.courseId ?? route.snapshot.queryParams.courseId);
const userId = parseInt(route.snapshot.queryParams.userId ?? CoreSites.instance.getCurrentSiteUserId());
+ const useSplitView = route.snapshot.data.useSplitView ?? true;
+ const outsideGradesTab = route.snapshot.data.outsideGradesTab ?? false;
- this.grades = new CoreGradesCourseManager(CoreGradesCoursePage, courseId, userId);
+ this.splitViewMode = useSplitView ? undefined : CoreSplitViewMode.MenuOnly;
+ this.grades = new CoreGradesCourseManager(CoreGradesCoursePage, courseId, userId, outsideGradesTab);
}
/**
@@ -118,11 +123,14 @@ class CoreGradesCourseManager extends CorePageItemsListManager {
+ if (this.outsideGradesTab) {
+ await CoreNavigator.instance.navigateToSitePath(`/grades/${this.courseId}/${row.id}`);
+
+ return;
+ }
+
+ return super.select(row);
+ }
+
/**
* @inheritdoc
*/
diff --git a/src/core/features/grades/services/handlers/course-option.ts b/src/core/features/grades/services/handlers/course-option.ts
index 9dcb7cb61..dae804c8a 100644
--- a/src/core/features/grades/services/handlers/course-option.ts
+++ b/src/core/features/grades/services/handlers/course-option.ts
@@ -83,19 +83,14 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa
}
/**
- * Returns the data needed to render the handler.
- *
- * @return Data or promise resolved with the data.
+ * @inheritdoc
*/
getDisplayData(): CoreCourseOptionsHandlerData | Promise {
- throw new Error('CoreGradesCourseOptionHandler.getDisplayData is not implemented');
-
- // @todo
- // return {
- // title: 'core.grades.grades',
- // class: 'core-grades-course-handler',
- // component: CoreGradesCourseComponent,
- // };
+ return {
+ title: 'core.grades.grades',
+ class: 'core-grades-course-handler',
+ page: 'grades',
+ };
}
/**