MOBILE-3901 insights: Support insight action links

main
Dani Palou 2021-11-02 08:40:40 +01:00
parent 7618da4bfa
commit 94c656d015
7 changed files with 269 additions and 0 deletions

View File

@ -1073,6 +1073,12 @@
"addon.privatefiles.sitefiles": "moodle",
"addon.qtype_essay.maxwordlimitboundary": "qtype_essay",
"addon.qtype_essay.minwordlimitboundary": "qtype_essay",
"addon.report_insights.actionsaved": "report_insights",
"addon.report_insights.fixedack": "analytics",
"addon.report_insights.incorrectlyflagged": "analytics",
"addon.report_insights.notapplicable": "analytics",
"addon.report_insights.notuseful": "analytics",
"addon.report_insights.useful": "analytics",
"addon.storagemanager.deletecourse": "local_moodlemobileapp",
"addon.storagemanager.deletecourses": "local_moodlemobileapp",
"addon.storagemanager.deletedatafrom": "local_moodlemobileapp",

View File

@ -30,6 +30,7 @@ import { AddonPrivateFilesModule } from './privatefiles/privatefiles.module';
import { AddonQbehaviourModule } from './qbehaviour/qbehaviour.module';
import { AddonQtypeModule } from './qtype/qtype.module';
import { AddonRemoteThemesModule } from './remotethemes/remotethemes.module';
import { AddonReportModule } from './report/report.module';
import { AddonStorageManagerModule } from './storagemanager/storagemanager.module';
import { AddonUserProfileFieldModule } from './userprofilefield/userprofilefield.module';
@ -51,6 +52,7 @@ import { AddonUserProfileFieldModule } from './userprofilefield/userprofilefield
AddonQbehaviourModule,
AddonQtypeModule,
AddonRemoteThemesModule,
AddonReportModule,
AddonStorageManagerModule,
AddonUserProfileFieldModule,
],

View File

@ -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 { AddonReportInsightsActionLinkHandler } from './services/handlers/action-link';
@NgModule({
imports: [],
exports: [],
providers: [
{
provide: APP_INITIALIZER,
multi: true,
useValue: () => {
CoreContentLinksDelegate.registerHandler(AddonReportInsightsActionLinkHandler.instance);
},
},
],
})
export class AddonReportInsightsModule {}

View File

@ -0,0 +1,8 @@
{
"actionsaved": "Your feedback of '{{$a}}' has been saved",
"fixedack": "Accept",
"incorrectlyflagged": "Incorrectly flagged",
"notapplicable": "Not applicable",
"notuseful": "Not useful",
"useful": "Useful"
}

View File

@ -0,0 +1,104 @@
// (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 { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton, Translate } from '@singletons';
import { AddonReportInsights } from '../insights';
// Bulk actions supported, along with the related lang string.
const BULK_ACTIONS = {
fixed: 'addon.report_insights.fixedack',
incorrectlyflagged: 'addon.report_insights.incorrectlyflagged',
notapplicable: 'addon.report_insights.notapplicable',
notuseful: 'addon.report_insights.notuseful',
useful: 'addon.report_insights.useful',
};
/**
* Content links handler for calendar view page.
*/
@Injectable({ providedIn: 'root' })
export class AddonReportInsightsActionLinkHandlerService extends CoreContentLinksHandlerBase {
name = 'AddonReportInsightsActionLinkHandler';
pattern = /\/report\/insights\/action\.php/;
/**
* @inheritdoc
*/
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: async (siteId?: string): Promise<void> => {
// Send the action.
const modal = await CoreDomUtils.showModalLoading('core.sending', true);
try {
await AddonReportInsights.sendActionExecuted(params.action, [Number(params.predictionid)], siteId);
} catch (error) {
CoreDomUtils.showErrorModal(error);
return;
} finally {
modal.dismiss();
}
if (BULK_ACTIONS[params.action]) {
// Done, display a toast.
CoreDomUtils.showToast(Translate.instant('addon.report_insights.actionsaved', {
$a: Translate.instant(BULK_ACTIONS[params.action]),
}));
} else if (!params.forwardurl) {
// Forward URL not defined, display a toast.
CoreDomUtils.showToast('core.success', true);
} else {
// Try to open the link in the app.
const forwardUrl = decodeURIComponent(params.forwardurl);
const treated = await CoreContentLinksHelper.handleLink(forwardUrl);
if (!treated) {
// Cannot be opened in the app, open in browser.
const site = await CoreSites.getSite(siteId);
await site.openInBrowserWithAutoLoginIfSameSite(forwardUrl);
}
}
},
}];
}
/**
* @inheritdoc
*/
async isEnabled(siteId: string, url: string, params: Record<string, string>): Promise<boolean> {
if (!params.action || !params.predictionid) {
// Required params missing.
return false;
}
return await AddonReportInsights.canSendActionInSite(siteId);
}
}
export const AddonReportInsightsActionLinkHandler = makeSingleton(AddonReportInsightsActionLinkHandlerService);

View File

@ -0,0 +1,93 @@
// (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 { CoreSites } from '@services/sites';
import { CoreSite } from '@classes/site';
import { makeSingleton } from '@singletons';
import { CoreWSExternalWarning } from '@services/ws';
import { CoreWSError } from '@classes/errors/wserror';
/**
* Service to handle insights.
*/
@Injectable({ providedIn: 'root' })
export class AddonReportInsightsService {
/**
* Check if site supports sending insight actions.
*
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with boolean: whether it's supported.
*/
async canSendActionInSite(siteId?: string): Promise<boolean> {
const site = await CoreSites.getSite(siteId);
return this.canSendAction(site);
}
/**
* Check if site supports sending insight actions.
*
* @param site Site. If not defined, current site.
* @return Whether it's supported.
*/
canSendAction(site?: CoreSite): boolean {
site = site || CoreSites.getCurrentSite();
return !!site?.wsAvailable('report_insights_action_executed');
}
/**
* Send an action.
*
* @param actionName Action name.
* @param ids List of IDs.
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved if success.
*/
async sendActionExecuted(actionName: string, ids: number[], siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
const params: AddonReportInsightsActionExecutedWSParams = {
actionname: actionName,
predictionids: ids,
};
const result = await site.write<AddonReportInsightsActionExecutedWSResult>('report_insights_action_executed', params);
if (result.warnings?.length) {
throw new CoreWSError(result.warnings[0]);
}
}
}
export const AddonReportInsights = makeSingleton(AddonReportInsightsService);
/**
* Params of WS report_insights_action_executed.
*/
export type AddonReportInsightsActionExecutedWSParams = {
actionname: string; // The name of the action.
predictionids: number[]; // Array of prediction ids.
};
/**
* Result of WS report_insights_action_executed.
*/
export type AddonReportInsightsActionExecutedWSResult = {
warnings?: CoreWSExternalWarning[];
};

View File

@ -0,0 +1,23 @@
// (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 { AddonReportInsightsModule } from './insights/insights.module';
@NgModule({
imports: [
AddonReportInsightsModule,
],
})
export class AddonReportModule { }