An Open Digital Asset Management Standard

We all use technology standards everyday.

We hop into our cars and play music from our mobile phones through the car speakers.  It doesn’t matter who the device or car manufacturer is, as long as they both add support for the A2DP Bluetooth profile.

We connect our set top boxes to our televisions with a single HDMI cable, again regardless of manufacturers.

We send emails to people in various organizations that use different email server vendors, but we don’t need to worry about how our server communicates with theirs, they just both support SMTP.

Specific to Digital Asset Management (DAM), we add captions and keywords to images in common desktop applications and most of us don’t have to think about the fact that they’re being embedded using IPTC.

The examples are numerous, and we usually take the end result for granted, but those standards take significant time and effort to properly define the problems and come up with solutions that satisfy everyone participating, who sometimes have competing interests.

Disconnected silos of media are widespread in the DAM space.  A large organization can have multiple, even tens of DAM systems, usually for different departments.  A common thread in the industry is that we need to make it easier to integrate these systems with each other and with the rest of the enterprise so that the entire lifecycle of content can be managed in an efficient manner.

What might those integrations look like?

Metadata. Say a web content management system needs to display an image and a crucial piece of metadata, its credit line for example.  There might be several web pages or even separate CMSes using the same image.  If that credit line needs to change the CMS users shouldn’t have to have to update it in every spot it’s used.  An integration could be developed to pull the image and data from a central DAM by building a connector between the two systems, but what if the DAM is switched out for another vendor, or there are multiple DAMs from different vendors?

Renditions. Lower quality renditions of rich media files (called proxies in the video world) are often used instead of the much larger original source files for various scenarios.  Let’s say we have a collaborative review mobile app which can be configured to point to a DAM system in order to use or request these renditions for playback or display.  For the app to support DAMs from multiple vendors a connector must be developed for each, assuming the vendor even has a relevant API for the task in the first place.

Rights. Omni-channel customer experience management solutions (Mmmm, words, so buzzy) might need to assemble content and obtain rights information from a DAM before making a campaign live.  There again: a different integration needed for each DAM vendor.

Interoperability standards are an obvious answer to these problems.

If we, the DAM ecosystem, build these critical system to system connectors using open standards that many vendors have agreed upon and have ultimately implemented we can be assured we’ll only have to do it once and will avoid vendor lock-in.

If you haven’t heard, work was started on just such a standard for the DAM industry, CMIS4DAM, designed to work alongside the existing Content Management Interoperability Services standard.  It held great promise as an answer to the call that seemed to be coming from many DAM analysts, consultants, vendors, and customers with initial participation from a range of companies and individuals full of vigor to help shape what was to come.

The OASIS technical committee (TC) charter was put forth, uses cases and deliverables were defined, and work started on the specification itself.

Unfortunately the participation waned throughout that process and the monthly meetings now consistently involve only a few attendees.

Without commitment from more individuals, and perhaps more importantly vendors, OASIS will have to shut down the CMIS4DAM TC.

Consider this a call for help.

If you were on the TC and have stopped attending, was there a specific reason?

If you’re a DAM vendor interested in improving the DAM technology ecosystem would you consider joining the committee to help develop the specification?

Is there a standard other than CMIS4DAM you feel would be a better match for the DAM community?

Perhaps most importantly, if you’re a purchaser of a DAM system and have interest in leveraging these concepts in your implementation, contact your DAM vendor and encourage them participate.  Your demands (hopefully) drive their roadmap, let’s make sure an open interoperability standard is on it!

Please consider giving your feedback in this 30 second poll.

Introducing the Aikau Sandpit

Aikau development continues rapidly with new releases each week. One of the challenges we have is in providing suitable education for getting up-to-speed with what widgets are currently available. We have the JSDoc and the online tutorial but these require you to either have or create a client or work within Alfresco Share. We had various feedback that it would be useful to have a “kitchen-sink” style application to show-case all the widgets but have found that trying to create a single application to demonstrate every widget is quite a sizable challenge. Instead we have created a “sandpit” application to demonstrate widgets that allows dynamic customization of the example configuration provided. This application is online now and can be found by following this link.

