Gavinc Work

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Needs to be Reviewed


Introduction


This page contains details of my 1.4 tasks from a planning and scoping point of view. The initial design for the tasks will also be placed here.


AJAX Framework


In the next few releases we will be adding AJAX capabilities to the UI and therefore need a framework to support our custom JSF components. Linton has identified the initial set of components below, which this framework obviously must support.


  • Node Information Popup
  • Picker (space/category)
  • Live Search
  • Breadcrumb
  • In place editing

Analysis


My previous investigation into AJAX frameworks recommended DWR and dojo. Since then DWR has moved on a couple of versions and another JSF specific framework, Shale, has come to light.

Once configured, DWR is very simple to use on the client side due to its encapsulation of the remote URL and parameters, you are essentially just making a method call. Contrary to my previous belief it appears that an integration into the JSF lifecycle is not required after all. As long as the FacesContext has been setup a simple method binding expression is all that is required for read and write operations. This is exactly what DWR provides and as such would be sufficient for our current needs, apart from one thing, portal support. All our components must run in a portal environment, DWR relies on a filter to setup the FacesContext, filters are not supported in portal servers yet! Unfortunately, this rules out the use of DWR.

Shale, on the other hand is designed to provide AJAX capabilities to JSF components and as such implicitly supports components running running in the servlet and portlet environments. It's also used by Sun's recent release of AJAX enabled JSF components. However, after a little investigation it was found that it makes some presumptions that do not fit with our environment. It's currently harcoded to work with JSF URLs using the .faces suffix as opposed to the /faces prefix we use. Secondly, it looks for the FacesServlet by class name, as we currently extend the FacesServlet it's not found in web.xml and produces a NullPointerException. These, therefore, also rule out the use of Shale.

As a result of the above findings a custom implementation will be developed to handle our AJAX requirements.


Implementation Detail


Details of the implementation of the AJAX framework can be found here.


Estimate


3 days


Investigate SEAM


Gavin King has recently released the SEAM framework which, as one of it's features, ties together JSF and EJB3. A days worth of investigation into the new framework will familiarise us with it's features, particulary it's handling of AJAX - 1 day.

My investigation notes can be found here.


Business Process and Task Management


The 1.4 release is introducing several advanced workflow features. The web client therefore needs to provide support for the following:


  • Starting a worflow on a content item
  • Managing the work items as the workflow progresses
  • Providing access to work items and completed work items via the new dashboard

Ad-hoc tasks will be managed separately (workflow items will be controlled by the jBPM server), this may even take the form of a customer contribution.


