diff --git a/src/addons/mod/assign/components/index/index.ts b/src/addons/mod/assign/components/index/index.ts index bb05633bc..24fb456a9 100644 --- a/src/addons/mod/assign/components/index/index.ts +++ b/src/addons/mod/assign/components/index/index.ts @@ -41,6 +41,7 @@ import { AddonModAssignSyncProvider, AddonModAssignSyncResult, } from '../../services/assign-sync'; +import { AddonModAssignModuleHandlerService } from '../../services/handlers/module'; import { AddonModAssignSubmissionComponent } from '../submission/submission'; /** @@ -318,9 +319,13 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo if (typeof status != 'undefined') { params.status = status; } - CoreNavigator.navigate('submission', { - params, - }); + + CoreNavigator.navigateToSitePath( + AddonModAssignModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.module.id}/submission`, + { + params, + }, + ); } /** diff --git a/src/addons/mod/data/components/index/addon-mod-data-index.html b/src/addons/mod/data/components/index/addon-mod-data-index.html index 26c2e3ec2..bf89fd47c 100644 --- a/src/addons/mod/data/components/index/addon-mod-data-index.html +++ b/src/addons/mod/data/components/index/addon-mod-data-index.html @@ -37,118 +37,115 @@ + - - + + - - + + + + + {{ 'core.hasdatatosync' | translate: {$a: moduleName} }} + + - - - - - {{ 'core.hasdatatosync' | translate: {$a: moduleName} }} - - + + + {{'core.groupsseparate' | translate }} + {{'core.groupsvisible' | translate }} + + + + {{groupOpt.name}} + + + - - - {{'core.groupsseparate' | translate }} - {{'core.groupsvisible' | translate }} + + + + {{ 'addon.mod_data.notopenyet' | translate:{$a: timeAvailableFromReadable} }} + + + + + + + {{ 'addon.mod_data.expired' | translate:{$a: timeAvailableToReadable} }} + + + + > + + + + {{ 'addon.mod_data.entrieslefttoaddtoview' | translate:{$a: {entrieslefttoview: access.entrieslefttoview} } }} + + + + + > + + + + {{ 'addon.mod_data.entrieslefttoadd' | translate:{$a: {entriesleft: access.entrieslefttoadd} } }} + + + + + + + + + {{ 'addon.mod_data.resetsettings' | translate}} - - - {{groupOpt.name}} - - - - - - {{ 'addon.mod_data.notopenyet' | translate:{$a: timeAvailableFromReadable} }} - + + +

+
+
- - - - {{ 'addon.mod_data.expired' | translate:{$a: timeAvailableToReadable} }} - - +
+ - > - - - - {{ 'addon.mod_data.entrieslefttoaddtoview' | translate:{$a: {entrieslefttoview: access.entrieslefttoview} } }} - - - + +
- > - - - - {{ 'addon.mod_data.entrieslefttoadd' | translate:{$a: {entriesleft: access.entrieslefttoadd} } }} - - - + + + + + + {{ 'core.previous' | translate }} + + + + + {{ 'core.next' | translate }} + + + + + - - - - - {{ 'addon.mod_data.resetsettings' | translate}} - - + + - - -

-
-
-
+ + {{ 'addon.mod_data.resetsettings' | translate}} + -
- + - -
- - - - - - - {{ 'core.previous' | translate }} - - - - - {{ 'core.next' | translate }} - - - - - - - - - - - {{ 'addon.mod_data.resetsettings' | translate}} - - -
- - - - - - -
+ + + + + diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index 69640238b..deeec564c 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -44,6 +44,7 @@ import { } from '../../services/data'; import { AddonModDataHelper } from '../../services/data-helper'; import { AddonModDataAutoSyncData, AddonModDataSyncProvider, AddonModDataSyncResult } from '../../services/data-sync'; +import { AddonModDataModuleHandlerService } from '../../services/handlers/module'; import { AddonModDataPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModDataComponentsCompileModule } from '../components-compile.module'; import { AddonModDataSearchComponent } from '../search/search'; @@ -469,7 +470,10 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp group: this.selectedGroup, }; - CoreNavigator.navigate('edit', { params }); + CoreNavigator.navigateToSitePath( + `${AddonModDataModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/edit`, + { params }, + ); } /** @@ -490,7 +494,10 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp params.offset = this.search.page * AddonModDataProvider.PER_PAGE + pageXOffset; } - CoreNavigator.navigate(String(entryId), { params }); + CoreNavigator.navigateToSitePath( + `${AddonModDataModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/${entryId}`, + { params }, + ); } /** diff --git a/src/addons/mod/data/data.module.ts b/src/addons/mod/data/data.module.ts index 4c2410ebc..353592b6d 100644 --- a/src/addons/mod/data/data.module.ts +++ b/src/addons/mod/data/data.module.ts @@ -38,6 +38,7 @@ import { AddonModDataShowLinkHandler } from './services/handlers/show-link'; import { AddonModDataSyncCronHandler } from './services/handlers/sync-cron'; import { AddonModDataTagAreaHandler } from './services/handlers/tag-area'; import { AddonModDataFieldModule } from './fields/field.module'; +import { AddonModDataComponentsModule } from './components/components.module'; // List of providers (without handlers). export const ADDON_MOD_DATA_SERVICES: Type[] = [ @@ -59,6 +60,7 @@ const routes: Routes = [ imports: [ CoreMainMenuTabRoutingModule.forChild(routes), AddonModDataFieldModule, + AddonModDataComponentsModule, ], providers: [ { diff --git a/src/addons/mod/folder/components/index/addon-mod-folder-index.html b/src/addons/mod/folder/components/index/addon-mod-folder-index.html index 9262fe900..814bcc3da 100644 --- a/src/addons/mod/folder/components/index/addon-mod-folder-index.html +++ b/src/addons/mod/folder/components/index/addon-mod-folder-index.html @@ -31,7 +31,7 @@ - +

{{folder.filename}}

diff --git a/src/addons/mod/folder/components/index/index.ts b/src/addons/mod/folder/components/index/index.ts index a3b4b2fae..10150ae14 100644 --- a/src/addons/mod/folder/components/index/index.ts +++ b/src/addons/mod/folder/components/index/index.ts @@ -23,6 +23,7 @@ import { CoreNavigator } from '@services/navigator'; import { Md5 } from 'ts-md5'; import { AddonModFolder, AddonModFolderFolder, AddonModFolderProvider } from '../../services/folder'; import { AddonModFolderFolderFormattedData, AddonModFolderHelper } from '../../services/folder-helper'; +import { AddonModFolderModuleHandlerService } from '../../services/handlers/module'; /** * Component that displays a folder. @@ -131,7 +132,10 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo const hash = Md5.hashAsciiStr(folder.filepath); - CoreNavigator.navigate('../' + hash, { params }); + CoreNavigator.navigateToSitePath( + `${AddonModFolderModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/${hash}`, + { params }, + ); } } diff --git a/src/addons/mod/forum/forum.module.ts b/src/addons/mod/forum/forum.module.ts index 0079e58bb..ec0c89af1 100644 --- a/src/addons/mod/forum/forum.module.ts +++ b/src/addons/mod/forum/forum.module.ts @@ -42,6 +42,7 @@ import { AddonModForumProvider } from './services/forum'; import { AddonModForumOfflineProvider } from './services/forum-offline'; import { AddonModForumHelperProvider } from './services/forum-helper'; import { AddonModForumSyncProvider } from './services/forum-sync'; +import { COURSE_CONTENTS_PATH } from '@features/course/course.module'; export const ADDON_MOD_FORUM_SERVICES: Type[] = [ AddonModForumProvider, @@ -62,12 +63,12 @@ const mainMenuRoutes: Routes = [ ...conditionalRoutes( [ { - path: `course/index/contents/${AddonModForumModuleHandlerService.PAGE_NAME}/new/:timeCreated`, + path: `${COURSE_CONTENTS_PATH}/${AddonModForumModuleHandlerService.PAGE_NAME}/new/:timeCreated`, loadChildren: () => import('./pages/new-discussion/new-discussion.module') .then(m => m.AddonForumNewDiscussionPageModule), }, { - path: `course/index/contents/${AddonModForumModuleHandlerService.PAGE_NAME}/:discussionId`, + path: `${COURSE_CONTENTS_PATH}/${AddonModForumModuleHandlerService.PAGE_NAME}/:discussionId`, loadChildren: () => import('./pages/discussion/discussion.module').then(m => m.AddonForumDiscussionPageModule), }, ], diff --git a/src/addons/mod/glossary/components/index/index.ts b/src/addons/mod/glossary/components/index/index.ts index 4b15485ff..c442b74e0 100644 --- a/src/addons/mod/glossary/components/index/index.ts +++ b/src/addons/mod/glossary/components/index/index.ts @@ -44,6 +44,7 @@ import { AddonModGlossarySyncProvider, AddonModGlossarySyncResult, } from '../../services/glossary-sync'; +import { AddonModGlossaryModuleHandlerService } from '../../services/handlers/module'; import { AddonModGlossaryPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModGlossaryModePickerPopoverComponent } from '../mode-picker/mode-picker'; @@ -93,6 +94,8 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity this.entries = new AddonModGlossaryEntriesManager( route.component, + this, + courseContentsPage ? `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/` : '', ); } @@ -524,8 +527,18 @@ class AddonModGlossaryEntriesManager extends CorePageItemsListManager onlineEntries: AddonModGlossaryEntry[] = []; offlineEntries: AddonModGlossaryOfflineEntry[] = []; - constructor(pageComponent: unknown) { + protected glossaryPathPrefix: string; + protected component: AddonModGlossaryIndexComponent; + + constructor( + pageComponent: unknown, + component: AddonModGlossaryIndexComponent, + glossaryPathPrefix: string, + ) { super(pageComponent); + + this.component = component; + this.glossaryPathPrefix = glossaryPathPrefix; } /** @@ -609,27 +622,30 @@ class AddonModGlossaryEntriesManager extends CorePageItemsListManager */ protected getItemPath(entry: EntryItem): string { if (this.isOnlineEntry(entry)) { - return `entry/${entry.id}`; + return `${this.glossaryPathPrefix}entry/${entry.id}`; } if (this.isOfflineEntry(entry)) { - return `edit/${entry.timecreated}`; + return `${this.glossaryPathPrefix}edit/${entry.timecreated}`; } - return 'edit/0'; + return `${this.glossaryPathPrefix}edit/0`; } /** * @inheritdoc */ getItemQueryParams(entry: EntryItem): Params { + const params: Params = { + cmId: this.component.module.id, + courseId: this.component.courseId, + }; + if (this.isOfflineEntry(entry)) { - return { - concept: entry.concept, - }; + params.concept = entry.concept; } - return {}; + return params; } /** diff --git a/src/addons/mod/glossary/glossary.module.ts b/src/addons/mod/glossary/glossary.module.ts index 69dfda5de..a6037fd5f 100644 --- a/src/addons/mod/glossary/glossary.module.ts +++ b/src/addons/mod/glossary/glossary.module.ts @@ -12,14 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { conditionalRoutes } from '@/app/app-routing.module'; import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; +import { COURSE_CONTENTS_PATH } from '@features/course/course.module'; +import { CoreCourseContentsRoutingModule } from '@features/course/pages/contents/contents-routing.module'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate'; import { CoreCronDelegate } from '@services/cron'; +import { CoreScreen } from '@services/screen'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { AddonModGlossaryComponentsModule } from './components/components.module'; import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA } from './services/database/glossary'; @@ -44,23 +48,43 @@ export const ADDON_MOD_GLOSSARY_SERVICES: Type[] = [ ]; const mainMenuRoutes: Routes = [ - { - path: `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/entry/:entryId`, - loadChildren: () => import('./pages/entry/entry.module').then(m => m.AddonModGlossaryEntryPageModule), - }, - { - path: `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/edit/:timecreated`, - loadChildren: () => import('./pages/edit/edit.module').then(m => m.AddonModGlossaryEditPageModule), - }, { path: AddonModGlossaryModuleHandlerService.PAGE_NAME, loadChildren: () => import('./glossary-lazy.module').then(m => m.AddonModGlossaryLazyModule), }, + ...conditionalRoutes( + [ + { + path: `${COURSE_CONTENTS_PATH}/${AddonModGlossaryModuleHandlerService.PAGE_NAME}/entry/:entryId`, + loadChildren: () => import('./pages/entry/entry.module').then(m => m.AddonModGlossaryEntryPageModule), + }, + { + path: `${COURSE_CONTENTS_PATH}/${AddonModGlossaryModuleHandlerService.PAGE_NAME}/edit/:timecreated`, + loadChildren: () => import('./pages/edit/edit.module').then(m => m.AddonModGlossaryEditPageModule), + }, + ], + () => CoreScreen.isMobile, + ), ]; +const courseContentsRoutes: Routes = conditionalRoutes( + [ + { + path: `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/entry/:entryId`, + loadChildren: () => import('./pages/entry/entry.module').then(m => m.AddonModGlossaryEntryPageModule), + }, + { + path: `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/edit/:timecreated`, + loadChildren: () => import('./pages/edit/edit.module').then(m => m.AddonModGlossaryEditPageModule), + }, + ], + () => CoreScreen.isTablet, +); + @NgModule({ imports: [ CoreMainMenuTabRoutingModule.forChild(mainMenuRoutes), + CoreCourseContentsRoutingModule.forChild({ children: courseContentsRoutes }), AddonModGlossaryComponentsModule, ], providers: [ diff --git a/src/addons/mod/h5pactivity/components/index/index.ts b/src/addons/mod/h5pactivity/components/index/index.ts index f8dfdccba..fe46478e2 100644 --- a/src/addons/mod/h5pactivity/components/index/index.ts +++ b/src/addons/mod/h5pactivity/components/index/index.ts @@ -44,6 +44,7 @@ import { AddonModH5PActivitySyncResult, } from '../../services/h5pactivity-sync'; import { CoreFileHelper } from '@services/file-helper'; +import { AddonModH5PActivityModuleHandlerService } from '../../services/handlers/module'; /** * Component that displays an H5P activity entry page. @@ -375,7 +376,9 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv const userId = CoreSites.getCurrentSiteUserId(); try { - await CoreNavigator.navigate(`userattempts/${userId}`); + await CoreNavigator.navigateToSitePath( + `${AddonModH5PActivityModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/userattempts/${userId}`, + ); } finally { this.isOpeningPage = false; } diff --git a/src/addons/mod/lesson/components/index/index.ts b/src/addons/mod/lesson/components/index/index.ts index 25c9c6400..9f69bbd95 100644 --- a/src/addons/mod/lesson/components/index/index.ts +++ b/src/addons/mod/lesson/components/index/index.ts @@ -47,6 +47,7 @@ import { AddonModLessonSyncProvider, AddonModLessonSyncResult, } from '../../services/lesson-sync'; +import { AddonModLessonModuleHandlerService } from '../../services/handlers/module'; /** * Component that displays a lesson entry page. @@ -424,12 +425,15 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo pageId = continueLast ? this.accessInfo.lastpageseen : this.accessInfo.firstpageid; } - await CoreNavigator.navigate('player', { - params: { - pageId: pageId, - password: this.password, + await CoreNavigator.navigateToSitePath( + `${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, + { + params: { + pageId: pageId, + password: this.password, + }, }, - }); + ); // Detect if anything was sent to server. this.hasPlayed = true; @@ -472,14 +476,17 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo return; } - CoreNavigator.navigate('player', { - params: { - pageId: this.retakeToReview.pageid, - password: this.password, - review: true, - retake: this.retakeToReview.retake, + CoreNavigator.navigateToSitePath( + `${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, + { + params: { + pageId: this.retakeToReview.pageid, + password: this.password, + review: true, + retake: this.retakeToReview.retake, + }, }, - }); + ); } /** @@ -695,11 +702,9 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo * @return Promise resolved when done. */ async openRetake(userId: number): Promise { - await CoreNavigator.navigate('user-retake', { - params: { - userId, - }, - }); + CoreNavigator.navigateToSitePath( + `${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/user-retake/${userId}`, + ); } /** diff --git a/src/addons/mod/lesson/lesson-lazy.module.ts b/src/addons/mod/lesson/lesson-lazy.module.ts index 1881e3f13..db94d2ddb 100644 --- a/src/addons/mod/lesson/lesson-lazy.module.ts +++ b/src/addons/mod/lesson/lesson-lazy.module.ts @@ -30,7 +30,7 @@ const routes: Routes = [ loadChildren: () => import('./pages/player/player.module').then( m => m.AddonModLessonPlayerPageModule), }, { - path: ':courseId/:cmId/user-retake', + path: ':courseId/:cmId/user-retake/:userId', loadChildren: () => import('./pages/user-retake/user-retake.module').then( m => m.AddonModLessonUserRetakePageModule), }, ]; diff --git a/src/addons/mod/lesson/services/handlers/grade-link.ts b/src/addons/mod/lesson/services/handlers/grade-link.ts index 151db384c..d5c847659 100644 --- a/src/addons/mod/lesson/services/handlers/grade-link.ts +++ b/src/addons/mod/lesson/services/handlers/grade-link.ts @@ -52,6 +52,7 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul siteId: string, ): Promise { const moduleId = Number(params.id); + const userId = Number(params.userid) || 0; const modal = await CoreDomUtils.showModalLoading(); @@ -65,9 +66,8 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul if (accessInfo.canviewreports) { // User can view reports, go to view the report. CoreNavigator.navigateToSitePath( - AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake`, + AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake/${userId}`, { - params: { userId: Number(params.userid) }, siteId, }, ); diff --git a/src/addons/mod/lesson/services/handlers/report-link.ts b/src/addons/mod/lesson/services/handlers/report-link.ts index 5fc993a2d..ecc00a4a1 100644 --- a/src/addons/mod/lesson/services/handlers/report-link.ts +++ b/src/addons/mod/lesson/services/handlers/report-link.ts @@ -102,14 +102,17 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand // Get the module object. const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + courseId = courseId || module.course; const params = { module: module, - courseId: courseId || module.course, action: 'report', group: groupId === undefined || isNaN(groupId) ? null : groupId, }; - CoreNavigator.navigateToSitePath(AddonModLessonModuleHandlerService.PAGE_NAME, { params, siteId }); + CoreNavigator.navigateToSitePath( + `${AddonModLessonModuleHandlerService.PAGE_NAME}/${courseId}/${module.id}`, + { params, siteId }, + ); } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'Error processing link.'); } finally { @@ -143,12 +146,11 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand courseId = courseId || module.course; const params = { - userId: userId, retake: retake || 0, }; CoreNavigator.navigateToSitePath( - AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake`, + AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake/${userId}`, { params, siteId }, ); } catch (error) { diff --git a/src/addons/mod/quiz/components/index/index.ts b/src/addons/mod/quiz/components/index/index.ts index 8f10dcc82..70e0ba693 100644 --- a/src/addons/mod/quiz/components/index/index.ts +++ b/src/addons/mod/quiz/components/index/index.ts @@ -27,6 +27,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { AddonModQuizModuleHandlerService } from '../../services/handlers/module'; import { AddonModQuizPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModQuiz, @@ -413,7 +414,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp try { await AddonModQuiz.getAttemptReview(attemptId, { page: -1, cmId: this.module.id }); - await CoreNavigator.navigate(`review/${attemptId}`); + await CoreNavigator.navigateToSitePath( + `${AddonModQuizModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/review/${attemptId}`, + ); } catch { // Ignore errors. } @@ -534,11 +537,14 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp protected openQuiz(): void { this.hasPlayed = true; - CoreNavigator.navigate('player', { - params: { - moduleUrl: this.module.url, + CoreNavigator.navigateToSitePath( + `${AddonModQuizModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, + { + params: { + moduleUrl: this.module.url, + }, }, - }); + ); } /** @@ -659,7 +665,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp * @return Promise resolved when done. */ async viewAttempt(attemptId: number): Promise { - CoreNavigator.navigate(`attempt/${attemptId}`); + await CoreNavigator.navigateToSitePath( + `${AddonModQuizModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/attempt/${attemptId}`, + ); } /** diff --git a/src/addons/mod/quiz/services/quiz-helper.ts b/src/addons/mod/quiz/services/quiz-helper.ts index 7a02c7a8e..d167e9653 100644 --- a/src/addons/mod/quiz/services/quiz-helper.ts +++ b/src/addons/mod/quiz/services/quiz-helper.ts @@ -24,6 +24,7 @@ import { CoreUtils } from '@services/utils/utils'; import { makeSingleton, ModalController, Translate } from '@singletons'; import { AddonModQuizPreflightModalComponent } from '../components/preflight-modal/preflight-modal'; import { AddonModQuizAccessRuleDelegate } from './access-rules-delegate'; +import { AddonModQuizModuleHandlerService } from './handlers/module'; import { AddonModQuiz, AddonModQuizAttemptWSData, @@ -238,12 +239,15 @@ export class AddonModQuizHelperProvider { courseId = courseId || module.course; // Go to the review page. - await CoreNavigator.navigateToSitePath(`mod_quiz/${courseId}/${module.id}/review/${attemptId}`, { - params: { - page: page == undefined || isNaN(page) ? -1 : page, + await CoreNavigator.navigateToSitePath( + `${AddonModQuizModuleHandlerService.PAGE_NAME}/${courseId}/${module.id}/review/${attemptId}`, + { + params: { + page: page == undefined || isNaN(page) ? -1 : page, + }, + siteId, }, - siteId, - }); + ); } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'An error occurred while loading the required data.'); } finally { diff --git a/src/addons/mod/scorm/components/index/index.ts b/src/addons/mod/scorm/components/index/index.ts index efaf7b3bd..1573fea4c 100644 --- a/src/addons/mod/scorm/components/index/index.ts +++ b/src/addons/mod/scorm/components/index/index.ts @@ -23,6 +23,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { AddonModScormModuleHandlerService } from '../../services/handlers/module'; import { AddonModScormPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModScorm, @@ -544,15 +545,18 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom } }, this.siteId); - CoreNavigator.navigate('player', { - params: { - mode: preview ? AddonModScormProvider.MODEBROWSE : AddonModScormProvider.MODENORMAL, - moduleUrl: this.module.url, - newAttempt: !!this.startNewAttempt, - organizationId: this.currentOrganization.identifier, - scoId: scoId, + CoreNavigator.navigateToSitePath( + `${AddonModScormModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, + { + params: { + mode: preview ? AddonModScormProvider.MODEBROWSE : AddonModScormProvider.MODENORMAL, + moduleUrl: this.module.url, + newAttempt: !!this.startNewAttempt, + organizationId: this.currentOrganization.identifier, + scoId: scoId, + }, }, - }); + ); } /** diff --git a/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html b/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html index 4885fe49c..3466dfb92 100644 --- a/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html +++ b/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html @@ -46,52 +46,50 @@ - - -
- +
+ + + + + + + + + {{ 'core.hasdatatosync' | translate:{$a: pageStr} }} + {{ 'core.hasdatatosync' | translate:{$a: moduleName} }} + + + + + + + + + {{ pageWarning }} + + +
+
+
+ - + + + +
- - - - - - {{ 'core.hasdatatosync' | translate:{$a: pageStr} }} - {{ 'core.hasdatatosync' | translate:{$a: moduleName} }} - - - - - - - - - {{ pageWarning }} - - +
+ {{ 'core.tag.tags' | translate }}: +
-
-
- - - - -
+
+ -
- {{ 'core.tag.tags' | translate }}: - -
-
- - - - - - - - + + + + + diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts index b32c69121..e0937ee6c 100644 --- a/src/addons/mod/wiki/components/index/index.ts +++ b/src/addons/mod/wiki/components/index/index.ts @@ -31,6 +31,7 @@ import { ModalController, PopoverController, Translate } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { Md5 } from 'ts-md5'; import { AddonModWikiPageDBRecord } from '../../services/database/wiki'; +import { AddonModWikiModuleHandlerService } from '../../services/handlers/module'; import { AddonModWiki, AddonModWikiPageContents, @@ -443,14 +444,17 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp * Open the view to create the first page of the wiki. */ protected goToCreateFirstPage(): void { - CoreNavigator.navigate('../../edit', { - params: { - pageTitle: this.wiki!.firstpagetitle, - wikiId: this.currentSubwiki?.wikiid, - userId: this.currentSubwiki?.userid, - groupId: this.currentSubwiki?.groupid, + CoreNavigator.navigateToSitePath( + `${AddonModWikiModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/edit`, + { + params: { + pageTitle: this.wiki!.firstpagetitle, + wikiId: this.currentSubwiki?.wikiid, + userId: this.currentSubwiki?.userid, + groupId: this.currentSubwiki?.groupid, + }, }, - }); + ); } /** @@ -478,7 +482,10 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp pageParams.groupId = this.currentSubwiki.groupid; } - CoreNavigator.navigate('../../edit', { params: pageParams }); + CoreNavigator.navigateToSitePath( + `${AddonModWikiModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/edit`, + { params: pageParams }, + ); } else if (this.currentSubwiki) { // No page loaded, the wiki doesn't have first page. this.goToCreateFirstPage(); @@ -505,7 +512,10 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp pageParams.groupId = this.currentSubwiki.groupid; } - CoreNavigator.navigate('../../edit', { params: pageParams }); + CoreNavigator.navigateToSitePath( + `${AddonModWikiModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/edit`, + { params: pageParams }, + ); } else if (this.currentSubwiki) { // No page loaded, the wiki doesn't have first page. this.goToCreateFirstPage(); @@ -550,12 +560,15 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp timestamp: Date.now(), })); - await CoreNavigator.navigate(`../${hash}`, { - params: { - module: this.module, - ...options, + CoreNavigator.navigateToSitePath( + `${AddonModWikiModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/page/${hash}`, + { + params: { + module: this.module, + ...options, + }, }, - }); + ); } /** diff --git a/src/addons/mod/wiki/pages/edit/edit.html b/src/addons/mod/wiki/pages/edit/edit.html index eab756228..9a90fb0e4 100644 --- a/src/addons/mod/wiki/pages/edit/edit.html +++ b/src/addons/mod/wiki/pages/edit/edit.html @@ -33,7 +33,7 @@ - + {{ 'addon.mod_wiki.wrongversionlock' | translate }} diff --git a/src/core/directives/fab.ts b/src/core/directives/fab.ts index 433d16bf5..838c0b9c2 100644 --- a/src/core/directives/fab.ts +++ b/src/core/directives/fab.ts @@ -29,7 +29,7 @@ export class CoreFabDirective implements OnDestroy { protected static readonly PADDINGBOTTOM = 56; - protected element?: HTMLElement; + protected scrollElement?: HTMLElement; protected done = false; constructor(protected content: IonContent) { @@ -41,10 +41,10 @@ export class CoreFabDirective implements OnDestroy { */ async asyncInit(): Promise { if (this.content) { - this.element = await this.content.getScrollElement(); + this.scrollElement = await this.content.getScrollElement(); if (!this.done) { - const bottom = parseInt(this.element.style.paddingBottom, 10) || 0; - this.element.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; + const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; + this.scrollElement.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; this.done = true; } } @@ -54,9 +54,9 @@ export class CoreFabDirective implements OnDestroy { * Destroy component. */ ngOnDestroy(): void { - if (this.done && this.element) { - const bottom = parseInt(this.element.style.paddingBottom, 10) || 0; - this.element.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; + if (this.done && this.scrollElement) { + const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; + this.scrollElement.style.paddingBottom = (bottom - CoreFabDirective.PADDINGBOTTOM) + 'px'; } } diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 36946262c..3803dbe44 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -126,7 +126,6 @@ import { ADDON_MOD_ASSIGN_SERVICES } from '@addons/mod/assign/assign.module'; import { ADDON_MOD_BOOK_SERVICES } from '@addons/mod/book/book.module'; import { ADDON_MOD_CHAT_SERVICES } from '@addons/mod/chat/chat.module'; import { ADDON_MOD_CHOICE_SERVICES } from '@addons/mod/choice/choice.module'; -import { ADDON_MOD_DATA_SERVICES } from '@addons/mod/data/data.module'; import { ADDON_MOD_FEEDBACK_SERVICES } from '@addons/mod/feedback/feedback.module'; import { ADDON_MOD_FOLDER_SERVICES } from '@addons/mod/folder/folder.module'; import { ADDON_MOD_FORUM_SERVICES } from '@addons/mod/forum/forum.module'; @@ -292,7 +291,6 @@ export class CoreCompileProvider { ...ADDON_MOD_BOOK_SERVICES, ...ADDON_MOD_CHAT_SERVICES, ...ADDON_MOD_CHOICE_SERVICES, - ...ADDON_MOD_DATA_SERVICES, ...ADDON_MOD_FEEDBACK_SERVICES, ...ADDON_MOD_FOLDER_SERVICES, ...ADDON_MOD_FORUM_SERVICES, diff --git a/src/core/features/course/course-lazy.module.ts b/src/core/features/course/course-lazy.module.ts index fec984b70..80f28334e 100644 --- a/src/core/features/course/course-lazy.module.ts +++ b/src/core/features/course/course-lazy.module.ts @@ -15,14 +15,11 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +export const COURSE_INDEX_PATH = ':courseId'; + const routes: Routes = [ { - path: '', - redirectTo: 'index', - pathMatch: 'full', - }, - { - path: ':courseId', + path: COURSE_INDEX_PATH, loadChildren: () => import('./pages/index/index.module').then( m => m.CoreCourseIndexPageModule), }, { diff --git a/src/core/features/course/course.module.ts b/src/core/features/course/course.module.ts index b795315c4..78e11b453 100644 --- a/src/core/features/course/course.module.ts +++ b/src/core/features/course/course.module.ts @@ -39,6 +39,7 @@ import { CoreCourseModuleDelegateService } from './services/module-delegate'; import { CoreCourseOptionsDelegateService } from './services/course-options-delegate'; import { CoreCourseOfflineProvider } from './services/course-offline'; import { CoreCourseSyncProvider } from './services/sync'; +import { COURSE_INDEX_PATH } from '@features/course/course-lazy.module'; export const CORE_COURSE_SERVICES: Type[] = [ CoreCourseProvider, @@ -52,16 +53,20 @@ export const CORE_COURSE_SERVICES: Type[] = [ CoreCourseSyncProvider, ]; +export const COURSE_PAGE_NAME = 'course'; +export const CONTENTS_PAGE_NAME = 'contents'; +export const COURSE_CONTENTS_PATH = `${COURSE_PAGE_NAME}/${COURSE_INDEX_PATH}/${CONTENTS_PAGE_NAME}`; + const routes: Routes = [ { - path: 'course', + path: COURSE_PAGE_NAME, loadChildren: () => import('@features/course/course-lazy.module').then(m => m.CoreCourseLazyModule), }, ]; const courseIndexRoutes: Routes = [ { - path: 'contents', + path: CONTENTS_PAGE_NAME, loadChildren: () => import('./pages/contents/contents.module').then(m => m.CoreCourseContentsPageModule), }, ]; diff --git a/src/core/features/course/pages/index/index.page.ts b/src/core/features/course/pages/index/index.page.ts index 9a2eae993..8629eb6a6 100644 --- a/src/core/features/course/pages/index/index.page.ts +++ b/src/core/features/course/pages/index/index.page.ts @@ -25,6 +25,7 @@ import { CoreCourseHelper } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; import { CoreNavigator } from '@services/navigator'; +import { CONTENTS_PAGE_NAME } from '@features/course/course.module'; /** * Page that displays the list of courses the user is enrolled in. @@ -46,7 +47,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { protected selectTabObserver: CoreEventObserver; protected firstTabName?: string; protected contentsTab: CoreTabsOutletTab = { - page: 'contents', + page: CONTENTS_PAGE_NAME, title: 'core.course.contents', pageParams: {}, }; diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index 2fbc9701f..4b647b267 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -1848,7 +1848,7 @@ export class CoreCourseHelperProvider { params = params || {}; Object.assign(params, { course: course }); - await CoreNavigator.navigateToSitePath('course/' + course.id, { siteId, params }); + await CoreNavigator.navigateToSitePath(`course/${course.id}`, { siteId, params }); } } diff --git a/src/core/features/course/services/handlers/default-format.ts b/src/core/features/course/services/handlers/default-format.ts index d0e800932..4b0258cb6 100644 --- a/src/core/features/course/services/handlers/default-format.ts +++ b/src/core/features/course/services/handlers/default-format.ts @@ -177,7 +177,7 @@ export class CoreCourseFormatDefaultHandler implements CoreCourseFormatHandler { Object.assign(params, { course: course }); // Don't return the .push promise, we don't want to display a loading modal during the page transition. - CoreNavigator.navigateToSitePath('course/' + course.id, { params }); + CoreNavigator.navigateToSitePath(`course/${course.id}`, { params }); } /** diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index 17809b66b..e83caa979 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -496,3 +496,11 @@ ion-button.core-button-select { textarea:not([core-auto-rows]) { height: 200px; } + +ion-fab[core-fab] { + position: fixed; +} + +ion-content > ion-fab[core-fab] { + position: absolute; +}