When you visit the application you’ll find an index page that allows you to search for and navigate to particular widget examples. Each page will contain one or more snippets of Aikau JSON model with a preview of what the model will render. You can edit the JSON model and update the preview to experiment with each widget. Every page has tabs for debug logging, mock XHR logging and the JSDoc for the primary widget being shown.

Sandpit_Screenshot_2

At the moment there aren’t very many example pages but we will be adding new examples for each new widget we add from now on. We’re also hoping that the Alfresco Community will get involved and contribute examples that they find useful. Contributing can be done via GitHub pull requests and instructions can be found here.

The Sandpit application will be updated each Tuesday as part of the Aikau release process. As always we’re grateful for any feedback or contributions.

Can one size fit all?

By Christine Thompson

A member of one of my Scrum teams recently pointed out that we only tend to use a limited range of numbers on our planning poker cards. Most of our stories get sized in the 3 / 5 / 8 range and he questioned why we weren’t using the full range of sizes for our stories. Here is my take on the situation.

Here is our sprint, that we need to populate with user stories:

Sprint

Within the Scrum team in question, the stories being written for the work we need to complete are currently being pitched very well. They are small enough to be clear what needs doing but not so small that they’re too granular. Within the team, we’re starting to write stories that are generally of a similar size. This suggests that we’re breaking them down correctly, to a consistent and appropriate level. Our sprints look like this, populated with a number of uniformly sized stories:

EvenSprint

The alternative would be to aim for stories within a not too narrow range – maybe 1 to 13 points. This allows you to populate a sprint with small, medium and large tasks. This is a good approach for the circumstances where you need to include a ‘large’ story, so the sprint must also contain ‘small’ stories too, to fill the gaps:

UnevenSprint

The one thing we want to avoid is populating a sprint with one, big story. Just bringing in one or two large stories carries a lot of risk, as in the last example below. If that story gets blocked, the whole sprint grinds to a halt:

MonolithSprint

So what are the benefits of sizing stories consistently? There was one occasion recently when we sized something at 13 points. The Lead Developer took it away and broke it down because it was considered too big to be properly understood. This shows that we’re trying for consistency and the sizing highlights when we have not achieved it. Anything above 8 points may be too large and complex to be sized accurately. Breaking it down ensures that the story is well understood at the appropriate level.

The important thing to note here is that we’re not limiting our choice of story points to a fixed set but instead we’re writing our user stories to a defined size.

Let me give you a couple of examples from another team. When a new PO joined the team, he was writing stories at a very granular level. The teams were giving them 0.5 or 1 point and asking him to combine them to make them bigger, as they felt too small to be worked on individually. Conversely, when he asked for a big, vague story about a database-driven feedback system, the team sized it at 100 points, showing it would need to be very well specified and broken down for us even to attempt to work on it. Here our use of the extreme planning poker cards showed a problem that needed addressing.

The exercise of sizing confirms we have pitched the story correctly and warns us when that is not the case so that action can be taken. It’s unlikely that user stories are always going to be sized equally, and you would start to wonder whether the team were even thinking properly about them if they were. However, the correct preparation of stories for sizing, and the discussions to confirm our understanding of them, give us the best possible indicator that we understand the work we’re doing and can successfully achieve the sprint.

 

Alfresco 5.1 Platform Update & Roadmap – Alfresco Day Boston, November 2015

As a quick follow up on Ole‘s last post on the Alfresco 5.1 Platform changes, I wanted to share with you the Alfresco Platform Update & Roadmap presentation I gave last week at the Boston’s Alfresco Day Developer Track.

It puts together the Developer Platform specific updates with all the other efforts we have done this year on the Platform side of Alfresco, including technical details of the Extreme Scalability / 1 Billion document benchmark and of the Upgrade Task Force (our investment toward simple upgrade of Alfresco instances) and a glance on Platform improvements in Alfresco 5.1 (e.g. Solr4 sharding, hint hint).

Check the slides below for all the details and as usual your feedback is welcome!

 

Changes in the Developer Platform

Since our last major Alfresco One release we’ve been working hard to improve and shift gears on the developer platform. Over the coming months, Gab and I will be travelling around to the different Alfresco Days where we will be presenting on this topic. You can view our slides here.

You may have heard of Release Agility and Share Separation, which is just one of the things we’ve invested in since.

