At Alfresco Summit 2014 in London this week I was presented with many different use cases that various Business Partners and Community members would like to implement on Share using Aikau and I was mostly able to either point them to existing blogs or examples in 5.0.
As always though there were a few use cases that made me curious to investigate and one of those was about the ability to pick different versions of a document. We are often asked about easily re-usable pickers and had already implemented a Document Picker widget with the intention of it being configurable and extendable and I wanted to check that the use case was possible.
The rule of thumb that I recommend to anyone using Aikau is that if a widget isn't used in Share out-of-the-box then it can't be guaranteed to be production quality. The 'alfresco/form/control/DocumentPicker' is not used out-of-the-box but I am pleased to report that investigation enabled me to identify a few issues and fix them to make it much more suitable for use in 5.0 customizations. However, as a result you're going to a need a nightly build, 5.0.c Community or 5.0 Enterprise (when released) for this example to work.
There is a common requirement when using Share to be able to select a document to work with (e.g. when creating a workflow for example) and as such we need to ensure that Aikau provides widgets to satisfy this requirement. For 5.0 there was no specific feature that needed a document picker but I wanted to ensure that we had at least explored how we could implement a configurable picker.
Typically you're going to want to capture the Document nodeRef information within a form, so the simplest way to achieve this would be with the following JSON model:
services: [
'alfresco/dialogs/AlfDialogService',
'alfresco/services/DocumentService',
'alfresco/services/SiteService'
],
widgets: [
{
name: 'alfresco/forms/Form',
config: {
okButtonPublishTopic: 'FORM_CONTENTS',
widgets: [
{
name: 'alfresco/forms/controls/DocumentPicker',
config: {
label: 'Choose a document',
name: 'document'
}
}
]
}
}
]
Here were defining a form that contains a single form control for selecting documents: 'alfresco/forms/controls/DocumentPicker'. This form control works with dialogs, documents and sites so the appropriate services need to be included in the page.
This will result in the following screenshots during use:
So hopefully this provides a really easy way in which to select documents within a form. But what about extending the default implementation to make it possible to select a specific version of a document?
As always in AIkau we try to make it possible to get a long way through JSON configuration and this example is no different. However, this is by no means necessarily the most simple configuration to follow compared with other examples.
The 'alfresco/forms/controls/DocumentPicker' extends the more abstract 'alfresco/forms/controls/Picker' widget which provides the following configuration points that we're going to make use of:
Given how much we like code re-use in Aikau you probably won't be surprised to learn that since the picked documents is just a list of items we've re-used the 'alfresco/lists/AlfList' module and that the JSON model required here is just for the 'alfresco/documentlibrary/views/AlfDocumentListView' that is renders the selected documents. Since I've covered lists and views in previous blog posts [1, 2] I won't go over it again, except to say that we're defining a view where each item is represented by a row containing 3 cells that show the name, label (version) and an action for removing the item:
configForPickedItems: {
widgets: [
{
name: 'alfresco/documentlibrary/views/layouts/Row',
config: {
widgets: [
{
name: 'alfresco/documentlibrary/views/layouts/Cell',
config: {
widgets: [
{
name: 'alfresco/renderers/Property',
config: {
propertyToRender: 'name'
}
}
]
}
},
{
name: 'alfresco/documentlibrary/views/layouts/Cell',
config: {
widgets: [
{
name: 'alfresco/renderers/Property',
config: {
propertyToRender: 'label'
}
}
]
}
},
{
name: 'alfresco/documentlibrary/views/layouts/Cell',
config: {
width: '20px',
widgets: [
{
name: 'alfresco/renderers/PublishAction',
config: {
iconClass: 'delete-16',
publishTopic: 'ALF_ITEM_REMOVED',
publishPayloadType: 'CURRENT_ITEM'
}
}
]
}
}
]
}
}
]
},
It is possible that you might want to display different information within the dialog than in the form (e.g. you might choose to add more document information in the form such as a title and description or render the view as a table) in this case we use exactly the same JSON model to show the name, version and an action to remove the selected item.
This is where it gets a bit more complicated...
The idea is that we can define a starting point for our picker and then add additional exploratory panes into the dialog until we reach a point where we have items to select. For example in the default picker our starting point is the ability to select from the current user's recently visited sites, their favourite sites, all sites to which they have access, the repository root, the share files folder and their user home folder. Depending upon the selection the next pane will either contain a list of sites or a document list view of a selected location.
The change that we want to make is to add an additional exploratory pane so that selecting a document allows further selection of version rather than just selecting that document as a picked item.
To do this we currently need to copy and paste some of the default picker JSON model - this is not ideal and is something I'd like to improve in future versions. The JSON model is to large to easily fit into this blog but can be found in a JAR that you can download to try out this example.
The JAR contains the file 'alfresco/site-webscripts/docversionpicker.get.js' which is the JavaScript controller for the WebScript that defines our sample page. The key lines in this file are as follows:
Here is where start changing the default 'alfresco/pickers/Picker' JSON model to override the default configuration for the 'alfresco/pickers/DocumentListPicker' that is displayed in the second picker pane.
Here the publication data that defines picker is modified to change picked items from publishing the item data to making a request for a new picker to be added.
The 'currentPickerDepth' attribute is used to ensure that picker panes don't simply keep getting appended into the dialog. By specifying an incrementally greater depth we ensure that the version picker is added to a new pane rather than replacing the 'alfresco/pickers/DocumentListPicker'
This defines the picker that we want to add to use to select a document version. The picker is just an 'alfresco/lists/AlfList' that is configured to publish requests for an 'alfresco/services/CrudService' to retrieve version information for the document selected in the previous pane.
By changing the publish payload type to 'PROCESS' and specifying the 'processCurrentItemTokens' publish payload modifier we are able to define a URL that will include the correct nodeRef to retrieve version information for.
The 'alfresco/renderers/PublishAction' is configured to publish on the 'ALF_ITEM_SELECTED' topic to which the 'alfresco/pickers/PickedItems' widget subscribes. This is selected version appears in the picked items pane.
If you try out the example you should see the updated picker appear as shown in the following screenshots:
This is probably the most complicated example I've attempted to blog about in Aikau so far - certainly the most complicated to try to describe anyway. Hopefully though it demonstrates that we will provide a default document picker that can be easily re-used without a lot of effort and that we're trying to take a more open-ended approach towards pickers that will make it easier to both create and customize pickers through declarative JSON modelling rather than needing to write code.
I still think that this is an area that we can further improve on going forwards, but it's always challenging to provide Aikau widgets without having a specific Alfresco product feature that they're required for.
Download the example code to review or try out here.