diff --git a/src/core/features/dataprivacy/components/newrequest/newrequest.ts b/src/core/features/dataprivacy/components/newrequest/newrequest.ts index 7e75e4e6b..fb603eae5 100644 --- a/src/core/features/dataprivacy/components/newrequest/newrequest.ts +++ b/src/core/features/dataprivacy/components/newrequest/newrequest.ts @@ -33,6 +33,7 @@ import { ModalController } from '@singletons'; export class CoreDataPrivacyNewRequestComponent implements OnInit { @Input() accessInfo?: CoreDataPrivacyGetAccessInformationWSResponse; + @Input() createType?: CoreDataPrivacyDataRequestType; message = ''; @@ -65,9 +66,24 @@ export class CoreDataPrivacyNewRequestComponent implements OnInit { return; } - // Just in case only deleting is allowed, change the default type. - if (!this.accessInfo.cancreatedatadownloadrequest && this.accessInfo.cancreatedatadeletionrequest){ - this.typeControl.setValue(CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_DELETE); + switch (this.createType) { + case CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_EXPORT: + if (this.accessInfo?.cancreatedatadownloadrequest) { + this.typeControl.setValue(this.createType); + + } + break; + case CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_DELETE: + if (this.accessInfo?.cancreatedatadeletionrequest) { + this.typeControl.setValue(this.createType); + } + break; + default: + // Just in case only deleting is allowed, change the default type. + if (!this.accessInfo.cancreatedatadownloadrequest && this.accessInfo.cancreatedatadeletionrequest){ + this.typeControl.setValue(CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_DELETE); + } + break; } } diff --git a/src/core/features/dataprivacy/dataprivacy.module.ts b/src/core/features/dataprivacy/dataprivacy.module.ts index 6891562d4..d0c6a22ce 100644 --- a/src/core/features/dataprivacy/dataprivacy.module.ts +++ b/src/core/features/dataprivacy/dataprivacy.module.ts @@ -19,6 +19,9 @@ import { Routes } from '@angular/router'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreDataPrivacyComponentsModule } from './components/components.module'; import { CORE_DATAPRIVACY_PAGE_NAME } from './constants'; +import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; +import { CoreDataPrivacyDataRequestsLinkHandler } from './services/handlers/datarequests-link'; +import { CoreDataPrivacyCreateDataRequestLinkHandler } from './services/handlers/createdatarequest-link'; const routes: Routes = [ { @@ -38,6 +41,8 @@ const routes: Routes = [ multi: true, useValue: () => { CoreUserDelegate.registerHandler(CoreDataPrivacyUserHandler.instance); + CoreContentLinksDelegate.registerHandler(CoreDataPrivacyDataRequestsLinkHandler.instance); + CoreContentLinksDelegate.registerHandler(CoreDataPrivacyCreateDataRequestLinkHandler.instance); }, }, ], diff --git a/src/core/features/dataprivacy/pages/main/main.ts b/src/core/features/dataprivacy/pages/main/main.ts index dfbc8a23f..037f59970 100644 --- a/src/core/features/dataprivacy/pages/main/main.ts +++ b/src/core/features/dataprivacy/pages/main/main.ts @@ -17,9 +17,11 @@ import { CoreDataPrivacyContactDPOComponent } from '@features/dataprivacy/compon import { CoreDataPrivacyNewRequestComponent } from '@features/dataprivacy/components/newrequest/newrequest'; import { CoreDataPrivacy, + CoreDataPrivacyDataRequestType, CoreDataPrivacyGetAccessInformationWSResponse, CoreDataPrivacyRequest, } from '@features/dataprivacy/services/dataprivacy'; +import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; @@ -46,13 +48,33 @@ export class CoreDataPrivacyMainPage implements OnInit { * @inheritdoc */ async ngOnInit(): Promise { - this.fetchContent(); - this.isTablet = CoreScreen.isTablet; this.layoutSubscription = CoreScreen.layoutObservable.subscribe(() => { this.isTablet = CoreScreen.isTablet; }); + + await this.fetchContent(); + + const createType = CoreNavigator.getRouteNumberParam('createType') as CoreDataPrivacyDataRequestType; + + switch (createType) { + case CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_EXPORT: + if (this.accessInfo?.cancreatedatadownloadrequest) { + this.newRequest(createType); + } + break; + case CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_DELETE: + if (this.accessInfo?.cancreatedatadeletionrequest) { + this.newRequest(createType); + } + break; + case CoreDataPrivacyDataRequestType.DATAREQUEST_TYPE_OTHERS: + if (this.accessInfo?.cancontactdpo) { + this.contactDPO(); + } + break; + } } /** @@ -111,12 +133,13 @@ export class CoreDataPrivacyMainPage implements OnInit { /** * Open the new request modal. */ - async newRequest(): Promise { + async newRequest(createType?: CoreDataPrivacyDataRequestType): Promise { // Create and show the modal. const succeed = await CoreDomUtils.openModal({ component: CoreDataPrivacyNewRequestComponent, componentProps: { accessInfo: this.accessInfo, + createType, }, }); diff --git a/src/core/features/dataprivacy/services/handlers/createdatarequest-link.ts b/src/core/features/dataprivacy/services/handlers/createdatarequest-link.ts new file mode 100644 index 000000000..eeb9f376c --- /dev/null +++ b/src/core/features/dataprivacy/services/handlers/createdatarequest-link.ts @@ -0,0 +1,62 @@ +// (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 } from '@angular/router'; +import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; +import { CORE_DATAPRIVACY_PAGE_NAME } from '@features/dataprivacy/constants'; +import { CoreNavigator } from '@services/navigator'; +import { makeSingleton } from '@singletons'; +import { CoreDataPrivacy } from '../dataprivacy'; + +/** + * Handler to treat data requests creation links. + */ +@Injectable({ providedIn: 'root' }) +export class CoreDataPrivacyCreateDataRequestLinkHandlerService extends CoreContentLinksHandlerBase { + + name = 'CoreDataPrivacyCreateDataRequestLinkHandler'; + pattern = /\/admin\/tool\/dataprivacy\/createdatarequest\.php.*([?&]type=\d+)/; + + /** + * @inheritdoc + */ + getActions( + siteIds: string[], + url: string, + params: Record, + ): CoreContentLinksAction[] | Promise { + + const pageParams: Params = { + createType: Number(params.type), + }; + + return [{ + action: async (siteId): Promise => { + await CoreNavigator.navigateToSitePath(CORE_DATAPRIVACY_PAGE_NAME, { params: pageParams, siteId }); + }, + }]; + } + + /** + * @inheritdoc + */ + async isEnabled(): Promise { + return await CoreDataPrivacy.isEnabled(); + } + +} + +export const CoreDataPrivacyCreateDataRequestLinkHandler = makeSingleton(CoreDataPrivacyCreateDataRequestLinkHandlerService); diff --git a/src/core/features/dataprivacy/services/handlers/datarequests-link.ts b/src/core/features/dataprivacy/services/handlers/datarequests-link.ts new file mode 100644 index 000000000..ce7fb8d0e --- /dev/null +++ b/src/core/features/dataprivacy/services/handlers/datarequests-link.ts @@ -0,0 +1,52 @@ +// (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 { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; +import { CORE_DATAPRIVACY_PAGE_NAME } from '@features/dataprivacy/constants'; +import { CoreNavigator } from '@services/navigator'; +import { makeSingleton } from '@singletons'; +import { CoreDataPrivacy } from '../dataprivacy'; + +/** + * Handler to treat data requests links. + */ +@Injectable({ providedIn: 'root' }) +export class CoreDataPrivacyDataRequestsLinkHandlerService extends CoreContentLinksHandlerBase { + + name = 'CoreDataPrivacyDataRequestsLinkHandler'; + pattern = /\/admin\/tool\/dataprivacy\/mydatarequests\.php/; + + /** + * @inheritdoc + */ + getActions(): CoreContentLinksAction[] { + return [{ + action: async (siteId): Promise => { + await CoreNavigator.navigateToSitePath(CORE_DATAPRIVACY_PAGE_NAME, { siteId }); + }, + }]; + } + + /** + * @inheritdoc + */ + async isEnabled(): Promise { + return await CoreDataPrivacy.isEnabled(); + } + +} + +export const CoreDataPrivacyDataRequestsLinkHandler = makeSingleton(CoreDataPrivacyDataRequestsLinkHandlerService); diff --git a/src/core/features/dataprivacy/services/handlers/user.ts b/src/core/features/dataprivacy/services/handlers/user.ts index 60698c03d..679daf47d 100644 --- a/src/core/features/dataprivacy/services/handlers/user.ts +++ b/src/core/features/dataprivacy/services/handlers/user.ts @@ -32,7 +32,7 @@ export class CoreDataPrivacyUserHandlerService implements CoreUserProfileHandler protected pageName = CORE_DATAPRIVACY_PAGE_NAME; type = CoreUserProfileHandlerType.LIST_ACCOUNT_ITEM; - name = 'CoreDataPrivacyDelegate'; + name = 'CoreDataPrivacy'; priority = 100; /** diff --git a/src/core/features/dataprivacy/tests/datarequests-link.test.ts b/src/core/features/dataprivacy/tests/datarequests-link.test.ts new file mode 100644 index 000000000..f757e5d54 --- /dev/null +++ b/src/core/features/dataprivacy/tests/datarequests-link.test.ts @@ -0,0 +1,71 @@ +// (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 { CoreDataPrivacyDataRequestsLinkHandler } from '@features/dataprivacy/services/handlers/datarequests-link'; +import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; +import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; +import { mockSingleton } from '@/testing/utils'; +import { CoreSites } from '@services/sites'; +import { CoreSite } from '@classes/sites/site'; +import { CoreNavigator } from '@services/navigator'; +import { CORE_DATAPRIVACY_PAGE_NAME } from '@features/dataprivacy/constants'; +import { CoreDataPrivacyCreateDataRequestLinkHandler } from '../services/handlers/createdatarequest-link'; +import { CoreDataPrivacy } from '../services/dataprivacy'; + +describe('CoreDataPrivacyDataRequestsLinkHandlerService', () => { + + let site: CoreSite; + + beforeAll(() => { + site = new CoreSite('siteId', 'https://school.edu', ''); + + mockSingleton(CoreDataPrivacy, { + isEnabled: () => Promise.resolve(true), + }); + + CoreContentLinksDelegate.registerHandler(CoreDataPrivacyDataRequestsLinkHandler.instance); + CoreContentLinksDelegate.registerHandler(CoreDataPrivacyCreateDataRequestLinkHandler.instance); + + mockSingleton(CoreNavigator, ['navigateToSitePath']); + mockSingleton(CoreSites, { + isLoggedIn: () => true, + getCurrentSiteId: () => site.id, + getSiteIdsFromUrl: () => Promise.resolve([site.id]), + getSite: () => Promise.resolve(site), + }); + }); + + it('opens data privacy page', async () => { + await CoreContentLinksHelper.handleLink('https://school.edu/admin/tool/dataprivacy/mydatarequests.php'); + + expect(CoreNavigator.navigateToSitePath).toHaveBeenCalledWith(CORE_DATAPRIVACY_PAGE_NAME, { siteId: site.id }); + }); + + it('opens data request modal', async () => { + await CoreContentLinksHelper.handleLink('https://school.edu/admin/tool/dataprivacy/createdatarequest.php?type=1'); + + expect(CoreNavigator.navigateToSitePath).toHaveBeenCalledWith( + CORE_DATAPRIVACY_PAGE_NAME, + { params: { createType: 1 }, siteId: site.id }, + ); + + await CoreContentLinksHelper.handleLink('https://school.edu/admin/tool/dataprivacy/createdatarequest.php?type=3'); + + expect(CoreNavigator.navigateToSitePath).toHaveBeenCalledWith( + CORE_DATAPRIVACY_PAGE_NAME, + { params: { createType: 3 }, siteId: site.id }, + ); + }); + +});