With Alfresco One 5.1 on its way, we wanted to share some of changes in the Alfresco Platform and explain how they affect you.

Share Separation
We covered this in-depth a while back, but the overall goal here is to split Share from the Repository. This way we can be more agile and release Share separately from the Repository and we provide compatibility between the different versions. This way you can upgrade the repository and leave Share as it is, or the other way around, which ultimately makes upgrading easier and more flexible

Upgrade Task Force
To make updates easier we’re working on a tool called “Update Assistant”. This tool will streamline and automate the process of installing hotfixes and service packs. It takes your customizations into account and only touches on the resources that has actually been changed for the update.

This tool will help you keep up to date on the latest service packs and hotfixes with ease. The tool will be available early next year and will support service packs and hotfixes for both the 5.0 and 5.1 code base.

Supported Extension Points
Alfresco is designed with customization in mind, but we have never defined a clear set of supported extension points, and we have not been doing a good job at hardening those extension points and APIs.

In the beginning of the year we did a big round of research where we talked to our customers and partners about various pain points relating to upgrades. One of the biggest issues we identified was customizations breaking between Alfresco releases.

With Alfresco One 5.1 and the Developer Platform project we aim to solve this by defining a clear set of supported Platform and Share Extensions.

Each extension point will be fully documented in the documentation. Eventually as we iterate through the list we will add both complete code samples, a test suite and a tutorial. You can already see some of the work in the docs. The testsuite will be running as part of the build, which helps us ensure we do not break customizations.

The list of extension points are not set in stone, and we will keep adding extension points as we find and validate them with our customers, partners and community. If you feel an extension point is missing we want to know about it! Leave a comment in JIRA, here on the blog or reach out to us by email.

The key take away from the idea of supported extension points: If you are customizing Alfresco and you keep your customizations within the supported extension points, your customizations are safe and should not break between upgrades within a major version.

Module support
Beginning from 5.1, we introduce a new way of loading modules. This means that there will be a new “modules” folder in the installation directory. Here you can place your modules, and they will be loaded from here. No need to use MMT to install, simply drop your AMP or JAR in here – yes, we will officially support JARs as a packaging format beginning from 5.1.
We are working on Alfresco SDK 3.0 which will feature JAR support, while still supporting AMPs.

You can still continue using MMT to install AMPs, but the recommended way of installing modules will be to place them in the modules folder.

Developer Documentation revamp
We are in the process of completely revamping the developer section of the official docs. We have a completely new “Developer Guide”, “Architecture Guide” and a “Reference Guide”. We are taking a use case/task driven based approach, which means that the extension points will be the basis for most of the developer guide, along with tutorials and samples which lives on GitHub.

We will continue to update and publish more in-depth blog posts about these topics as we get closer to the release. We look forward to your feedback!

Alfresco SDK 2.1.1 released

I’m pleased to announce that we have just released Alfresco SDK 2.1.1.

This is a minor release, so we have fixed a number of bugs, you can see the full list here.

The biggest change for this release is that we reverted back to Java 7 for the SDK. This means that you are no longer forced to use Java 8 while using the SDK, but the SDK will support both using Java 7 and 8.

Please note that this release does not fully support Alfresco 5.1 just yet. We have started work on the next iteration of the SDK, we hope to have it ready in the coming months.

As always, we welcome your feedback! Raise an issue on GitHub or catch us on #Alfresco on FreeNode.

I also want to thank our community for their contributions, various bug reports and pull requests. We really appreciate your work and feedback, thanks!

Aikau 1.0.39 – Dynamic Form Field Option Updates

Amongst all the bug fixes and features added since my last post, in the 1.0.39 release of Aikau we’ve added a useful addition to our forms capabilities that I thought would be worth calling out. It’s actually something that I’ve been meaning to add for a while but have never had a use-case to drive its inclusion. If you’re not familiar with the different ways in which you can provide a from control with options, then you should review the information in this tutorial before reading any further.

When using a form control (e.g. Select, ComboBox, MultiSelectInput, RadioButtons), you can provide a “publishTopic” attribute that will be used to request the options for that form control to use, however the published payload didn’t provide any data about the the current values of the other fields in the form. We’ve now updated the Form widget to subscribe to a new topic that can be used to update the options-requesting payload with the current form values and then forward the request onto another topic.