Analysis


  • Work item and completed work item dashlets - 4 days (AWC-811)
  • Work item dialog - 2 weeks (AWC-812)
    • Association editor needs to handle groups (if it doesn't now)
    • Marshalling of Node between jBPM and PropertySheet
    • Componentising the work item 'package' (in form of several JSP snippets)
    • Filter user selection by the current space
    • Workflow details component
  • Start Workflow Wizard - 3 days (AWC-813)
    • Re-use work item dialog JSP for step 2
  • Track Workflow Dialog - 4 days (AWC-814)
  • Incorporate advanced workflow into Create Rule and Run Action Wizards - 2 days (AWC-815)

NOTE: Some of these tasks are dependent on tasks in the Dialog and Wizard Framework section below.



If we are going to implement the ad-hoc tasks the following will be required (AWC-578):


  • Create Task Space dialog - 1 day
  • Implement tasks.jsp (shows list of tasks in the task list) - 1 day
  • Create Task dialog - 2 days
  • Create Task List for a node (similar to create discussion) - 1 day

Convert Remaining Wizards


  • New User Wizard (AWC-676) - 1 day
  • Invite User Wizard (AWC-677) - 1 day

Convert Delete Dialogs


  • File/Folder delete dialogs - 1 day (AWC-803)
  • Forum area delete dialogs - 1 day (AWC-803)

Dialog and Wizard Framework Improvements


  • Allow multi level dialogs/wizards - 1 day (AWC-672)
  • Allow the same JSP snippet to be used in a dialog and a wizard - 1 day (AWC-805)
  • Add support for displaying actions in the title area for the dialog (BPM requirement) - 1 day (AWC-806)
  • Add support for displaying extra dialog buttons, including 'Create And Create Another' button (BPM requirement) - 2 days (AWC-807)

Implementation Detail


Multi-level Dialogs and Wizards

There are 2 types of dialogs, simple dialogs and configured dialogs. Simple dialogs are normal JSPs but are added to the view stack before display. Configured dialogs use the dialog container JSP and have state associated with them. Wizards are basically multi-page dialogs, with their own container JSP and additional state. A DialogManager and WizardManager handle configured dialogs and wizards, respectively.

Any number of simple dialogs can be opened as there is no state associated with them. Configured dialogs and wizards however require their state to be saved before opening another one, they are currently therefore the 'end of the line'.

The DialogManager and the WizardManager will be changed to only store a single variable, this object will encapsulate all the state for the current dialog or wizard. The following objects will hold the dialog and wizard state.

public class DialogState
{
   private DialogConfig config;
   private IDialogBean dialog;
   private Map<String, String> params;
   ...
   getters and setters
   ...
}

public class WizardState
{
   private WizardConfig config;
   private IWizardBean wizard;
   private Map<String, String> params;
   private int stepNumber;
   private String stepName;
   private List<StepConfig> steps;
   private PageConfig page;
   ...
   getters and setters
   ...
}

The State objects above will be created by the Dialog/WizardManager when their setCurrentDialog/Wizard method is called. The following methods will also be added to get access to the State object and to later restore the state.

public Dialog/WizardState getState();
public void restoreState(Dialog/WizardState state);

The AlfrescoNavigationHandler will use the methods above to save and restore the state at the appropriate time. When a new dialog or wizard is opened the State object of the current dialog or wizard will be retrieved from the Manager and stored in the view stack (the view stack will be changed from storing String's to Object's). If the stack is empty or the current dialog is a simple dialog the viewId will be stored as it is today.

Pseduo code for AlfrescoNavigationHandler.handleDialog/WizardOpen() is shown below.

if stack is empty or top of stack is String
   push current viewId to stack
else
   get dialog/wizard state from Manager
   push state object to stack

At some point a nested dialog or wizard will be closed. In this scenario the view stack will be examined, if the object at the top of the stack is a viewId it will simply be navigated to. If the object at the top of the stack is a State object, the restoreState() method will be called on the appropriate Manager, the appropriate container JSP will be retrieved and navigated to.

Pseduo code for AlfrescoNavigationHandler.handleDialogOrWizardClose() is shown below.

if stack is not empty
   if top of stack is String (a viewId)
      if outcome is overridden
         clear stack
         navigate to override
      else
         navigate to viewId
   if top of stack is DialogState
      if outcome is overridden
         clear stack
         navigate to override
      else
         DialogManager.restoreState()
         navigate to dialog container
   if top of stack is WizardState
      if outcome is overridden
         clear stack
         navigate to override
      else
         WizardManager.restoreState()
         navigate to wizard container

Cross Container Identifier

The dialog and wizard framework introduced the possibility to share JSP snippets across multiple dialogs or wizards. The problem is that the page can only be used in one type of container i.e. if the page uses #{DialogManager.bean.property} it can only be used in dialogs and not in wizards.

JSF allows custom variable resolvers to be plugged in. These determine the object to use for the first part of a JSF binding expression. For example in #{DialogManager.bean}, DialogManager gets resolved to the managed bean named DialogManager. We already use a custom variable resolver as our integration into Spring, it's this that allows us to inject repository services into our managed beans.

org.alfresco.web.app.AlfrescoVariableResolver will extend the existing Spring variable resolver and use the pseduo code shown below.

if variable name is 'Container'
   if top of view stack is DialogState
      return FacesHelper.getManagedBean('DialogManager')
   if top of view stack is WizardState
      return FacesHelper.getManagedBean('WizardManager')
else
   delegate to Spring variable resolver

For performance reasons it's best to use the direct reference where possible but if there are JSP snippets that have to be in a dialog AND a wizard, the #{Container.bean.property} syntax can be used.

Additional Buttons

The dialog container JSP currently shows an 'OK' and a 'Cancel' button. Some of the Workflow features are going to require extra buttons on dialog's i.e. managing workflow tasks will require buttons for approving and rejecting.

A dialogButtons self rendering JSF component will be implemented and placed on the dialog container page. This component will automatically generate the components present today (as shown below).

<h:commandButton id='finish-button' styleClass='wizardButton'
                 value='#{DialogManager.finishButtonLabel}'
                 action='#{DialogManager.finish}'
                 disabled='#{DialogManager.finishButtonDisabled}' />
<h:commandButton id='cancel-button' styleClass='wizardButton'
                 value='#{DialogManager.cancelButtonLabel}'
                 action='#{DialogManager.cancel}' />

The component will also render any additional buttons configured in the dialog configuration file and those defined at runtime by the current dialog.

The dialogButtons component will replace the buttons above and will appear in the dialog container JSP as below.

<r:dialogButtons id='dialog-buttons' buttonStyleClass='wizardButton' />

The component will retrieve the list of buttons to generate by calling a new getAdditionalButtons() method on the DialogManager as shown below.

public List<DialogButtonConfig> getAdditionalButtons();

DialogButtonConfig will be an inner class of DialogsConfigElement and be driven from the button element in the dialogs configuration file. A typical example is shown below.

<dialogs>
   ...
   <dialog name='createTask' ....>
      <button id='ok-and-add-button'
              label='Create and Create Another'
              label-id='create-another-button'
              action='#{DialogManager.createAnother}'
              disabled='#{DialogManager.createAnotherDisabled}'
              onclick='javascript:method()' />
   </dialog>
   ...
</dialogs>

DialogManager.getAdditionalButtons() will also call a new getAdditionalButtons() method on the IDialogBean interface. This will allow dialogs to define extra buttons to display at runtime. This will be particulary useful for the Manage Workflow Task Dialog as the buttons to display could be different for each execution/task, as it is driven by the state of the underlying workflow. IDialogBean.getAdditionalButtons() will also return a list of DialogButtonConfig objects, meaning that DialogManager can combine the lists to return to the dialogButtons component.

For completeness the DialogButtonConfig class is shown below.

public class DialogButtonConfig
{
   private String id;
   private String label;
   private String labelId;
   private String action;
   private String disabled;
   private String onclick;
   ...
   constructor and getters
   ...
}

Error Handling


  • Upgrade MyFaces to 1.1.3 - 0.5 day (AWC-808)
  • Remove extension of FacesServlet - 1 day (AWC-808)
  • Handle errors in jsp:include'd pages - 0.5 day (AWC-808)

Customisation and Configuration Improvements


  • Configurable date ranges - 0.25 day
  • Configurable text field length - 0.25 day
  • Textarea Component Generator - 0.5 day
  • More testing and fixing of dispatching - 2 days
    • If a customer has a custom space type for their home space, will it dispatch correctly from the My Home link?
    • Changing the view does not dispatch correctly (AWC-774)
    • Does returning from Add Content dialog dispatch correctly (uses the global 'browse' outcome)?



These tasks are all captured under AWC-809


Property Sheet Enhancements


The workitem dialogs in the wireframes shows the general properties and the user properties being separated by a heading. The PropertySheet component therefore needs a way to be configured to display separators. The separator could take many forms i.e. it could be a hr element, a div representing a heading or indeed any HTML.


Implementation Detail

Attachments

    Outcomes