How To implement batch actions |
Custom batch actions: allows developers to easily implement new actions on their PFItem classes.
Using the navigation, authorized users can then execute these actions on selected items.
This topic contains the following sections:
Consider the following data, a Document content-type with a reference and a validity date:
We want a feature easily increasing the validity date of multiple items.
On our Document class, we add the following code:
[PFItemBatchAction()] public void IncreaseValidityOneMonth() { this.__ValidityDate = this.__ValidityDate.AddMonths(1); this.Save(); }
When selecting rows in the navigation, the following option appears:
Clicking the new option will show a confirmation dialog, then the code executes:
The validity date has been increased on selected items and the view has been refreshed.
Five settings allow the customization of an action's display:
IconName: the name of a Font-Awesome icon.
DisplayName: used as a label for the action.
DisplayName_TranslationKey: same as DisplayName, but its value is used to find the corresponding translation in the current application's resource files (.resx).
Description: used as an explanation for the action.
Description_TranslationKey: same as Description, but its value is used to find the corresponding translation in the current application's resource files (.resx).
Example with the following code:
[PFItemBatchAction(IconName = "calendar-plus-o", DisplayName = "Increase validity", Description = "Changes the validity date to the next month.")] public void IncreaseValidityOneMonth() { this.__ValidityDate = this.__ValidityDate.AddMonths(1); this.Save(); }
The VisibilityScope setting defines which users have access to the action. Several options are available: PFItemBatchAction_Visibility.
The most specific scope allows to specify users' logins:
[PFItemBatchAction(VisibilityScope = PFItemBatchAction_Visibility.SpecificLogins, Visibility_Logins = @"nasa\narmstrong;nasa\baldrin;nasa\mcollins")] public void IncreaseValidityOneMonth() { this.__ValidityDate = this.__ValidityDate.AddMonths(1); this.Save(); }
The users not being part of the chosen scope will not see the action at all.
The default scope is "AllUsers".
Your method may receive parameters. However, only the following types are currently accepted:
Text (String)
Boolean
Numeric (int, long, decimal, float, double)
Date (DateTime, DateTimeOffset)
Note: default values are handled.
The following method contains three parameters with their default values:
[PFItemBatchAction(IconName = "calendar", DisplayName = "Change validity", Description = "Changes the validity date, increasing or decreasing it by the specified amount of months.")] public void ChangeValidity(int months = 1, Boolean notifyAuthor = false, String authorMessage = "The validity has been changed.") { this.__ValidityDate = this.__ValidityDate.AddMonths(months); this.Save(); if (notifyAuthor) this.CreatedBy.Notify(authorMessage, this.Url); }
This impacts the confirmation dialog, proposing to enter values:
Note |
---|
The confirmation dialog is always shown when parameters are found on the method. On another side, without parameters, the confirmation dialog can be disabled by changing the value of RequireConfirmation which is True by default. |
If a String parameter requires to be multi-line, you can use the ParamMultiLine attribute.
[PFItemBatchAction(IconName = "calendar", DisplayName = "Change validity", Description = "Changes the validity date, increasing or decreasing it by the specified amount of months.")] public void ChangeValidity(int months = 1, Boolean notifyAuthor = false, [ParamMultiLine]String authorMessage = "The validity has been changed.") { this.__ValidityDate = this.__ValidityDate.AddMonths(months); this.Save(); if (notifyAuthor) this.CreatedBy.Notify(authorMessage, this.Url); }
You've probably noticed that the parameters' names are automatically adapted from CamelCase.
Alternatively, a custom label can be set using the ParamTitle attribute.
[PFItemBatchAction(IconName = "calendar", DisplayName = "Change validity", Description = "Changes the validity date, increasing or decreasing it by the specified amount of months.")] public void ChangeValidity([ParamTitle("Number of months (can be negative or positive)")]int months = 1, Boolean notifyAuthor = false, [ParamMultiLine]String authorMessage = "The validity has been changed.") { this.__ValidityDate = this.__ValidityDate.AddMonths(months); this.Save(); if (notifyAuthor) this.CreatedBy.Notify(authorMessage, this.Url); }
You can also use the application's translations with the ParamTitleTranslation attribute; its translation key is used to find the corresponding translation in the resource files (.resx).
If you want to check the configuration before the execution, you can set a validation method.
That method is still defined on the PFItem class and must have the same parameters (name and type) as the action method.
The validation is completely processed before the main execution. So if the method throws an exception (a ValidationExcetion is recommended), the execution is not started.
[PFItemBatchAction(DisplayName = "Increase validity", ValidationMethodName = "IncreaseValidity_Validation")] public void IncreaseValidity(int month = 1) { this.__ValidityDate = this.__ValidityDate.AddMonths(month); this.Save(); } public void IncreaseValidity_Validation(int month = 1) { if (this.__ValidityDate.AddMonths(month) < DateTime.Now) throw new ValidationException("You cannot set the validity in the past."); }
The month value has been set to -5. Here is the result, with the details section opened:
The execution of an action consists of several steps:
Items selection (see below)
Action choice among those visible for the current user
Confirmation dialog / action setup: if RequireConfirmation is set to True or if parameters are available, a dialog is shown before launch.
Validation: if specified, the validation method is executed on selected items. If it fails, the main execution is not started.
Execution: the method is executed on each selected item. Meanwhile, a progression is shown and details provided progressively. See below for execution options.
Conclusion: success/fail count are available along with details results. The view is also refreshed. The details of each execution can be enhanced (see below).
Items can be selected by clicking the corresponding rows in the table.
The Shift+Click shortcut can be used to (un)select multiple rows between the clicked one and the last clicked one.
Finally, the head row contains a checkbox (un)selecting all displayed rows.
Multiple information and options are available during the execution.
Indicates that settings have been defined. Hover this icon to display their values in a tooltip.
The name of the action currently executed.
The progression showing successful executions in green and the failed ones in red.
This button shows or hides the details, containing executions output and errors.
This button will pause or resume the execution.
This button aborts the execution (no confirmation dialog).
Your method may return a String value. If the execution succeeds, this will be shown in the details section.
[PFItemBatchAction(DisplayName = "Increase validity", ValidationMethodName = "IncreaseValidity_Validation")] public String IncreaseValidity(int month = 1) { this.__ValidityDate = this.__ValidityDate.AddMonths(month); this.Save(); return String.Format("New validity date: {0}.", this.__ValidityDate.ToString("yyyy\MM\dd")); }
Here are some last indications to note about the batch actions:
There is no impersonation on the executed code. If the user has no permission to update the item while your code tries to save it, it will fail.
This feature is not available in multi-content views.
If relevant, consider adding a PFItemEvent in the PFItem.Events collection.
Please note this feature is not only intended for item changes. This kind of action could also be useful:
[PFItemBatchAction(DisplayName = "Notify about validity", Description = "Notify someone about an approaching validity.")] public void Notify(String emailAddress) { String message = String.Format("The validity of the document <a href='{0}'>{1}</a> is approaching.", this.AbsoluteUrl, this.Reference); this.Site.SendMail(this.Reference, message, emailAddress, useHtml: true); }