In the specific use-case we needed to solve, we needed to get the available sites on the currently selected Cloud network. When the user changed the network we wanted to update a FilteringSelect widget to show the sites for that network.

This extract from one of our form models shows how this can be configured

{
  id: "CLOUD_SYNC_TENANT",
  name: "alfresco/forms/controls/FilteringSelect",
  config: {
    fieldId: "CLOUD_SYNC_TENANT",
    name: "remoteTenantId",
    label: "cloud-sync.dialog.network.label",
    optionsConfig: {
      queryAttribute: "value",
      labelAttribute: "value",
      valueAttribute: "value",
      publishTopic: topics.GET_CLOUD_TENANTS,
      publishPayload: {
        resultsProperty: "response"
      }
    }
  }
},
{
  id: "CLOUD_SYNC_SITE",
  name: "alfresco/forms/controls/FilteringSelect",
  config: {
    fieldId: "CLOUD_SYNC_SITE",
    name: "remoteSiteId",
    label: "cloud-sync.dialog.site.label",
    optionsConfig: {
      changesTo: [
        {
          targetId: "CLOUD_SYNC_TENANT"
        }
      ],
      queryAttribute: "title",
      labelAttribute: "title",
      valueAttribute: "shortName",
      publishTopic: topics.GET_FORM_VALUE_DEPENDENT_OPTIONS,
      publishPayload: {
        publishTopic: topics.GET_CLOUD_SITES,
        resultsProperty: "response"
      },
      publishGlobal: false
    }
  }
},

The key things to notice here are:

  1. We’re now using constants for all our topics. As well as reducing the number of string values to maintain, it means that we are able to improve our JSDoc for the topics to include information about the publishers and subscribers of those topics as well as the parameters that should be included in the payloads.
  2. We use topics.GET_FORM_VALUE_DEPENDENT_OPTIONS as the optionsConfig.publishTopic to request that the form (in which the control is placed) should add the current value of all the other fields into the payload provided.
  3. The optionsConfig.publishPayload.publishTopic is assigned the topic that is then published by the form using the updated payload. The subscriber to this topic should provide the options to be displayed.
  4. The optionsConfig.publishGlobal is configured to be false to ensure that the form detects the publication (a Form will generate a unique pubSubScope and pass it on to its child controls in order to scope communication within the form).
  5. It’s also worth noting how the optionsConfig.changesTo configuration is used to trigger a reloading of options as the user switches tenants (networks).

In this example the options retrieval is handled by a service subscribing to the topics.GET_CLOUD_SITES. This is able to check the published payload to find the tenant from which to retrieve the sites, e.g:

if (payload.username && payload.remoteTenantId)
{
  this.serviceXhr({
    url : AlfConstants.PROXY_URI + "cloud/people/" + payload.username + "/sites?network=" + payload.remoteTenantId,
    method: "GET",
    data: payload
  });
}

This is obviously just a single example of how this feature could be used. No doubt there will be plenty of other use cases in the future that need to take advantage of this capability.

Cross-skilling: When opportunity meets desire

by Christine Thompson

Cross-skilling seems to be a hot topic amongst our Scrum Teams at the moment. But what does this actually mean and why should anyone want to do it?

What is cross-skilling?

Cross-skilling refers to the breadth and depth of skills that a person may have. We can consider three alternatives.

1. The Specialist has a great depth of skill within just one particular area.

Specialist

2. The Jack of all Trades has a great breadth of skills, and can cover many areas, but none of them in much depth.

JackOfAllTrades

3. The Cross-skilled person has a specialism but is also able to cross into other areas where they have a limited level of skill but can help out. We would call this a “T-shaped” person.

Cross-skilled

Why is “T-shaped-ness” so good? Every team benefits from people who are experts at what they do. They are able to work quickly and effectively in their area of expertise. But what if these  specialists also understand something about each other’s areas of expertise? They can now collaborate more easily with each other, help out wherever they can and generally extend the reach of the team. Let’s have a closer look at some of the reasons for cross-skilling.

Why cross-skill?

What would drive an individual to become more “T-shaped” and to extend their skills into other areas?

1. To fill a gap that the team doesn’t have

