MOBILE-2338 data: Implement link handlers
parent
44e8acbb5e
commit
88269125b6
|
@ -23,6 +23,4 @@ export class AddonModDataFieldPluginComponent {
|
||||||
@Input() database?: any; // Database object.
|
@Input() database?: any; // Database object.
|
||||||
@Input() error?: string; // Error when editing.
|
@Input() error?: string; // Error when editing.
|
||||||
@Input() viewAction: string; // Action to perform.
|
@Input() viewAction: string; // Action to perform.
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<a *ngIf="action == 'more'" ion-button icon-only clear [href]="url" core-link capture-link="true" [title]="'addon.mod_data.more' | translate">
|
<a *ngIf="action == 'more'" ion-button icon-only clear [href]="url" core-link capture="true" [title]="'addon.mod_data.more' | translate">
|
||||||
<ion-icon name="search"></ion-icon>
|
<ion-icon name="search"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a *ngIf="action == 'edit'" ion-button icon-only clear [href]="url" core-link capture-link="true" [title]="'core.edit' | translate">
|
<a *ngIf="action == 'edit'" ion-button icon-only clear [href]="url" core-link capture="true" [title]="'core.edit' | translate">
|
||||||
<ion-icon name="cog"></ion-icon>
|
<ion-icon name="cog"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a *ngIf="action == 'delete' && !entry.deleted" ion-button icon-only clear [href]="url" core-link capture-link="true" [title]="'core.delete' | translate">
|
<a *ngIf="action == 'delete' && !entry.deleted" ion-button icon-only clear [href]="url" core-link capture="true" [title]="'core.delete' | translate">
|
||||||
<ion-icon name="trash"></ion-icon>
|
<ion-icon name="trash"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@
|
||||||
<ion-icon name="undo"></ion-icon>
|
<ion-icon name="undo"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a *ngIf="action == 'approve'" ion-button icon-only clear [href]="url" core-link capture-link="true" [title]="'addon.mod_data.approve' | translate">
|
<a *ngIf="action == 'approve'" ion-button icon-only clear [href]="url" core-link capture="true" [title]="'addon.mod_data.approve' | translate">
|
||||||
<ion-icon name="thumbs-up"></ion-icon>
|
<ion-icon name="thumbs-up"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a *ngIf="action == 'disapprove'" ion-button icon-only clear [href]="url" core-link capture-link="true" [title]="'addon.mod_data.disapprove' | translate">
|
<a *ngIf="action == 'disapprove'" ion-button icon-only clear [href]="url" core-link capture="true" [title]="'addon.mod_data.disapprove' | translate">
|
||||||
<ion-icon name="thumbs-down"></ion-icon>
|
<ion-icon name="thumbs-down"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,4 @@ export class AddonModDataFieldPluginComponent implements OnInit {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate the plugin data.
|
|
||||||
*
|
|
||||||
* @return {Promise<any>} Promise resolved when done.
|
|
||||||
*/
|
|
||||||
invalidate(): Promise<any> {
|
|
||||||
return Promise.resolve(this.dynamicComponent && this.dynamicComponent.callComponentFunction('invalidate', []));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ import { AddonModDataComponentsModule } from './components/components.module';
|
||||||
import { AddonModDataModuleHandler } from './providers/module-handler';
|
import { AddonModDataModuleHandler } from './providers/module-handler';
|
||||||
import { AddonModDataProvider } from './providers/data';
|
import { AddonModDataProvider } from './providers/data';
|
||||||
import { AddonModDataLinkHandler } from './providers/link-handler';
|
import { AddonModDataLinkHandler } from './providers/link-handler';
|
||||||
|
import { AddonModDataApproveLinkHandler } from './providers/approve-link-handler';
|
||||||
|
import { AddonModDataDeleteLinkHandler } from './providers/delete-link-handler';
|
||||||
|
import { AddonModDataShowLinkHandler } from './providers/show-link-handler';
|
||||||
|
import { AddonModDataEditLinkHandler } from './providers/edit-link-handler';
|
||||||
import { AddonModDataHelperProvider } from './providers/helper';
|
import { AddonModDataHelperProvider } from './providers/helper';
|
||||||
import { AddonModDataPrefetchHandler } from './providers/prefetch-handler';
|
import { AddonModDataPrefetchHandler } from './providers/prefetch-handler';
|
||||||
import { AddonModDataSyncProvider } from './providers/sync';
|
import { AddonModDataSyncProvider } from './providers/sync';
|
||||||
|
@ -43,6 +47,10 @@ import { AddonModDataFieldModule } from './fields/field.module';
|
||||||
AddonModDataPrefetchHandler,
|
AddonModDataPrefetchHandler,
|
||||||
AddonModDataHelperProvider,
|
AddonModDataHelperProvider,
|
||||||
AddonModDataLinkHandler,
|
AddonModDataLinkHandler,
|
||||||
|
AddonModDataApproveLinkHandler,
|
||||||
|
AddonModDataDeleteLinkHandler,
|
||||||
|
AddonModDataShowLinkHandler,
|
||||||
|
AddonModDataEditLinkHandler,
|
||||||
AddonModDataSyncCronHandler,
|
AddonModDataSyncCronHandler,
|
||||||
AddonModDataSyncProvider,
|
AddonModDataSyncProvider,
|
||||||
AddonModDataOfflineProvider,
|
AddonModDataOfflineProvider,
|
||||||
|
@ -54,10 +62,16 @@ export class AddonModDataModule {
|
||||||
constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModDataModuleHandler,
|
constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModDataModuleHandler,
|
||||||
prefetchDelegate: CoreCourseModulePrefetchDelegate, prefetchHandler: AddonModDataPrefetchHandler,
|
prefetchDelegate: CoreCourseModulePrefetchDelegate, prefetchHandler: AddonModDataPrefetchHandler,
|
||||||
contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModDataLinkHandler,
|
contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModDataLinkHandler,
|
||||||
cronDelegate: CoreCronDelegate, syncHandler: AddonModDataSyncCronHandler) {
|
cronDelegate: CoreCronDelegate, syncHandler: AddonModDataSyncCronHandler,
|
||||||
|
approveLinkHandler: AddonModDataApproveLinkHandler, deleteLinkHandler: AddonModDataDeleteLinkHandler,
|
||||||
|
showLinkHandler: AddonModDataShowLinkHandler, editLinkHandler: AddonModDataEditLinkHandler) {
|
||||||
moduleDelegate.registerHandler(moduleHandler);
|
moduleDelegate.registerHandler(moduleHandler);
|
||||||
prefetchDelegate.registerHandler(prefetchHandler);
|
prefetchDelegate.registerHandler(prefetchHandler);
|
||||||
contentLinksDelegate.registerHandler(linkHandler);
|
contentLinksDelegate.registerHandler(linkHandler);
|
||||||
|
contentLinksDelegate.registerHandler(approveLinkHandler);
|
||||||
|
contentLinksDelegate.registerHandler(deleteLinkHandler);
|
||||||
|
contentLinksDelegate.registerHandler(showLinkHandler);
|
||||||
|
contentLinksDelegate.registerHandler(editLinkHandler);
|
||||||
cronDelegate.register(syncHandler);
|
cronDelegate.register(syncHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
<ion-input *ngIf="mode != 'show'" type="url" [formControlName]="'f_'+field.id" [placeholder]="field.name" [(ngModel)]="val"></ion-input>
|
<ion-input *ngIf="mode != 'show'" type="url" [formControlName]="'f_'+field.id" [placeholder]="field.name" [(ngModel)]="val"></ion-input>
|
||||||
|
|
||||||
<a *ngIf="mode == 'show' && value && value.content" [href]="value.content" core-link capture-link="true">{{field.name}}</a>
|
<a *ngIf="mode == 'show' && value && value.content" [href]="value.content" core-link capture="true">{{field.name}}</a>
|
|
@ -1,3 +1,41 @@
|
||||||
{
|
{
|
||||||
|
"addentries": "Add entries",
|
||||||
|
"advancedsearch": "Advanced search",
|
||||||
|
"alttext": "Alternative text",
|
||||||
|
"approve": "Approve",
|
||||||
|
"approved": "Approved",
|
||||||
|
"ascending": "Ascending",
|
||||||
|
"authorfirstname": "Author first name",
|
||||||
|
"authorlastname": "Author surname",
|
||||||
|
"confirmdeleterecord": "Are you sure you want to delete this entry?",
|
||||||
|
"descending": "Descending",
|
||||||
|
"disapprove": "Undo approval",
|
||||||
|
"emptyaddform": "You did not fill out any fields!",
|
||||||
|
"entrieslefttoadd": "You must add {{$a.entriesleft}} more entry/entries in order to complete this activity",
|
||||||
|
"entrieslefttoaddtoview": "You must add {{$a.entrieslefttoview}} more entry/entries before you can view other participants' entries.",
|
||||||
|
"errorapproving": "Error approving or unapproving entry.",
|
||||||
|
"errordeleting": "Error deleting entry.",
|
||||||
|
"errormustsupplyvalue": "You must supply a value here.",
|
||||||
|
"expired": "Sorry, this activity closed on {{$a}} and is no longer available",
|
||||||
|
"fields": "Fields",
|
||||||
|
"latlongboth": "Both latitude and longitude are required.",
|
||||||
|
"menuchoose": "Choose...",
|
||||||
|
"more": "More",
|
||||||
|
"nomatch": "No matching entries found!",
|
||||||
|
"norecords": "No entries in database",
|
||||||
|
"notapproved": "Entry is not approved yet.",
|
||||||
|
"notopenyet": "Sorry, this activity is not available until {{$a}}",
|
||||||
|
"numrecords": "{{$a}} entries",
|
||||||
|
"other": "Other",
|
||||||
|
"recordapproved": "Entry approved",
|
||||||
|
"recorddeleted": "Entry deleted",
|
||||||
|
"recorddisapproved": "Entry unapproved",
|
||||||
|
"resetsettings": "Reset filters",
|
||||||
|
"search": "Search",
|
||||||
|
"single": "View single",
|
||||||
|
"selectedrequired": "All selected required",
|
||||||
|
"single": "View single",
|
||||||
|
"timeadded": "Time added",
|
||||||
|
"timemodified": "Time modified",
|
||||||
|
"usedate": "Include in search."
|
||||||
}
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 '@core/contentlinks/classes/base-handler';
|
||||||
|
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||||
|
import { AddonModDataProvider } from './data';
|
||||||
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content links handler for database approve/disapprove entry.
|
||||||
|
* Match mod/data/view.php?d=6&approve=5 with a valid data id and entryid.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
|
name = 'AddonModDataApproveLinkHandler';
|
||||||
|
featureName = 'CoreCourseModuleDelegate_AddonModData';
|
||||||
|
pattern = /\/mod\/data\/view\.php.*([\?\&](d|approve|disapprove)=\d+)/;
|
||||||
|
|
||||||
|
constructor(private dataProvider: AddonModDataProvider, private courseProvider: CoreCourseProvider,
|
||||||
|
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to help get courseId.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Database Id.
|
||||||
|
* @param {string} siteId Site Id, if not set, current site will be used.
|
||||||
|
* @param {number} courseId Course Id if already set.
|
||||||
|
* @return {Promise<number>} Resolved with course Id when done.
|
||||||
|
*/
|
||||||
|
protected getActivityCourseIdIfNotSet(dataId: number, siteId: string, courseId: number): Promise<number> {
|
||||||
|
if (courseId) {
|
||||||
|
return Promise.resolve(courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
|
||||||
|
return module.course;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of actions for a link (url).
|
||||||
|
*
|
||||||
|
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||||
|
*/
|
||||||
|
getActions(siteIds: string[], url: string, params: any, courseId?: number):
|
||||||
|
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
return [{
|
||||||
|
action: (siteId, navCtrl?): void => {
|
||||||
|
const modal = this.domUtils.showModalLoading(),
|
||||||
|
dataId = parseInt(params.d, 10),
|
||||||
|
entryId = parseInt(params.approve, 10) || parseInt(params.disapprove, 10),
|
||||||
|
approve = parseInt(params.approve, 10) ? true : false;
|
||||||
|
|
||||||
|
this.getActivityCourseIdIfNotSet(dataId, siteId, courseId).then((cId) => {
|
||||||
|
courseId = cId;
|
||||||
|
|
||||||
|
// Approve/disapprove entry.
|
||||||
|
return this.dataProvider.approveEntry(dataId, entryId, approve, courseId, siteId).catch((message) => {
|
||||||
|
modal.dismiss();
|
||||||
|
this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errorapproving', true);
|
||||||
|
|
||||||
|
return Promise.reject(null);
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
const promises = [];
|
||||||
|
promises.push(this.dataProvider.invalidateEntryData(dataId, entryId, siteId));
|
||||||
|
promises.push(this.dataProvider.invalidateEntriesData(dataId, siteId));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
}).then(() => {
|
||||||
|
this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId}, siteId);
|
||||||
|
|
||||||
|
modal.dismiss();
|
||||||
|
this.domUtils.showToast(approve ? 'addon.mod_data.recordapproved' : 'addon.mod_data.recorddisapproved', true,
|
||||||
|
3000);
|
||||||
|
}).finally(() => {
|
||||||
|
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||||
|
* If not defined, defaults to true.
|
||||||
|
*
|
||||||
|
* @param {string} siteId The site ID.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||||
|
*/
|
||||||
|
isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise<boolean> {
|
||||||
|
if (typeof params.d == 'undefined' || (typeof params.approve == 'undefined' && typeof params.disapprove == 'undefined')) {
|
||||||
|
// Required fields not defined. Cannot treat the URL.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dataProvider.isPluginEnabled(siteId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
import { CoreFilepoolProvider } from '@providers/filepool';
|
||||||
import { AddonModDataOfflineProvider } from './offline';
|
import { AddonModDataOfflineProvider } from './offline';
|
||||||
|
import { CoreAppProvider } from '@providers/app';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that provides some features for databases.
|
* Service that provides some features for databases.
|
||||||
|
@ -32,7 +33,8 @@ export class AddonModDataProvider {
|
||||||
protected logger;
|
protected logger;
|
||||||
|
|
||||||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
|
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
|
||||||
private filepoolProvider: CoreFilepoolProvider, private dataOffline: AddonModDataOfflineProvider) {
|
private filepoolProvider: CoreFilepoolProvider, private dataOffline: AddonModDataOfflineProvider,
|
||||||
|
private appProvider: CoreAppProvider) {
|
||||||
this.logger = logger.getInstance('AddonModDataProvider');
|
this.logger = logger.getInstance('AddonModDataProvider');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +62,51 @@ export class AddonModDataProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Approves or unapproves an entry.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Database ID.
|
||||||
|
* @param {number} entryId Entry ID.
|
||||||
|
* @param {boolean} approve Whether to approve (true) or unapprove the entry.
|
||||||
|
* @param {number} courseId Course ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when the action is done.
|
||||||
|
*/
|
||||||
|
approveEntry(dataId: number, entryId: number, approve: boolean, courseId: number, siteId?: string): Promise<any> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
// Convenience function to store a data to be synchronized later.
|
||||||
|
const storeOffline = (): Promise<any> => {
|
||||||
|
const action = approve ? 'approve' : 'disapprove';
|
||||||
|
|
||||||
|
return this.dataOffline.saveEntry(dataId, entryId, action, courseId, null, null, null, siteId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get if the opposite action is not synced.
|
||||||
|
const oppositeAction = approve ? 'disapprove' : 'approve';
|
||||||
|
|
||||||
|
return this.dataOffline.getEntry(dataId, entryId, oppositeAction, siteId).then(() => {
|
||||||
|
// Found. Just delete the action.
|
||||||
|
return this.dataOffline.deleteEntry(dataId, entryId, oppositeAction, siteId);
|
||||||
|
}).catch(() => {
|
||||||
|
|
||||||
|
if (!this.appProvider.isOnline()) {
|
||||||
|
// App is offline, store the action.
|
||||||
|
return storeOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.approveEntryOnline(entryId, approve, siteId).catch((error) => {
|
||||||
|
if (this.utils.isWebServiceError(error)) {
|
||||||
|
// The WebService has thrown an error, this means that responses cannot be submitted.
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't connect to server, store in offline.
|
||||||
|
return storeOffline();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Approves or unapproves an entry. It does not cache calls. It will fail if offline or cannot connect.
|
* Approves or unapproves an entry. It does not cache calls. It will fail if offline or cannot connect.
|
||||||
*
|
*
|
||||||
|
@ -79,6 +126,62 @@ export class AddonModDataProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an entry.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Database ID.
|
||||||
|
* @param {number} entryId Entry ID.
|
||||||
|
* @param {number} courseId Course ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when the action is done.
|
||||||
|
*/
|
||||||
|
deleteEntry(dataId: number, entryId: number, courseId: number, siteId?: string): Promise<any> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
// Convenience function to store a data to be synchronized later.
|
||||||
|
const storeOffline = (): Promise<any> => {
|
||||||
|
return this.dataOffline.saveEntry(dataId, entryId, 'delete', courseId, null, null, null, siteId);
|
||||||
|
};
|
||||||
|
|
||||||
|
let justAdded = false;
|
||||||
|
|
||||||
|
// Check if the opposite action is not synced and just delete it.
|
||||||
|
return this.dataOffline.getEntryActions(dataId, entryId, siteId).then((entries) => {
|
||||||
|
if (entries && entries.length) {
|
||||||
|
// Found. Delete other actions first.
|
||||||
|
const proms = entries.map((entry) => {
|
||||||
|
if (entry.action == 'add') {
|
||||||
|
justAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dataOffline.deleteEntry(dataId, entryId, entry.action, siteId);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(proms);
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
if (justAdded) {
|
||||||
|
// The field was added offline, delete and stop.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.appProvider.isOnline()) {
|
||||||
|
// App is offline, store the action.
|
||||||
|
return storeOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.deleteEntryOnline(entryId, siteId).catch((error) => {
|
||||||
|
if (this.utils.isWebServiceError(error)) {
|
||||||
|
// The WebService has thrown an error, this means that responses cannot be submitted.
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't connect to server, store in offline.
|
||||||
|
return storeOffline();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an entry. It does not cache calls. It will fail if offline or cannot connect.
|
* Deletes an entry. It does not cache calls. It will fail if offline or cannot connect.
|
||||||
*
|
*
|
||||||
|
@ -494,6 +597,20 @@ export class AddonModDataProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates database entry data.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Data ID for caching purposes.
|
||||||
|
* @param {number} entryId Entry ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||||
|
*/
|
||||||
|
invalidateEntryData(dataId: number, entryId: number, siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
return site.invalidateWsCacheForKey(this.getEntryCacheKey(dataId, entryId));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether or not the plugin is enabled in a certain site. Plugin is enabled if the database WS are available.
|
* Return whether or not the plugin is enabled in a certain site. Plugin is enabled if the database WS are available.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 '@core/contentlinks/classes/base-handler';
|
||||||
|
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||||
|
import { AddonModDataProvider } from './data';
|
||||||
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content links handler for database delete entry.
|
||||||
|
* Match mod/data/view.php?d=6&delete=5 with a valid data id and entryid.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
|
name = 'AddonModDataDeleteLinkHandler';
|
||||||
|
featureName = 'CoreCourseModuleDelegate_AddonModData';
|
||||||
|
pattern = /\/mod\/data\/view\.php.*([\?\&](d|delete)=\d+)/;
|
||||||
|
|
||||||
|
constructor(private dataProvider: AddonModDataProvider, private courseProvider: CoreCourseProvider,
|
||||||
|
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to help get courseId.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Database Id.
|
||||||
|
* @param {string} siteId Site Id, if not set, current site will be used.
|
||||||
|
* @param {number} courseId Course Id if already set.
|
||||||
|
* @return {Promise<number>} Resolved with course Id when done.
|
||||||
|
*/
|
||||||
|
protected getActivityCourseIdIfNotSet(dataId: number, siteId: string, courseId: number): Promise<number> {
|
||||||
|
if (courseId) {
|
||||||
|
return Promise.resolve(courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
|
||||||
|
return module.course;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of actions for a link (url).
|
||||||
|
*
|
||||||
|
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||||
|
*/
|
||||||
|
getActions(siteIds: string[], url: string, params: any, courseId?: number):
|
||||||
|
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
return [{
|
||||||
|
action: (siteId, navCtrl?): void => {
|
||||||
|
const modal = this.domUtils.showModalLoading(),
|
||||||
|
dataId = parseInt(params.d, 10),
|
||||||
|
entryId = parseInt(params.delete, 10);
|
||||||
|
|
||||||
|
this.getActivityCourseIdIfNotSet(dataId, siteId, courseId).then((cId) => {
|
||||||
|
courseId = cId;
|
||||||
|
|
||||||
|
// Delete entry.
|
||||||
|
return this.dataProvider.deleteEntry(dataId, entryId, courseId, siteId).catch((message) => {
|
||||||
|
modal.dismiss();
|
||||||
|
this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errordeleting', true);
|
||||||
|
|
||||||
|
return Promise.reject(null);
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
const promises = [];
|
||||||
|
promises.push(this.dataProvider.invalidateEntryData(dataId, entryId, siteId));
|
||||||
|
promises.push(this.dataProvider.invalidateEntriesData(dataId, siteId));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
}).then(() => {
|
||||||
|
this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId,
|
||||||
|
deleted: true}, siteId);
|
||||||
|
|
||||||
|
modal.dismiss();
|
||||||
|
this.domUtils.showToast('addon.mod_data.recorddeleted', true, 3000);
|
||||||
|
}).finally(() => {
|
||||||
|
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||||
|
* If not defined, defaults to true.
|
||||||
|
*
|
||||||
|
* @param {string} siteId The site ID.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||||
|
*/
|
||||||
|
isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise<boolean> {
|
||||||
|
if (typeof params.d == 'undefined' || typeof params.delete == 'undefined') {
|
||||||
|
// Required fields not defined. Cannot treat the URL.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dataProvider.isPluginEnabled(siteId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 '@core/contentlinks/classes/base-handler';
|
||||||
|
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||||
|
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||||
|
import { AddonModDataProvider } from './data';
|
||||||
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content links handler for database add or edit entry.
|
||||||
|
* Match mod/data/edit.php?d=6&rid=6 with a valid data and optional record id.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModDataEditLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
|
name = 'AddonModDataEditLinkHandler';
|
||||||
|
featureName = 'CoreCourseModuleDelegate_AddonModData';
|
||||||
|
pattern = /\/mod\/data\/edit\.php.*([\?\&](d|rid)=\d+)/;
|
||||||
|
|
||||||
|
constructor(private linkHelper: CoreContentLinksHelperProvider, private dataProvider: AddonModDataProvider,
|
||||||
|
private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of actions for a link (url).
|
||||||
|
*
|
||||||
|
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||||
|
*/
|
||||||
|
getActions(siteIds: string[], url: string, params: any, courseId?: number):
|
||||||
|
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
return [{
|
||||||
|
action: (siteId, navCtrl?): void => {
|
||||||
|
const modal = this.domUtils.showModalLoading(),
|
||||||
|
dataId = parseInt(params.d, 10),
|
||||||
|
rId = parseInt(params.rid, 10) || false;
|
||||||
|
|
||||||
|
this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
|
||||||
|
const stateParams = {
|
||||||
|
moduleId: module.id,
|
||||||
|
module: module,
|
||||||
|
courseId: module.course
|
||||||
|
};
|
||||||
|
|
||||||
|
if (rId) {
|
||||||
|
stateParams['entryId'] = rId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.linkHelper.goInSite(navCtrl, 'AddonModDataEditPage', stateParams, siteId);
|
||||||
|
}).finally(() => {
|
||||||
|
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||||
|
* If not defined, defaults to true.
|
||||||
|
*
|
||||||
|
* @param {string} siteId The site ID.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||||
|
*/
|
||||||
|
isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise<boolean> {
|
||||||
|
if (typeof params.d == 'undefined') {
|
||||||
|
// Id not defined. Cannot treat the URL.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dataProvider.isPluginEnabled(siteId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,10 +27,10 @@ export class AddonModDataOfflineProvider {
|
||||||
protected logger;
|
protected logger;
|
||||||
|
|
||||||
// Variables for database.
|
// Variables for database.
|
||||||
protected SURVEY_TABLE = 'addon_mod_data_entry';
|
protected DATA_ENTRY_TABLE = 'addon_mod_data_entry';
|
||||||
protected tablesSchema = [
|
protected tablesSchema = [
|
||||||
{
|
{
|
||||||
name: this.SURVEY_TABLE,
|
name: this.DATA_ENTRY_TABLE,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: 'dataid',
|
name: 'dataid',
|
||||||
|
@ -102,7 +102,7 @@ export class AddonModDataOfflineProvider {
|
||||||
*/
|
*/
|
||||||
deleteEntry(dataId: number, entryId: number, action: string, siteId?: string): Promise<any> {
|
deleteEntry(dataId: number, entryId: number, action: string, siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().deleteRecords(this.SURVEY_TABLE, {dataid: dataId, entryid: entryId, action: action});
|
return site.getDb().deleteRecords(this.DATA_ENTRY_TABLE, {dataid: dataId, entryid: entryId, action: action});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ export class AddonModDataOfflineProvider {
|
||||||
*/
|
*/
|
||||||
getAllEntries(siteId?: string): Promise<any> {
|
getAllEntries(siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().getAllRecords(this.SURVEY_TABLE);
|
return site.getDb().getAllRecords(this.DATA_ENTRY_TABLE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ export class AddonModDataOfflineProvider {
|
||||||
*/
|
*/
|
||||||
getDatabaseEntries(dataId: number, siteId?: string): Promise<any> {
|
getDatabaseEntries(dataId: number, siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().getRecords(this.SURVEY_TABLE, {dataid: dataId});
|
return site.getDb().getRecords(this.DATA_ENTRY_TABLE, {dataid: dataId});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ export class AddonModDataOfflineProvider {
|
||||||
*/
|
*/
|
||||||
getEntry(dataId: number, entryId: number, action: string, siteId?: string): Promise<any> {
|
getEntry(dataId: number, entryId: number, action: string, siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().getRecord(this.SURVEY_TABLE, {dataid: dataId, entryid: entryId, action: action});
|
return site.getDb().getRecord(this.DATA_ENTRY_TABLE, {dataid: dataId, entryid: entryId, action: action});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ export class AddonModDataOfflineProvider {
|
||||||
*/
|
*/
|
||||||
getEntryActions(dataId: number, entryId: number, siteId?: string): Promise<any> {
|
getEntryActions(dataId: number, entryId: number, siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().getRecords(this.SURVEY_TABLE, {dataid: dataId, entryid: entryId});
|
return site.getDb().getRecords(this.DATA_ENTRY_TABLE, {dataid: dataId, entryid: entryId});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,4 +207,38 @@ export class AddonModDataOfflineProvider {
|
||||||
return this.textUtils.concatenatePaths(folderPath, entryId + '_' + fieldId);
|
return this.textUtils.concatenatePaths(folderPath, entryId + '_' + fieldId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save an entry data to be sent later.
|
||||||
|
*
|
||||||
|
* @param {number} dataId Database ID.
|
||||||
|
* @param {number} entryId Database entry Id. If action is add entryId should be 0 and -timemodified will be used.
|
||||||
|
* @param {string} action Action to be done to the entry: [add, edit, delete, approve, disapprove]
|
||||||
|
* @param {number} courseId Course ID of the database.
|
||||||
|
* @param {number} [groupId] Group ID. Only provided when adding.
|
||||||
|
* @param {any[]} [fields] Array of field data of the entry if needed.
|
||||||
|
* @param {number} [timemodified] The time the entry was modified. If not defined, current time.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved if stored, rejected if failure.
|
||||||
|
*/
|
||||||
|
saveEntry(dataId: number, entryId: number, action: string, courseId: number, groupId?: number, fields?: any[],
|
||||||
|
timemodified?: number, siteId?: string): Promise<any> {
|
||||||
|
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
timemodified = timemodified || new Date().getTime();
|
||||||
|
entryId = typeof entryId == 'undefined' || entryId === null ? -timemodified : entryId;
|
||||||
|
const entry = {
|
||||||
|
dataid: dataId,
|
||||||
|
courseid: courseId,
|
||||||
|
groupid: groupId,
|
||||||
|
action: action,
|
||||||
|
entryid: entryId,
|
||||||
|
fields: fields,
|
||||||
|
timemodified: timemodified
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.getDb().insertRecord(this.DATA_ENTRY_TABLE, entry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 '@core/contentlinks/classes/base-handler';
|
||||||
|
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||||
|
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||||
|
import { AddonModDataProvider } from './data';
|
||||||
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content links handler for database show entry.
|
||||||
|
* Match mod/data/view.php?d=6&rid=5 with a valid data id and entryid.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModDataShowLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
|
name = 'AddonModDataShowLinkHandler';
|
||||||
|
featureName = 'CoreCourseModuleDelegate_AddonModData';
|
||||||
|
pattern = /\/mod\/data\/view\.php.*([\?\&](d|rid|page|group|mode)=\d+)/;
|
||||||
|
|
||||||
|
constructor(private linkHelper: CoreContentLinksHelperProvider, private dataProvider: AddonModDataProvider,
|
||||||
|
private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of actions for a link (url).
|
||||||
|
*
|
||||||
|
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||||
|
*/
|
||||||
|
getActions(siteIds: string[], url: string, params: any, courseId?: number):
|
||||||
|
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
return [{
|
||||||
|
action: (siteId, navCtrl?): void => {
|
||||||
|
const modal = this.domUtils.showModalLoading(),
|
||||||
|
dataId = parseInt(params.d, 10),
|
||||||
|
rId = parseInt(params.rid, 10) || false,
|
||||||
|
group = parseInt(params.group, 10) || false,
|
||||||
|
page = parseInt(params.page, 10) || false;
|
||||||
|
|
||||||
|
this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
|
||||||
|
const stateParams = {
|
||||||
|
moduleId: module.id,
|
||||||
|
module: module,
|
||||||
|
courseId: module.course
|
||||||
|
};
|
||||||
|
|
||||||
|
if (group) {
|
||||||
|
stateParams['group'] = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.mode && params.mode == 'single') {
|
||||||
|
stateParams['page'] = page || 1;
|
||||||
|
} else if (rId) {
|
||||||
|
stateParams['entryId'] = rId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.linkHelper.goInSite(navCtrl, 'AddonModDataEntryPage', stateParams, siteId);
|
||||||
|
}).finally(() => {
|
||||||
|
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||||
|
* If not defined, defaults to true.
|
||||||
|
*
|
||||||
|
* @param {string} siteId The site ID.
|
||||||
|
* @param {string} url The URL to treat.
|
||||||
|
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||||
|
*/
|
||||||
|
isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise<boolean> {
|
||||||
|
if (typeof params.d == 'undefined') {
|
||||||
|
// Id not defined. Cannot treat the URL.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!params.mode || params.mode != 'single') && typeof params.rid == 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dataProvider.isPluginEnabled(siteId);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue