We have developed many Alfresco solutions over the years and a best practice consideration on projects has been to use a Repo Action to bundle behaviour for changes to a document or folder into a Repo Action so that it could be re-used. I therefore assumed that the ADF framework would have a Service available to call a Repo action. While the ADF js-api module has service apis for most alfresco services, for some reason there is no service api available for the actionsApi. We therefore decided to call the actions api webscript directly.
The solution works as follows:
- Define an Angular Service to include Service calls that your ADF application will make to manage documents.
- Create methods in your Service that will call the actions api using the JS API Service and webscript API.
- The Actions Api can be called by a webscript. It has an execute method which takes the url path for the action. Paramaters for the action call, such as the name of the action and any action specific parameters are passed into the webscript in the Body.
- We then used an event emitter from our Datatable action to emit the action request to the containing component, which in turn calls the angular service method to call the webscript.
Defining the Service
Define a service in your project and inject the js-api into the service. This uses the js service webscript object to call the Repo action using a POST, passing in the required parameters in the body.
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApi } from '@alfresco/js-api'; @Injectable({ providedIn: 'root' }) export class MediaMonitoringService { // constructor injects the js api service constructor(private apiService: AlfrescoApiService){} public rejectSubmission(mediaItem: MediaItem): Promise<void | MediaItem>{ //Example Repo Action body params { "actionDefinitionId": "add-features", "targetId": mediaItem.nodeRef.substring(24), "params": { "aspect-name": "cm:versionable" } } // my body class. let actionBodyExec = { "actionDefinitionId": "action.mediamonitoring.moveToRejected", // id of the bean you have defined for the Repo Action "targetId": mediaItem.nodeRef.substring(24), // Identifies the node the action will work on. Note: needed to strip workspace://SpaceStore from the nodeRef "params": { "reason": mediaItem.mediaRejectionReason // a custom param defined in my Repo Action } } return this.runRepoAction(actionBodyExec, mediaItem); } private runRepoAction(actionParams: any, mediaItem: MediaItem): Promise<void | MediaItem>{ console.log('Call Actions API'); return this.apiService.getInstance().webScript.executeWebScript( 'POST', 'action-executions', null, 'alfresco', 'api/-default-/public/alfresco/versions/1', actionParams ).then((data) => { console.log('actionExec API called successfully. Returned data: '); console.log(data); return mediaItem; }, function(error) { console.error(error); }); } }
Custom Action Definition
The Custom Action that was called was created as a Java Repo Action.
The bean definition for this action is shown below:
<bean id=”action.mediamonitoring.moveToRejected”
class=”org.seeksystem.mediamonitoring.action.MoveToRejectedRepoAction”
parent=”action-executer”>
<property name=”nodeService” ref=”nodeService” />
<property name=”searchService” ref=”searchService” />
<property name=”namespaceService” ref=”NamespaceService” />
<property name=”siteService” ref=”SiteService” />
</bean>
The expected params for the Repo Action are defined in the java class for the bean: ie
@Override
protected void addParameterDefinitions(List<ParameterDefinition> listParameterDefinition) {
ParameterDefinition reason = new ParameterDefinitionImpl(REASON, DataTypeDefinition.TEXT, true, “Reason”, false);
listParameterDefinition.add(reason);
}
Calling the Service from my Smart Component
The smart component receives an event when a user selects an action from a Datatable and calls the service method:
rejectSubmission(event: MediaItem){ console.log("Reject event called"); this.mediaMonitoringService.rejectSubmission(event).then((mediaItem: MediaItem) => { // Refresh all the submissions for this site this.mediaMonitoringService .getSubmissions(this.mediaSearchArgs) .then((rows: any) => { this.data = rows; }); }); }
Conclusion
Using this method allows you to call Alfresco Repo Actions while developing ADF applications. This is powerful when you want to bundle business logic for a node in the Repository into a single call. Hopefully at some time in the future the ADF JS API Service will be extended to include the actionsAPI.