diff --git a/src/addons/messages/tests/behat/snapshots/test-basic-usage-of-messages-in-app-view-recent-conversations-and-contacts_22.png b/src/addons/messages/tests/behat/snapshots/test-basic-usage-of-messages-in-app-view-recent-conversations-and-contacts_22.png index e85b3bcfc..cb8d3a916 100644 Binary files a/src/addons/messages/tests/behat/snapshots/test-basic-usage-of-messages-in-app-view-recent-conversations-and-contacts_22.png and b/src/addons/messages/tests/behat/snapshots/test-basic-usage-of-messages-in-app-view-recent-conversations-and-contacts_22.png differ diff --git a/src/addons/mod/mod.module.ts b/src/addons/mod/mod.module.ts index 1e3d73622..49a0fd1ec 100644 --- a/src/addons/mod/mod.module.ts +++ b/src/addons/mod/mod.module.ts @@ -33,6 +33,7 @@ import { AddonModPageModule } from './page/page.module'; import { AddonModQuizModule } from './quiz/quiz.module'; import { AddonModResourceModule } from './resource/resource.module'; import { AddonModScormModule } from './scorm/scorm.module'; +import { AddonModSubsectionModule } from './subsection/subsection.module'; import { AddonModSurveyModule } from './survey/survey.module'; import { AddonModUrlModule } from './url/url.module'; import { AddonModWikiModule } from './wiki/wiki.module'; @@ -59,6 +60,7 @@ import { AddonModWorkshopModule } from './workshop/workshop.module'; AddonModQuizModule, AddonModResourceModule, AddonModScormModule, + AddonModSubsectionModule, AddonModSurveyModule, AddonModUrlModule, AddonModWikiModule, diff --git a/src/addons/mod/subsection/services/handlers/index-link.ts b/src/addons/mod/subsection/services/handlers/index-link.ts new file mode 100644 index 000000000..f8962eb5d --- /dev/null +++ b/src/addons/mod/subsection/services/handlers/index-link.ts @@ -0,0 +1,65 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler'; +import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreLoadings } from '@services/loadings'; +import { CoreDomUtils } from '@services/utils/dom'; +import { makeSingleton } from '@singletons'; +import { AddonModSubsection } from '../subsection'; + +/** + * Handler to treat links to subsection. + */ +@Injectable({ providedIn: 'root' }) +export class AddonModSubsectionIndexLinkHandlerService extends CoreContentLinksModuleIndexHandler { + + name = 'AddonModSubsectionLinkHandler'; + + constructor() { + super('AddonModSubsection', 'subsection', 'id'); + } + + /** + * @inheritdoc + */ + getActions( + siteIds: string[], + url: string, + params: Record, + courseId?: number, + ): CoreContentLinksAction[] | Promise { + return [{ + action: async(siteId) => { + const modal = await CoreLoadings.show(); + const moduleId = Number(params.id); + + try { + // Get the module. + const module = await CoreCourse.getModule(moduleId, courseId, undefined, true, false, siteId); + + await AddonModSubsection.openSubsection(module.section, module.course, siteId); + } catch (error) { + CoreDomUtils.showErrorModalDefault(error, 'Error opening link.'); + } finally { + modal.dismiss(); + } + }, + }]; + } + +} +export const AddonModSubsectionIndexLinkHandler = makeSingleton(AddonModSubsectionIndexLinkHandlerService); diff --git a/src/addons/mod/subsection/services/handlers/module.ts b/src/addons/mod/subsection/services/handlers/module.ts new file mode 100644 index 000000000..c9266d0d5 --- /dev/null +++ b/src/addons/mod/subsection/services/handlers/module.ts @@ -0,0 +1,88 @@ +// (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 { CoreConstants, ModPurpose } from '@/core/constants'; +import { Injectable } from '@angular/core'; +import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; +import { + CoreCourseModuleDelegate, + CoreCourseModuleHandler, + CoreCourseModuleHandlerData, +} from '@features/course/services/module-delegate'; +import { CoreDomUtils } from '@services/utils/dom'; +import { makeSingleton } from '@singletons'; +import { AddonModSubsection } from '../subsection'; + +/** + * Handler to support subsection modules. + * + * This is merely to disable the siteplugin. + */ +@Injectable({ providedIn: 'root' }) +export class AddonModSubsectionModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler { + + name = 'AddonModSubsection'; + modName = 'subsection'; + + supportedFeatures = { + [CoreConstants.FEATURE_MOD_ARCHETYPE]: CoreConstants.MOD_ARCHETYPE_RESOURCE, + [CoreConstants.FEATURE_GROUPS]: false, + [CoreConstants.FEATURE_GROUPINGS]: false, + [CoreConstants.FEATURE_MOD_INTRO]: false, + [CoreConstants.FEATURE_COMPLETION_TRACKS_VIEWS]: true, + [CoreConstants.FEATURE_GRADE_HAS_GRADE]: false, + [CoreConstants.FEATURE_GRADE_OUTCOMES]: false, + [CoreConstants.FEATURE_BACKUP_MOODLE2]: true, + [CoreConstants.FEATURE_SHOW_DESCRIPTION]: false, + [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT, + }; + + /** + * @inheritdoc + */ + getData(module: CoreCourseModuleData): CoreCourseModuleHandlerData { + return { + icon: CoreCourseModuleDelegate.getModuleIconSrc(module.modname, module.modicon), + title: module.name, + a11yTitle: '', + class: 'addon-mod-subsection-handler', + hasCustomCmListItem: true, + action: async(event, module) => { + try { + await AddonModSubsection.openSubsection(module.section, module.course); + } catch (error) { + CoreDomUtils.showErrorModalDefault(error, 'Error opening subsection.'); + } + }, + }; + } + + /** + * @inheritdoc + */ + async getMainComponent(): Promise { + // There's no need to implement this because subsection cannot be used in singleactivity course format. + return; + } + + /** + * @inheritdoc + */ + getIconSrc(): string { + return ''; + } + +} +export const AddonModSubsectionModuleHandler = makeSingleton(AddonModSubsectionModuleHandlerService); diff --git a/src/addons/mod/subsection/services/subsection.ts b/src/addons/mod/subsection/services/subsection.ts new file mode 100644 index 000000000..ac62b952f --- /dev/null +++ b/src/addons/mod/subsection/services/subsection.ts @@ -0,0 +1,51 @@ +// (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 { CoreCourse } from '@features/course/services/course'; +import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreSites } from '@services/sites'; +import { makeSingleton } from '@singletons'; + +/** + * Service that provides some features for subsections. + */ +@Injectable({ providedIn: 'root' }) +export class AddonModSubsectionProvider { + + /** + * Open a subsection. + * + * @param sectionId Section ID. + * @param courseId Course ID. + * @param siteId Site ID. If not defined, current site. + * @returns Promise resolved when done. + */ + async openSubsection(sectionId: number, courseId: number, siteId?: string): Promise { + const pageParams = { + sectionId, + }; + + if ( + (!siteId || siteId === CoreSites.getCurrentSiteId()) && + CoreCourse.currentViewIsCourse(courseId) + ) { + CoreCourse.selectCourseTab('', pageParams); + } else { + await CoreCourseHelper.getAndOpenCourse(courseId, pageParams, siteId); + } + } + +} +export const AddonModSubsection = makeSingleton(AddonModSubsectionProvider); diff --git a/src/addons/mod/subsection/subsection.module.ts b/src/addons/mod/subsection/subsection.module.ts new file mode 100644 index 000000000..bfd1f2f09 --- /dev/null +++ b/src/addons/mod/subsection/subsection.module.ts @@ -0,0 +1,33 @@ +// (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 { APP_INITIALIZER, NgModule } from '@angular/core'; +import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; +import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; +import { AddonModSubsectionIndexLinkHandler } from './services/handlers/index-link'; +import { AddonModSubsectionModuleHandler } from './services/handlers/module'; + +@NgModule({ + providers: [ + { + provide: APP_INITIALIZER, + multi: true, + useValue: () => { + CoreCourseModuleDelegate.registerHandler(AddonModSubsectionModuleHandler.instance); + CoreContentLinksDelegate.registerHandler(AddonModSubsectionIndexLinkHandler.instance); + }, + }, + ], +}) +export class AddonModSubsectionModule {} diff --git a/src/core/components/message/message.ts b/src/core/components/message/message.ts index 99b4d9b2e..aeb18b6ae 100644 --- a/src/core/components/message/message.ts +++ b/src/core/components/message/message.ts @@ -46,11 +46,9 @@ export class CoreMessageComponent implements OnInit { protected deleted = false; // Needed to fix animation to void in Behat tests. - // @TODO Recover the animation using native css or wait for Angular 13.1 - // where the bug https://github.com/angular/angular/issues/30693 is solved. - // @HostBinding('@coreSlideInOut') get animation(): string { - // return this.isMine ? '' : 'fromLeft'; - // } + @HostBinding('@coreSlideInOut') get animation(): string { + return this.isMine ? '' : 'fromLeft'; + } @HostBinding('class.is-mine') isMine = false; diff --git a/src/core/features/course/components/course-format/course-format.html b/src/core/features/course/components/course-format/course-format.html index 38d99fd84..733821a0f 100644 --- a/src/core/features/course/components/course-format/course-format.html +++ b/src/core/features/course/components/course-format/course-format.html @@ -8,10 +8,13 @@ -
+
- - + + @@ -19,13 +22,16 @@
-
+
- + @for (section of sections; track section.id) { - @if ($index <= lastShownSectionIndex) { - + @if ($index <= lastShownSectionIndex && !section.hiddenbynumsections && section.id !== allSectionsId && + section.id !== stealthModulesSectionId && !section.component) { + } } @@ -65,55 +71,3 @@