diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml index f63cd5edb..a2d2e1330 100644 --- a/.github/workflows/acceptance.yml +++ b/.github/workflows/acceptance.yml @@ -16,6 +16,11 @@ on: pull_request: branches: [ main, v*.x ] +concurrency: + group: acceptance-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + + jobs: build: diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ff5e04e2a..2bd657f1e 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -2,6 +2,10 @@ name: Testing on: [push, pull_request] +concurrency: + group: testing-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + jobs: test: diff --git a/src/addons/competency/competency.module.ts b/src/addons/competency/competency.module.ts index d705ed1c3..8cf0c600b 100644 --- a/src/addons/competency/competency.module.ts +++ b/src/addons/competency/competency.module.ts @@ -17,8 +17,6 @@ import { CoreContentLinksDelegate } from '@features/contentlinks/services/conten import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { CoreUserDelegate } from '@features/user/services/user-delegate'; -import { AddonCompetencyProvider } from './services/competency'; -import { AddonCompetencyHelperProvider } from './services/competency-helper'; import { AddonCompetencyCompetencyLinkHandler } from './services/handlers/competency-link'; import { AddonCompetencyCourseOptionHandler } from './services/handlers/course-option'; import { AddonCompetencyPlanLinkHandler } from './services/handlers/plan-link'; @@ -33,11 +31,20 @@ import { CoreCourseIndexRoutingModule } from '@features/course/course-routing.mo import { COURSE_PAGE_NAME } from '@features/course/course.module'; import { PARTICIPANTS_PAGE_NAME } from '@features/user/user.module'; -// List of providers (without handlers). -export const ADDON_COMPETENCY_SERVICES: Type[] = [ - AddonCompetencyProvider, - AddonCompetencyHelperProvider, -]; +/** + * Get competency services. + * + * @returns Competency services. + */ +export async function getCompetencyServices(): Promise[]> { + const { AddonCompetencyProvider } = await import('@addons/competency/services/competency'); + const { AddonCompetencyHelperProvider } = await import('@addons/competency/services/competency-helper'); + + return [ + AddonCompetencyProvider, + AddonCompetencyHelperProvider, + ]; +} export const ADDON_COMPETENCY_LEARNING_PLANS_PAGE = 'learning-plans'; export const ADDON_COMPETENCY_COMPETENCIES_PAGE = 'competencies'; diff --git a/src/addons/competency/services/competency.ts b/src/addons/competency/services/competency.ts index 07f70f915..d6b3ca689 100644 --- a/src/addons/competency/services/competency.ts +++ b/src/addons/competency/services/competency.ts @@ -42,18 +42,34 @@ export class AddonCompetencyProvider { static readonly REVIEW_STATUS_WAITING_FOR_REVIEW = 1; static readonly REVIEW_STATUS_IN_REVIEW = 2; + /** + * Check if competencies are enabled in a certain site. + * + * @param options Site ID or site object. + * @returns Whether competencies are enabled. + */ + async areCompetenciesEnabled(options?: {siteId?: string; site?: CoreSite}): Promise { + const site = options?.site ? options.site : await CoreSites.getSite(options?.siteId); + + if (!site) { + return false; + } + + return site.canUseAdvancedFeature('enablecompetencies') && + !(site.isFeatureDisabled('CoreMainMenuDelegate_AddonCompetency') && + site.isFeatureDisabled('CoreCourseOptionsDelegate_AddonCompetency') && + site.isFeatureDisabled('CoreUserDelegate_AddonCompetency')); + } + /** * Check if all competencies features are disabled. * * @param siteId Site ID. If not defined, current site. * @returns Promise resolved with boolean: whether all competency features are disabled. + * @deprecated since 4.4. Use areCompetenciesEnabled instead. */ async allCompetenciesDisabled(siteId?: string): Promise { - const site = await CoreSites.getSite(siteId); - - return site.isFeatureDisabled('CoreMainMenuDelegate_AddonCompetency') && - site.isFeatureDisabled('CoreCourseOptionsDelegate_AddonCompetency') && - site.isFeatureDisabled('CoreUserDelegate_AddonCompetency'); + return !(await this.areCompetenciesEnabled({ siteId })); } /** @@ -69,6 +85,11 @@ export class AddonCompetencyProvider { return false; } + const enabled = await this.areCompetenciesEnabled({ siteId }); + if (!enabled) { + return false; + } + try { const response = await this.getCourseCompetenciesPage(courseId, siteId); diff --git a/src/addons/competency/services/handlers/competency-link.ts b/src/addons/competency/services/handlers/competency-link.ts index c804f5618..6d268c040 100644 --- a/src/addons/competency/services/handlers/competency-link.ts +++ b/src/addons/competency/services/handlers/competency-link.ts @@ -70,10 +70,7 @@ export class AddonCompetencyCompetencyLinkHandlerService extends CoreContentLink * @inheritdoc */ async isEnabled(siteId: string): Promise { - // Handler is disabled if all competency features are disabled. - const disabled = await AddonCompetency.allCompetenciesDisabled(siteId); - - return !disabled; + return AddonCompetency.areCompetenciesEnabled({ siteId }); } } diff --git a/src/addons/competency/services/handlers/course-option.ts b/src/addons/competency/services/handlers/course-option.ts index e46b49b78..ac611c4d8 100644 --- a/src/addons/competency/services/handlers/course-option.ts +++ b/src/addons/competency/services/handlers/course-option.ts @@ -39,7 +39,7 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti * @inheritdoc */ async isEnabled(): Promise { - return true; + return AddonCompetency.areCompetenciesEnabled(); } /** diff --git a/src/addons/competency/services/handlers/plan-link.ts b/src/addons/competency/services/handlers/plan-link.ts index fbf9e9f35..12eee7afe 100644 --- a/src/addons/competency/services/handlers/plan-link.ts +++ b/src/addons/competency/services/handlers/plan-link.ts @@ -48,10 +48,7 @@ export class AddonCompetencyPlanLinkHandlerService extends CoreContentLinksHandl * @inheritdoc */ async isEnabled(siteId: string): Promise { - // Handler is disabled if all competency features are disabled. - const disabled = await AddonCompetency.allCompetenciesDisabled(siteId); - - return !disabled; + return AddonCompetency.areCompetenciesEnabled({ siteId }); } } diff --git a/src/addons/competency/services/handlers/plans-link.ts b/src/addons/competency/services/handlers/plans-link.ts index 838381e17..685481b2b 100644 --- a/src/addons/competency/services/handlers/plans-link.ts +++ b/src/addons/competency/services/handlers/plans-link.ts @@ -49,10 +49,7 @@ export class AddonCompetencyPlansLinkHandlerService extends CoreContentLinksHand * @inheritdoc */ async isEnabled(siteId: string): Promise { - // Handler is disabled if all competency features are disabled. - const disabled = await AddonCompetency.allCompetenciesDisabled(siteId); - - return !disabled; + return AddonCompetency.areCompetenciesEnabled({ siteId }); } } diff --git a/src/addons/competency/services/handlers/push-click.ts b/src/addons/competency/services/handlers/push-click.ts index 8172821e2..ec3b3d493 100644 --- a/src/addons/competency/services/handlers/push-click.ts +++ b/src/addons/competency/services/handlers/push-click.ts @@ -39,7 +39,7 @@ export class AddonCompetencyPushClickHandlerService implements CorePushNotificat if (CoreUtils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' && (notification.name == 'competencyplancomment' || notification.name == 'competencyusercompcomment')) { // If all competency features are disabled, don't handle the click. - return AddonCompetency.allCompetenciesDisabled(notification.site).then((disabled) => !disabled); + return AddonCompetency.areCompetenciesEnabled({ siteId: notification.site }); } return false; diff --git a/src/addons/competency/services/handlers/user-competency-link.ts b/src/addons/competency/services/handlers/user-competency-link.ts index 47a861baa..3cc83b2b0 100644 --- a/src/addons/competency/services/handlers/user-competency-link.ts +++ b/src/addons/competency/services/handlers/user-competency-link.ts @@ -48,10 +48,7 @@ export class AddonCompetencyUserCompetencyLinkHandlerService extends CoreContent * @inheritdoc */ async isEnabled(siteId: string): Promise { - // Handler is disabled if all competency features are disabled. - const disabled = await AddonCompetency.allCompetenciesDisabled(siteId); - - return !disabled; + return AddonCompetency.areCompetenciesEnabled({ siteId }); } } diff --git a/src/addons/competency/services/handlers/user.ts b/src/addons/competency/services/handlers/user.ts index 9cd7df793..bfbce8765 100644 --- a/src/addons/competency/services/handlers/user.ts +++ b/src/addons/competency/services/handlers/user.ts @@ -43,7 +43,7 @@ export class AddonCompetencyUserHandlerService implements CoreUserProfileHandler * @inheritdoc */ async isEnabled(): Promise { - return true; + return AddonCompetency.areCompetenciesEnabled(); } /** diff --git a/src/addons/competency/tests/behat/navigation.feature b/src/addons/competency/tests/behat/navigation.feature index e6f833b08..2913696df 100644 --- a/src/addons/competency/tests/behat/navigation.feature +++ b/src/addons/competency/tests/behat/navigation.feature @@ -175,6 +175,15 @@ Feature: Test competency navigation Then I should find "Desserts are important" in the app But I should not find "Cakes" in the app + Given the following config values are set as admin: + | enabled | 0 | core_competency | + When I entered the course "Course 1" as "student1" in the app + Then I should not find "Competencies" in the app + + When I press the back button in the app + And I press the user menu button in the app + And I should not find "Learning plans" in the app + Scenario: Mobile navigation (teacher) Given I entered the course "Course 1" as "teacher1" in the app diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 77149f3a8..93ebfd090 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -127,7 +127,7 @@ import { CoreSitePluginsAssignSubmissionComponent } from '@features/siteplugins/ import { ADDON_BADGES_SERVICES } from '@addons/badges/badges.module'; import { ADDON_CALENDAR_SERVICES } from '@addons/calendar/calendar.module'; import { getCourseCompletionServices } from '@addons/coursecompletion/coursecompletion.module'; -import { ADDON_COMPETENCY_SERVICES } from '@addons/competency/competency.module'; +import { getCompetencyServices } from '@addons/competency/competency.module'; import { ADDON_MESSAGEOUTPUT_SERVICES } from '@addons/messageoutput/messageoutput.module'; import { ADDON_MESSAGES_SERVICES } from '@addons/messages/messages.module'; import { ADDON_MOD_ASSIGN_SERVICES } from '@addons/mod/assign/assign.module'; @@ -307,7 +307,6 @@ export class CoreCompileProvider { ...extraProviders, ...ADDON_BADGES_SERVICES, ...ADDON_CALENDAR_SERVICES, - ...ADDON_COMPETENCY_SERVICES, ...ADDON_MESSAGEOUTPUT_SERVICES, ...ADDON_MESSAGES_SERVICES, ...ADDON_MOD_ASSIGN_SERVICES, @@ -407,6 +406,7 @@ export class CoreCompileProvider { */ async getLazyLibraries(): Promise[]> { const ADDON_MOD_WORKSHOP_SERVICES = await getWorkshopServices(); + const ADDON_COMPETENCY_SERVICES = await getCompetencyServices(); const ADDON_COURSECOMPLETION_SERVICES = await getCourseCompletionServices(); const CORE_COMMENTS_SERVICES = await getCommentsServices(); @@ -414,6 +414,7 @@ export class CoreCompileProvider { return [ ...ADDON_MOD_WORKSHOP_SERVICES, + ...ADDON_COMPETENCY_SERVICES, ...ADDON_COURSECOMPLETION_SERVICES, ...CORE_COMMENTS_SERVICES, ...CORE_TAG_SERVICES,