How to customise action buttons - softwareloop/alfresco-inboxes GitHub Wiki
The previous page left us with a customised view for owd:dossier
objects,
but with the buttons still performing the default stub action.
This page will show how to connect the buttons to actions that actually change a dossier's status. Clicking on the "Mark active" button will change the status to Active, clicking on "Mark retired" will change the status to Retired. Simple as that.
To implement the status change, we're going to use a CMIS update call. We're also going to see why this approach and the possible alternatives.
Buttons are primarily user interface objects so a good place to start studying
them is the html template that generates them. Open the Item.html
file located
at src/main/amp/web/js/softwareloop/inboxes/templates/
in the source
distribution. The relevant lines are shown here:
<button class="inboxes-item-button inboxes-item-button-approve"
data-dojo-attach-event="click:approveAction">${approveLabel}
</button>
<button class="inboxes-item-button inboxes-item-button-reject"
data-dojo-attach-event="click:rejectAction">${rejectLabel}
</button>
The data-dojo-attach-event
attribute is the one involved in event handling. Its
value click:approveAction
provides the specific details of what event to attach
to (click) and the function name to be called (approveAction).
The attribute and the whole mechanism are specific to Dojo/Aikau. There is some
automatic processing performed by the framework, going on behind the scenes,
that translates the custom attribute in regular event listeners attached to the
button's node. The details are explained in
Dojo's documentation.
Here we're only interested in the result of this html fragment: when the
"Mark active" (or "Mark retired") button is pressed, the event handler function
approveAction()
(or rejectAction()
) is invoked on the component.
The component is the Dossier.js
we discussed in the
previous page.
The two event handler functions are shown below:
approveAction: function () {
this.updateStatus("Active");
},
rejectAction: function () {
this.updateStatus("Retired");
},
The functions simply delegate the actual change in status to updateStatus()
,
passing the desired status as an argument.
##CMIS update invocation
updateStatus()
runs a webscript on Alfresco's repository with Share acting as a
proxy between the browser and the repository. At the end of the update, it
triggers a page reload.
updateStatus: function (status) {
var url = lang.replace(
"{proxyUri}cmis/s/workspace:SpacesStore/i/{entryId}",
{
proxyUri: Alfresco.constants.PROXY_URI,
entryId: this.entry.id
}
);
var dossierStatus = this.entry.attributes["owd:dossierStatus"];
dossierStatus.values[0] = status;
var updateAttributes = {};
updateAttributes["owd:dossierStatus"] = dossierStatus;
cmis.updateEntry(url, updateAttributes, function() {
location.reload(false);
});
}
The webscript responds to HTTP PUT invocations and takes an XML atom entry as
its input, much like a CMIS query returns XML atom entries in its output. The
details of the protocol are handled in the utility module
"softwareloop/cmis/cmis"; Dossier.js only needs to invoke cmis.updateEntry()
.
In this code, only the owd:status
attribute is updated. All other attributes are
not transmitted to the CMIS update webscript and consequently are left
unmodified.
CMIS is a flexible protocol that does the job in our example. It is also natively supported by Alfresco's repository, which allowed us to focus on Share only, without writing any custom code for the repository. However CMIS has limitations of which you must to be aware in case you deal with other scenarios.
First, running a CMIS update requires the logged in user to have write permissions on the object. This may not always be the case. Sometimes in a workflow, a user can perform an approve/reject action but does not have write access to all the attributes of the object.
Second, CMIS supports CRUD on single objects but cannot perform a complex transaction on multiple related object.
Third, CMIS is not aware of and cannot operate directly on Activiti.
When CMIS is not sufficient, the alternative is to write a custom webscript on Alfresco's repository to perform the required operation. Custom webscripts benefit from transactions, can operate on multiple objects, can apply permissions according to any logic and have access to a wide range of server-side APIs.
In many Alfresco projects, the requirements for UI customisations are as strong as for content model customisations. Sometimes users want the UI to expose more information, sometimes less, sometimes more or less depending on the task at hand.
Alfresco-inboxes makes customisations of presentation and actions very simple and accessible to most developers as hopefully this page has demonstrated.