FillGap

This makes the team more capable, by extending the skills it can cover.

2. To help out when the team need more of a skill than they currently have available

HelpOut

This makes the team more resilient because it can cope better with changes in workload and absences within the team.

3. To further the skills and experience of the individual

Extend

This is a bonus side-effect for the individual, in addition to the advantages for the team.

When to cross-skill?

The motivators for the individual to extend their skill set may be driven by:

  1. Opportunity: The project has a need, perhaps for a new skill
  2. Team-focus: The team has a need, perhaps for more of one skill
  3. Interest: The individual has a desire to learn something new

Cross-skilling should not be driven by Management but should be enabled and supported by them.

How to cross-skill?

Let’s have a look at some example scenarios which should explain these ideas.

Case Study 1:

Jason is a Java developer who works on a team where test resource is stretched. He helps to write the automated tests for the project, as defined by the test specialist in the team. He’s not a test expert but he can use his Java skills to facilitate the automated testing.

Case Study 2:

Carla is a UI developer who has a desire to extend her skill-set. She’s working on a team with only one back-end developer, who is due to take extended leave later in the year. Having done some Java training at Uni, she takes a refresher course and begins to do some back-end work, under the watchful eye of the experienced Java developer in the team.

Case Study 3:

Sally is a Scrum Master working on a team that currently has no testers. She wants to help out in this area so she builds up her domain knowledge by completing the available online training and tutorials. Working alongside the team, she carries out some exploratory testing of the stories that are being developed during the sprint, raising any issues she finds with the Product Manager and Developers.

In summary, cross-skilling is a natural, organic process which occurs via an individual’s desire to expand their skills alongside their choice to support the needs of the team. Investing in a new skill may have a short-term cost but this is likely to be out-weighed by the long-term gain for the individual, for the team and for the organisation.

Aikau 1.0.34 – Form Control Rule Evaluation Updates

Introduction

In my last blog post I said that I would try and provide more frequent updates on Aikau. Just over a week has passed since then and we’ve released version 1.0.34 at the end of Sprint 34. We didn’t deliver a huge amount as we only had 35% availability due to team members’ vacation but there was one addition that I thought was worth mentioning.

Form Control Rule Evaluation

We had a requirement from one the feature teams using Aikau to update the form controls to support OR based evaluation of the dynamic visibility, requirement and enablement behaviour. Previously we had only supported AND based evaluation such that all the configured rules needed to be true but the team wanted to be able to make a form field required if either one of two fields was not empty.

As an aside there was already a workaround to implement this using the “autoSetConfig” capabilities provided in forms to set the value of a hidden field and then use the value of that hidden field as the evaluated target for the rules. However, the updates we’ve since made are a much cleaner way of implementing the solution

The original dynamic rule capabilities are described in the Aikau tutorial on the GitHub repository so it is worth reviewing that chapter first if you’re not familiar with the concepts before you read on.

So for example you have three fields “accidents”, “convictions” and “details” and you want to ensure that if either “accidents” or “convictions” are indicated that the “details” must be provided. You can set up your basic form controls like this:

{
  id: "ACCIDENTS",
  name: "alfresco/forms/controls/RadioButtons",
  config: {
    fieldId: "ACCIDENTS",
    name: "accidents",
    value: "NO",
    label: "Previous accidents",
    description: "Have you been involved in any previous accidents?",
    optionsConfig: {
      fixed: [
        { label: "Yes", value: "YES"},
        { label: "No", value: "NO"}
      ]
    }
  }
},
{
  id: "CONVICTIONS",
  name: "alfresco/forms/controls/RadioButtons",
  config: {
    fieldId: "CONVICTIONS",
    name: "convictions",
    value: "NO",
    label: "Previous Convictions",
    description: "Do you have any previous convictions?",
    optionsConfig: {
      fixed: [
        { label: "Yes", value: "YES"},
        { label: "No", value: "NO"}
      ]
    }
  }
},
{
  id: "DETAILS",
  name: "alfresco/forms/controls/TextArea",
  config: {
    fieldId: "DETAILS",
    name: "details",
    label: "Details",
    description: "Please provide the details of your previous accidents and/or convictions" 
  }
}

