Answers to questions on developing and manipulating widgets.
Widgets provide a way for administrators to customize the space, project, social group and system homepages (Overview tab). They're a simple to create combination of Java code and FreeMarker templates that can be deployed as a plugin.
The WidgetContext, which should be available in your FreeMarker template as widgetContext, has an isEdit() method, which should give you the ability to show a different view if the widget is being rendered as part of a editing session.
Not at this time, no.
Not at this time, no. However, there are a number of ways that you can expose content to other systems using either RSS or JSON.
Yes, although if you do this and your widget uses JavaScript to refer to various parts of the template, you'll want to append an identifier to the DOM element ID's that you create/manipulate. An example of how to do that is in the /template/widget/your-statusupdates.ftl template, which contains this line of code at the top of the template:
<#assign idPrefix = StringUtils.randomString(6) />
and then later in the page a <div> element in the widget can be referred to like this:
<div id="current-status-${idPrefix}">
Yes, the current user is part of the WidgetContext interface that gets passed to your plugin's render method. If your widget extends BaseWidget, then you can call applyFreemarkerTemplate() which will call loadProperties() and adds the WidgetContext to the FreemarkerContext, and from there you can access the current user. Also, if you override loadProperties() then you can add whatever other run-time props you want to access in your FTL file.
You need a plugin.xml with a <widget> element pointing to a class that implements the Widget interface (or better yet that extends BaseWidget). That's the bare minimum and assumes no design-time properties. If you want design-time props, then you'll need a properties file in the beans folder, and a @PropertyNames annotation at the class level that defines the design-time properties.
PopularityDeterminationTask is the class that handles the majority of the work. It runs every 15 minutes (as configured in spring-taskContext.xml, which means you can probably change it via a plugin in 2.1 if you want) and works closely with ActivityManagerImpl. Every time it runs it does the following things:
Calendar c = Calendar.getInstance();
c.add(Calendar.DATE, -daysAgo);
Date now = new Date();
Date nDaysAgo = c.getTime();
long dateDiff = now.getTime() - nDaysAgo.getTime();
long dateAdjustment = dateDiff / 86400000;
long decayedScore = score / (1 + dateAdjustment);
Add the results of the second and third steps together. So for example, let's say I published a blog post 2 months ago and through some sort of magic, it got 3 comments every day for the last 2 months (and it's already received 2 comments today that haven't been archived to the jivePopularity table). We only take into account the popularity score for the last seven days so the total score is going to be the sum of the following scores:
Date | Number of Comments | Recorded Score | Score With Decay |
---|---|---|---|
6/5/2008 (today) | 3 | 15 | 15 |
6/4/2008 | 3 | 15 | 7 |
6/3/2008 | 3 | 15 | 5 |
6/2/2008 | 3 | 15 | 3 |
6/1/2008 | 3 | 15 | 3 |
5/31/2008 | 3 | 15 | 2 |
5/30/2008 | 3 | 15 | 2 |
Total Score | 37 |
Finally, each item is added to a SortedSet and then copied back to ActivityManagerImpl, where it lives until the next time popularity is calculated fifteen minutes later.
So when you see a widget that shows the most popular items for a given space, project, social group or blog, you're getting the n items who have the highest combined score, which is a combination of comments, replies, edits and views, decayed over the last seven days.
Short & Sweet.
.jive-widget {border:none !important;}
If you wanted to remove the background on the header...
.jive-widget .jive-widget-header {background:transparent !important;}
But you might want an underline so that people know it is the header still...
.jive-widget .jive-widget-header {
background:transparent !important;
border-bottom:1px dashed gray;
}
And last -- a disclaimer that not all the widgets are controlled by these 2 pieces of CSS. So further work would be needed in the profile, actions, etc.1