Re-using and Customizing Aikau Pickers

cancel
Showing results for 
Search instead for 
Did you mean: 

Re-using and Customizing Aikau Pickers

ddraper
Intermediate II
1 12 4,765

Introduction

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.

Picking Documents

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:

Document Picker in Form 

Document Picker Dialog Opened with Document Selected Document Picker showing the selected document after closing the dialog

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?

Customizing the Picker

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:

    • configForPickedItems - this is the JSON model that declares how you see picked items when the dialog is not displayed
    • configForPicker.widgetsForPickedItems - this is the JSON model the declares how you see picked items within the picker dialog
    • configForPicker.widgetsForRootPicker - this is the JSON model that defines how the dialog picker is constructed.

configForPickedItems

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'
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ]
},

widgetsForPickedItems

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.

widgetsForRootPicker

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:

Line 154:

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.

Lines 157 - 160:

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.

Line 161:

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'

Line 162:

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.

Line 201:

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.

Example In Action

If you try out the example you should see the updated picker appear as shown in the following screenshots:

The initially displayed dialog with just a single root option

Having selected the Repository...

Having selected a folder containing the target document

Having selected the target document you see the available versions

Having selected the required version

Having confirmed selection of the required version

Summary

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.

12 Comments
blog_commenter
Active Member
[…] one or more items from a list. This widget re-uses much of the same code implemented for the more complex form pickers (e.g. for selecting documents, folders or properties) but distils the underlying JSON model into a […]
blog_commenter
Active Member
Hi,



How to select the people(user)? i tried to implement using DocumentPicker by customising the ,

api/people. but i couldn't get it done.

Can you please guide me?
ddraper
Intermediate II
@Ashwani - the DocumentPicker as it's name suggests is a specialist picker for selecting documents...  take a look at this post for how to create a picker for almost anything: https://www.alfresco.com/blogs/developer/2014/10/31/aikau-simple-picker-updates/ (you just need to have a REST API to call).
blog_commenter
Active Member
Hi Dave,

Do you have any example JavaScript that actions the OK button? I need to get an array of the selected nodeRefs, but I can't seem to find anything online to do it.
ddraper
Intermediate II
@Sarah - everything works over a publication/subscription model, so the selected items would be published on a topic of your choosing and then you can have a service subscribe to that topic and decide what the resulting action should be.
blog_commenter
Active Member
I have been looking for a simple way to manually populate an AlfList from an API call that returns a JSON document that is not driven by alfresco.    I can use Dojo to make the call and process the returned JSOn, but i am having trouble getting the list to respond to the data.  I have tried setting the loadDataPublishTopic property of the AlfList to a custom topic and publishing a payload to that topic.  I configured the AlfList in many way but this is where I am at now:



                      name: 'alfresco/lists/AlfList',

                      config: {

                        loadDataPublishTopic: 'MY_API_DATA_READY',

                        publishPayloadModifiers: [ 'processCurrentItemTokens' ],

                        publishPayloadType: 'PROCESS',

                        itemsProperty: 'items',

                        publishPayload: {

                          items: '{items}',

                        },



                       .........



                      var items = [];

                       var item = {'description': statements[j].description, 'name': Id};

                       items.push(item);

                       this.alfPublish('MY_API_DATA_READY', data);





Can you help by providing an example on how to do this as I have search and cant seem to find an example.  Alternatively a simple statically configure list with data would help to demonstrate the concept as well.
blog_commenter
Active Member
Any way to show an example of how to populate the data for an AlfList widget from data retrieved from a non Alfresco API call?  I have a need to do this and I cant seem to get this to work no matter how I try.  The following code snippets demonstrate my latest current failed attempt.



                   .......    



                  name: 'alfresco/lists/AlfList',

                      config: {

                        loadDataPublishTopic: 'MY_API_DATA_READY',

                        publishPayloadModifiers: [ 'processCurrentItemTokens' ],

                        publishPayloadType: 'PROCESS',

                        publishPayload: {

                          items: '{items}',

                        },



                   .......    



              this.serviceXhr({url : 'http://10.72.71.34/getStatements',

                               method: 'GET',

                               headers: { 'X-Requested-With': null },

                               successCallback: this.XHRonSuccessCallbackFrameworkApi,

                               callbackScope: this});    



                   .......    



                  var items = [];

                  item = {'description': statement.description, 'name': Id};

           items.push(item);



                   .......    



                var data = {'items': items}; 

                this.alfPublish('MY_API_DATA_READY', data);
ddraper
Intermediate II
AIkau has been written to work with Alfresco so this is something that I've never really attempted before. The first thing that jumps to mind is that you might be hitting issues with CSRF filtering but I'm not sure.
ddraper
Intermediate II
I don't have any examples on how to do this because it's not something that Aikau was intended to do and so isn't something I've ever tried.
blog_commenter
Active Member
Dave,



I understand that its a reasonable requirement to work within the confines of the Alfresco repo for data requests.  I however wanted to use Alfresco Share (thus my foray into Aikau) as an integration point for content related applications that have a need to leverage data and APIs outside of Alfresco.  Share takes care of the many non functional requirement associated with this task such as access/auth/deployment etc.



I am able to to access the external API data from my aikau widget and manipulate it as I see fit so I cont believe I have any CSRF filtering going on.  The issue for me is not being able to have the ability to set that payload for the AlfList widget outside of its base context even though I can put the retrieved API data into the same format expected by the AlfList widget.  Once I have data in the widget I have no issue rendering it as I see fit.



I hope this explanation helps you understand the issue and the reason it has come about.  I hope that this is a feature that will be in future release of Aikau.
ddraper
Intermediate II
Mark,



I'll be perfectly honest here... unless there is a compelling reason for a feature to be added (i.e. something that is required by a feature of the product) then this isn't something that is likely to be added given the current backlog of work on the Aikau project.  If I had examples of doing what you require then I would quite happily share them, but I don't and therefore can't. I understand that it is a perfectly reasonable requirement for your project, however given my limited time available and the priority of my other assignments this isn't something that I currently am able to look into.



That isn't to say that what you require is not achievable, just that at the present time I will not be able to assist you with it.
afielden
Active Member II

Link is dead. Do you have an alternative link, showing how to use the document picker?