Previously if you’d configured the “requirementConfig” attribute so that the “details” field became required based on the values of the “accidents” and “convictions” fields you would have created the following:

requirementConfig: {
  initialValue: true,
  rules: [
    {
      targetId: "ACCIDENTS",
      isNot: ["NO"]
    },
    {
      targetId: "CONVICTIONS",
      isNot: ["NO"]
    }
  ]
}

However, this would mean that the “details” field would only be required when both the “accidents” field and the “convictions” fields were both set to “YES”. To resolve this you can now update the configuration with a new “rulesMethod” attribute.

requirementConfig: {
  initialValue: true,
  rulesMethod: "ANY", // NOTE: This the key attribute!
  rules: [
    {
      targetId: "ACCIDENTS",
      isNot: ["NO"]
    },
    {
      targetId: "CONVICTIONS",
      isNot: ["NO"]
    }
  ]
}

Summary

This demonstrates a few of the things we like about the Aikau framework. First of all we were able to make this change in a single module (alfresco/forms/controls/utilities/RulesEngineMixin) and this new capability was immediately available for all of the form controls.

It is also a completely backwards compatible change. If you didn’t specific a “rulesMethod” attribute before then your form models will continue to work exactly as they did before. Our comprehensive unit test suites ensured that we didn’t regress any of the existing functionality.

Finally it shows that we’re able to respond to requests as they arrive and to continue to iterate on existing code without needing to constantly re-invent the wheel.

So a full page example of this would be:

model.jsonModel = {
  services: [],
  widgets: [
    {
      id: "FORM",
      name: "alfresco/forms/Form",
      config: {
        okButtonPublishTopic: "SAVE_FORM",
        okButtonLabel: "Save",
        widgets: [
          {
            id: "ACCIDENTS",
            name: "alfresco/forms/controls/RadioButtons",
            config: {
              fieldId: "ACCIDENTS",
              name: "accidents",
              value: "NO",
              label: "Previous accidents",
              description: "Have you been involved in any previous accidents?",
              optionsConfig: {
                fixed: [
                  { label: "Yes", value: "YES"},
                  { label: "No", value: "NO"}
                ]
              }
            }
          },
          {
            id: "CONVICTIONS",
            name: "alfresco/forms/controls/RadioButtons",
            config: {
              fieldId: "CONVICTIONS",
              name: "convictions",
              value: "NO",
              label: "Previous Convictions",
              description: "Do you have any previous convictions?",
              optionsConfig: {
                fixed: [
                  { label: "Yes", value: "YES"},
                  { label: "No", value: "NO"}
                ]
              }
            }
          },
          {
            id: "DETAILS",
            name: "alfresco/forms/controls/TextArea",
            config: {
              fieldId: "DETAILS",
              name: "details",
              label: "Details",
              description: "Please provide the details of your previous accidents and/or convictions",
              requirementConfig: {
                initialValue: true,
                rulesMethod: "ANY",
                rules: [
                  {
                    targetId: "ACCIDENTS",
                    isNot: ["NO"]
                  },
                  {
                    targetId: "CONVICTIONS",
                    isNot: ["NO"]
                  }
                ]
              }
            }
          }
        ]
      }
    }
  ]
};

Aikau Update August 2015

Introduction

It’s been a few months since my last update on Aikau so I thought it would be useful to provide some information on what we’ve been up to recently. I had hoped that we’d be able to make more regular communications on what is included in each weekly release and although the release notes, the JIRA backlog and sprint progress are publicly available, they don’t provide an enormous amount of context on what we’ve been working on. Internally we hold a Sprint review before each release to share with the teams that depend on Aikau the features implemented and bugs fixed, but this isn’t shared outside of the company.

In an ideal world we’d share a more detailed blog post each week, detailing what we’ve done and provide some real-world use cases of how the updates can be used. This week we released 1.0.33 – our 33rd release of the year (not including hot-fixes) – and our team velocity and processes have comfortably stabilized.

Some sprints we find ourselves working on nothing but bugs (as we prioritize these above everything else); some sprints it’s mostly feature development or infrastructure work (such as getting our unit tests working against a Selenium Grid).

In the future I’ll endeavour to provide more frequent updates, and although I can’t cover in detail everything we’ve been working on over the last dozen sprints, I’d like to highlight a few things that might warrant your further investigation.

