This post is the third in a series of blog posts about customizing for Clearspace 2.x. The previous posts covered general information about Customizations in Clearspace 2.x and upgrading themes and FTL files. This post continues the series with more information about widgets.

 

Widgets can be used much more broadly in version 2 than previously, so most of your widget-specific upgrade changes are related to this broader support. In version 1 a system or space administrator could use widgets only to assemble a space or community overview page. In version 2 both administrators and users can customize page layouts in several areas. Widgets can be used on the Clearspace instance home page (which has been rendered from main.ftl), a user's personal home page, a community/space overview page, a project overview page.

 

Note that unless your widget is extremely simple, you're likely to also need to keep in mind API changes and FreeMarker changes. For example, version 2 requires that widgets acquire references to Clearspace manager beans using Spring. The rest of widget development model  -- artifacts involved, how you deploy them, and so on  -- is unchanged from version 1.

 

When upgrading a widget (or developing a new one on version 2), you use the @WidgetTypeMarker annotation to specify which of the display contexts your widget is allowed in. Deciding which contexts to allow is an important part of your widget's design. For example, you might decide that a widget that takes a very individual-oriented set of property values (such as the Tag widget, which displays content associated with a particular tag) isn't useful in high-level contexts such as the instance or space home pages (where the broad set of people viewing might want views on a large variety of tags).

 

The @WidgetTypeMarker annotation supports values from the WidgetType enumeration. Here's an example that includes all of those values:

 

@WidgetTypeMarker({WidgetType.HOMEPAGE, WidgetType.PERSONALIZEDHOMEPAGE, 
    WidgetType.COMMUNITY, WidgetType.PROJECT})
@PropertyNames("myProperty")
public class MyWidget extends BaseWidget {
    // Implementation code omitted.
}

In order to reduce the tight coupling between the widget views (which are typically built using FreeMarker) and the rest of the Clearspace application, the widget context that was previously populated with a reference to the current context via a JiveContext instance has been modified so that the widget view no longer has access to that instance. That means that you'll need to provide everything that your widget view needs through the properties that the widget interface requires. Typically you'll create a widget class that extends BaseWidget and then you'll override this method:

 

protected Map<String, Object> loadProperties(WidgetContext widgetContext, ContainerSize size)

So in the previous version of Clearspace, you might have had something like this in the FTL file that's your widget's view:

 

${widgetContext.jiveContext.communityManager.rootCommunity.ID?c}

Because the JiveContext instance has been removed from the WidgetContext class, you'll need to provide your view with the properties it needs explicitly in your widget. Here's an example:

 

public class MyWidget extends BaseWidget {

    // Declare a property variable and setter for injection by Spring.
    private CommunityManager communityManager;
    public void setCommunityManager(CommunityManager cm) {
        this.communityManager = cm;
    }

    protected Map<String, Object> loadProperties(WidgetContext widgetContext, 
        ContainerSize size)
    {
        Map<String, Object> properties = super.loadProperties(widgetContext, size);
        // Implementation code omitted.
        properties.put("rootCommunityID", communityManager.getRootCommunity().getID());
        return properties;
    }
}

Finally, because you can create a widget that exists in multiple parts of the application (the homepage, a personalized homepage, a community, a project), you'll sometimes want to change the behavior of your widget based on where the widget is being rendered. You can determine the render context of your widget by checking the type of the WidgetContext class that you're given in the loadProperties method. Here's some example code that shows how you can determine what context the widget is in:

 

public class MyWidget extends BaseWidget {
    protected Map<String, Object> loadProperties(WidgetContext widgetContext, ContainerSize size) {
        Map<String, Object> properties = super.loadProperties(widgetContext, size);
        if (widgetContext.getWidgetType() == WidgetType.COMMUNITY) {
            CommunityWidgetContext cwc = (CommunityWidgetContext)widgetContext;
            // Do something specific for the community
        }
        else if (widgetContext.getWidgetType() == WidgetType.HOMEPAGE) {
            HomepageWidgetContext hwc = (HomepageWidgetContext)widgetContext;
            // Do something specific for the homepage
        } 
        else if (widgetContext.getWidgetType() == WidgetType.PERSONALIZEDHOMEPAGE) {
            PersonalizedHomepageWidgetContext phwc = 
                (PersonalizedHomepageWidgetContext)widgetContext;
            // Do something specific for the personalized homepage    
        }
        else if (widgetContext.getWidgetType() == WidgetType.PROJECT) {
            ProjectWidgetContext wwc = (ProjectWidgetContext)widgetContext;
            // Do something specific for the project
        }
    
        properties.put("rootCommunityID", communityManager.getRootCommunity().getID());
        return properties;
    }
}

 

The information above along with more details can be found in the Upgrading Extensions to 2.0 documentation.

 

You can also watch a video and download a presentation to learn more about how to write new widgets for Clearspace 2.0 from Aaron Johnson, Engineering Manager at Jive.