So in no particular order, here are a few things that you might like to be aware of…

Button Styling

There is lots of work going on behind the scenes in reviewing Share from a design and usability point of view, some of which will be surfaced in the next release of Alfresco. Aikau faces the interesting challenge of supporting releases both past and future, and one of the new design requirements has been a button design. We needed to find a way of preserving the old button style when Aikau is used on a 5.0.n release but also enabling the new improved style in 5.1.n releases. We’ve achieved this through the use of LESS variables and in particular a single variable that allows us to toggle between the old and new styles.

By default Aikau uses the “legacy” style and Share in Alfresco 5.1 will enable the new style by overriding the variable in the LESS XML file (yes, we know… LESS in XML isn’t great – we still haven’t had the opportunity to do anything about that yet!). This also means that buttons can be easily styled per theme, using those LESS variables.

We continue to push more and more of the widget styling into LESS variables to avoid the need for custom CSS selectors as they will invariably be brittle as Aikau development progresses. If there is a specific widget that you would like to see us update to take advantage of LESS then you should raise an issue.

Multiple Document Libraries on a Single Page

One of the internal component teams that is consuming Aikau is implementing a single page that has multiple Aikau Document Libraries within an alfresco/layout/AlfTabContainer. This has been quite a challenge since we’re not completely finished on the Aikau Document Library, and this exercise has flushed out lots of bugs and allowed us to make some great improvements to our publication/subscription framework to ensure that the Document Libraries don’t interfere with each other (e.g. creating content in the wrong location, refreshing all the lists at once, etc). It’s also focused our attention on fixing lots of the little niggly bugs in our Document Library implementation to make it a more polished experience.

Search Without URL hashing or Infinite Scroll

We wrote the new filtered search page for Share 5.0 long before Aikau was abstracted to a project in its own right and it was written very much with a single use case in mind. Since then we’ve done lots of re-factoring and re-work on our list implementations, and quite rightly we’ve had requests to support alternative ways of providing search – namely with basic pagination and without requiring URL hashing. I’m pleased to say that with the release of 1.0.30 both of these things are possible. This will make it much easier to embed the search widgets within pages that aren’t fully dedicated to search.

Document Library Actions

We know that although Aikau predominantly supports Share it should also support other standalone clients. Since those clients won’t have access to the Share Document Library XML action configuration we needed to find a way in which to support actions in a variety of situations. We’ve settled on a fall-back model in which there are 3 ways in which you can define actions:

  1. Where available the XML configuration will be used
  2. It is also possible to configure in completely custom menu items as actions
  3. When nothing else is available fall-back to metadata evaluated actions.

This last approach requires that we map each of the existing Share Document Library action evaluators into individual AMD modules. This means it becomes really easy to add and remove actions as necessary, as well as insert new actions. Where you want to provide an entirely new action, you simply need to include a service to handle the topic that the action publishes. Hopefully this should make action configuration much simpler to re-use and customize dynamically, based on evaluated extension modules. We’re still a long way from completing this exercise but we have at least settled on an appropriate path.

Form Updates

There is steady incremental improvement on forms in Aikau. There’s still a full UX/design review on the horizon but we have made a few tweaks to the design (in particular how form controls are displayed in dialogs). We’ve also provided the ability to auto-save forms and prevent displaying validation errors immediately. It’s also possible to drive form values to and from the browser URL hash.

We’ve added an additional layout widget for forms that allows form controls to be placed in tabs: it’s worth understanding that you can’t use just any layout widget with a form because they won’t necessarily provide the capabilities to delegate the form-to-form-control communications that enable the dynamic validation, display, enablement, and requirement behaviour that Aikau forms provide.

Finally we’ve added support for dynamically showing and hiding warnings based on the changing values of the fields in the form.

Screenshot showing warnings in a form

Screenshot showing a form displaying dynamically evaluated warnings

Filtered Lists

We’ve extended the alfresco/lists/AlfSortablePaginatedList to create an alfresco/lists/AlfFilteredList. This provides the additional ability to update the request for data to include additional filters. Although this doesn’t perform any filtering on the client, it does enable filters to be passed to an API. It also supports the ability to set the filters as browser URL hash parameters to support back button navigation and sharing of bookmarks. This widget can best be seen in the Aikau Unit Test application home page.

Screenshot of Unit Test Application Index Page

Screenshot showing the Aikau Unit Test Application index page

Debug Log

When the Aikau project first started we had the alfresco/logging/SubscriptionLog widget for debugging communication over the publication/subscription layer. We’ve since replaced this with the much improved alfresco/logging/DebugLog which provides the additional capabilities to clear logs, filter on type or text and has expandable/collapsible payload rendering. We’re going to continue to improve this widget over time (any suggestions that you think would be useful are always appreciated) and you can make use of this already in Alfresco Share when client-debug mode is enabled via the Debug Menu in the header bar.

Screenshot of the DebugLog widget

Screenshot showing the DebugLog widget in a dialog

Dashlets

One of the core benefits of Aikau is its unit testing framework. This allows us to release frequently and be confident that we haven’t caused any regressions from the previous release. When the occasional regression does slip through the net we will hotfix the release containing the bug and add a new unit test to prevent any future regressions. When we first abstracted Aikau from Share we weren’t able to remove all of the core Share/YUI2 dependencies from all modules. Dashlets were an example of this, meaning they couldn’t be used outside of Share and couldn’t be unit tested. We’ve since completely removed all of those Share and YUI dependencies which has enabled us to fully unit test the Dashlet widget. Aikau Dashlets also make full use of LESS variables which means that they can be easily themed in Share.

Layout Widgets

We continue to add layout widgets and improve the behaviour of the existing layout widgets. I thought it would be worth calling out a few of the recent additions and updates…

HorizontalWidgets

The alfresco/layout/HorizontalWidgets widget has been updated so that it now takes into account changes to the visibility of its immediate child widgets. This means that the full horizontal space is always consumed as widgets are displayed and hidden. It does this by using the visibilityConfig and invisibilityConfig attributes on its child widgets, and then resizes and recalculates as they are hidden or revealed. Coupled with the existing ability to mix and match fixed widths, percentage widths, and automatically assigned widths on its child widgets, makes this a very powerful tool for fluid layouts.

FixedHeaderFooter

As its name suggests, the alfresco/layout/FixedHeaderFooter provides the ability to define fixed-height header and footer widget models, with a scrollable central panel. It can be configured to have a fixed height or can automatically grow to consume all of the available vertical space from its offset within a page. This makes it possible to have key controls always visible on the page such as the pagination controls for a list or a menu bar that relates to the scrolling content.

InfiniteScrollArea

The alfresco/layout/InfiniteScrollArea is designed to work with the alfresco/lists/AlfSortablePaginatedList (or one of its descendant modules). It can be thought of as the inverse of infinite scrolling – instead of scrolling triggering the loading of the next page of data, pages of data are continually requested until the available vertical space is used up. If more space is then provided (for example if it was included in a resizeable Dashlet that was then expanded) then more data will automatically be requested.

StripedContent

During a prototyping exercise we looked at various layout options and one that has since been integrated into Aikau is the alfresco/layout/StripedContent. This widget allows for a fixed width vertical column to be added to a page where stripes are rendered across the full width of the page. A few stripe styles are included out-of-the-box that can be configured through LESS variables.

Drag And Drop

The Content Modelling feature in Alfresco 5.1 makes heavy use of the Aikau drag-and-drop capabilities. This has meant that we’ve had the opportunity to flush out lots of bugs and make drag-and-drop in Aikau really simple. All the drag-and-drop modules were re-written (and can be found in the alfresco/dnd package) to be completely abstract to support custom data modelling. Really, this needs a blog post or a set of tutorials in its own right, but the unit test pages should give you an idea of what’s possible. Again, just something to be aware of – at some point it would be great if we could make use of the capabilities for a complete drag-and-drop development environment (we even have a unit test page that allows you to build drag-and-drop data models for this purpose!) – but sadly we just don’t have the bandwidth to work on it at the moment.

Where To Find Out More

It’s a great idea to keep a clone of the Aikau GitHub repository up-to-date so that you can use the Unit Test Application to see examples of all the widgets in action. Although this application is intended for unit testing rather than demonstration purposes it is a great way of seeing various configurations of all the widgets in action.