Polarion Widget SDK
Polarion Widget SDK
Polarion Widget SDK
© 2022 Siemens
This material contains trade secrets or otherwise confidential information owned by Siemens Industry Software, Inc., its subsidiaries or its affiliates (collectively, "Siemens"), or its
licensors. Access to and use of this information is strictly limited as set forth in Customer's applicable agreement with Siemens. This material may not be copied, distributed, or otherwise
disclosed outside of Customer's facilities without the express written permission of Siemens, and may not be used in any way not expressly authorized by Siemens.
This document is for information and instruction purposes only. Siemens reserves the right to make changes in specifications and other information contained in this publication without
prior notice, and the reader should, in all cases, consult Siemens to determine whether any changes have been made. Representations about products, features or functionality in this
document constitute technical information, not a warranty or guarantee, and shall not give rise to any liability of Siemens whatsoever. Siemens disclaims all warranties including, without
limitation, the implied warranties of merchantability and fitness for a particular purpose. In particular, Siemens does not warrant that the operation of the products will be uninterrupted or
error free.
The terms and conditions governing the sale and licensing of Siemens products are set forth in written agreements between Siemens and its customers. Siemens' End User License
Agreement and Universal Contract Agreement may be viewed at: https://www.sw.siemens.com/en-US/sw-terms/
TRADEMARKS: The trademarks, logos, and service marks ("Marks") used herein are the property of Siemens or other parties. Noone is permitted to use these Marks without the prior
written consent of Siemens or the owner of the Marks, as applicable. The use herein of third party Marks is not an attempt to indicate Siemens as a source of a product, but is intended to
indicate a product from, or associated with, a particular third party. A list of Siemens' trademarks may be viewed at:
https://www.plm.automation.siemens.com/global/en/legal/trademarks.html.
The registered trademark Linux® is used pursuant to a sublicense from LMI, the exclusive licensee of Linus Torvalds, owner of the mark on a world-wide basis.
Siemens Digital Industries Software is a leading global provider of product life cycle management (PLM) software and services with 7 million licensed seats and 71,000 customers
worldwide. Headquartered in Plano, Texas, Siemens Digital Industries Software works collaboratively with companies to deliver open solutions that help them turn more ideas into
successful products. For more information on Siemens Digital Industries Software products and services, visit https://www.siemens.com/plm
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.6 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
5.6 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
6 Small Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
7 Page Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
9 Actions in widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
9.2 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
13.1 The HTML attributes configured on a Work Item so that the Work Items sidebar is displayed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
14.1 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
15 F.A.Q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1 Java widget example
1.1 Introduction
This example will detail how to create a custom Java widget for Pages.
By developing your own widgets you can extend your widget library in Pages.
How to create a custom widget. A Work Record Report widget will be implemented that calculates work records from items defined by its parent and link
role.
See the Workspace preparation section in the main Polarion SDK Guide.
The best way to create a Project plugin is to import the provided example. (It contains all the dependencies needed to create a custom plugin.)
Info: Make sure that your plugin is compiled against the Polarion version that you use. This example contains a precompiled jar plugin. You can remove it before you start
developing your own plugin based on this example. Eclipse ensures that the new jar plugin will be created against your source code and Polarion version.
See the Deployment to Installed Polarion section in the main Polarion SDK guide.
See the Execution from Workspace section in the main Polarion SDK guide.
1.6 Configuration
After a successful deployment of the plug-in into Polarion the Work Record widget can be used in Pages.
Info: A custom widget plugin is deployed using HiveMind. See /src/META-INF/hivemodule.xml for more details. Deployment configuration is located at
/com.polarion.alm.ui/ui.jar/META-INF/richpages-hivemodule.xml.
2 Velocity widget example
2.1 Introduction
This example will detail how to create a custom, Velocity based, widget for Pages.
By developing your own widgets you can extend your widget library for Pages.
How to create a custom Widget. A Work Record Report widget will be implemented that calculates work records from items defined by its parent and link role.
2.2 Deployment
Info: Velocity widgets can be deployed to the repository for both the Global and Project scopes. Widgets deployed for the Global scope will be visible to all Projects. If there are
two widgets with the same ID deployed on both Global and Project scopes, then the widget in the Project scope will be used.
2.3 Tags
A widget's tags (or categories), that are specified as a comma separated list in the tags property in the widget.properties file, can be any String or localization key. For the localization keys
of the standard tags see the javadoc for com.polarion.alm.shared.api.model.rp.widget.RichPageWidget.getTags(SharedContext)
3.1 Introduction
This example will detail how to deploy a custom macro for Pages.
By developing your own macros you can extend your macro library for Pages.
How to create custom macro. A custom Info box will be implemented that displays information.
3.2 Deployment
3.2.2 Usage
1. Place a Script, a Block, a Script or an Inline widget to your Page via the widgets sidebar.
2. Import macros using #import("macros.vm").
3. Use an infoBox macro like #infoBox("your message").
Info: Polarion first searches for the included file in the Project scope. If it doesn’t find it there, then it is taken from the Global scope.
4 Customize an existing widget within a Script widget
4.1 Introduction
This example will detail how to customize an existing Widget within a script widget using the Copy Widget Source Code operation.
How to customize an existing Multi Line Trend Chart widget. (The number of work items, separated by category in a time axis will be displayed.)
4.2 Implementation
#set($projectId = "PROJECT_ID")
<div class="polarion-rp-widget-part" data-widget="com.polarion.multiSetTrendChart">
<span class="polarion-rp-widget-parameters">
<sub id="title">Work Items count separated by category</sub>
<sub id="data">
<sub id="elements">
#set($categories = $transaction.categories().search().query("project.id:$projectId"))
#foreach ($category in $categories)
<sub>
<sub id="prototype">WorkItem</sub>
<sub id="queryType">lucene</sub>
<sub id="luceneQuery">categories.id:$category.fields.id.get</sub>
<sub id="children">
<sub id="name">$category.fields.name.get</sub><sub id="color"></sub>
</sub>
</sub>
#end
</sub>
</sub>
<sub id="timeAxis">
<sub id="from">
<sub id="relative">-30</sub>
</sub>
<sub id="to">
<sub id="relative">0</sub>
</sub>
<sub id="scaleType">week</sub>
<sub id="baseDate">1</sub>
</sub>
</span>
</div>
Info: There are two kinds of Script widgets - Inline and Block. Inline widgets can be used inside a paragraph because they don’t break the text. Block widgets are used as
separate components.
5 Extend Velocity context example
5.1 Introduction
This example will detail how to deploy and use your own HiveMind services or Java instances in scripts, widgets and macros.
By developing your own services and objects, you can extend the Velocity context used in Pages, widgets, macros and parameters that support it.
How to extend the Velocity context. Work Item Util will be implemented and contributed as a Java instance that will count the time spent on a given Work Item. Then Repository
Util will be implemented and contributed as a HiveMind service that provides a method for getting the last revision in the repository, and provide the IRepositoryService.
See the Workspace preparation section in the main Polarion SDK Guide.
The best way to create a Project plugin is to import a provided example that contains all the dependencies needed to create your custom plugin.
Info: Make sure that your plugin is compiled against the Polarion version that you use. This example contains a precompiled jar plugin. You can remove it before you start
developing the plugin based on this example. Eclipse ensures that the new jar plugin will be created against your source code and Polarion version.
See the Deployment to Installed Polarion section in the main Polarion SDK guide.
See the Execution from Workspace section in the main Polarion SDK guide.
5.6 Configuration
After a successful deployment of the plug-in into Polarion, you can start using Work Item Util and Repository Util within your Velocity code on Pages:
Create a page with, for example, a Script Block widget. Use the following as the script's content:
$workItemUtil.printTimeSpent($transaction.workItems().getBy().ids("PROJECT_ID", "WORKITEM_ID"))
Replace PROJECT_ID and WORKITEM_ID with Project and Work Item IDs that have work records.
Info: The Velocity Context plugin is deployed using HiveMind. See /src/META-INF/hivemodule.xml for details.
To enable an Inline widget, create a widget.properties file in the target widget's folder and add the fillowing line:
inline=true
6 Small Examples
This example details how to use the Script Block widget to generate a custom Highcharts chart using Velocity and the Polarion Rendering API.
#set($html = $renderingContext.createHtmlFragmentBuilder())
#set($chart = $renderingContext.createChartBuilder())
#set($pie = $chart.pie().name("Number of demands"))
$!pie.addValue("yksi", 1).null
$!pie.addValue("kaksi", 2).null
$!pie.addValue("kolme", $math.toDouble("3.3")).null
$!chart.build().title().text("Sample").null
$!chart.build().plotOptions().pie().addRawAttribute("tooltip", "{pointFormat: '<b>{point.y}</b>'}").null
$!chart.build().render($html, 300, $renderingContext.columnWidth).null
$html
Sample
yksi
kolme
kaksi
This example shows how to set raw attributes for these charts.
#set($html = $renderingContext.createHtmlFragmentBuilder())
#set($builder = $renderingContext.createChartBuilder().build())
$!builder.title().text("Chart").null
$!builder.chart().type().line().null
$!builder.addRawAttribute("noData","{style: {fontWeight: 'bold', fontSize: '15px', color: '#FF0000'}}").null
$!builder.render($html, 300, $renderingContext.columnWidth).null
$html
Chart
No data to display
The Highchart is now configured and you can use Velocity to pull data from Polarion to populate the chart.
The following code examples show how to use the Script Block widget to render a table that displays object properties. The object set is defined by a query.
EXAMPLE 1:
<table class="polarion-rpw-table-content">
<tbody>
<tr class="polarion-rpw-table-header-row">
<th>Item</th>
<th>Status</th>
<th>Parent</th>
</tr>
#foreach($w in $transaction.workItems.search.query("project.id:drivepilot"))
<tr class="polarion-rpw-table-content-row">
<td>$w.render.withLinks.withTitle</td>
<td>$w.fields.status.render</td>
<td>
#foreach($l in $w.fields.linkedWorkItems.direct)
#if($l.fields.role.get.id == "parent")
$l.fields.workItem.render.withTitle.withLinks
#end
#end
</td>
</tr>
#end
</tbody>
</table>
EXAMPLE 2:
<table class="polarion-rpw-table-content">
<tbody>
<tr class="polarion-rpw-table-header-row">
<th>Plan #</th>
<th># of Work Items at Start</th>
<th># of WIs at End</th>
</tr>
#set($counter=1)
#foreach($plan in $transaction.plans().search().limit(19))
#if($plan.fields().startedOn().get() && $plan.fields().finishedOn().get() && $plan.fields().name().get().contains("Team"))
#set($revisionStarted = $transaction.revisions().getBy().dateOrAfter($plan.fields().startedOn().get()).fields().id().get())
#set($planAtStart = $transaction.plans().getBy().revision($revisionStarted).path($plan.getReference().toPath()))
#set($revisionFinished = $transaction.revisions().getBy().dateOrAfter($plan.fields().finishedOn().get()).fields().id().get())
#set($planAtEnd = $transaction.plans().getBy().revision($revisionFinished).path($plan.getReference().toPath()))
#if(!$planAtStart.isUnresolvable() && !$planAtEnd.isUnresolvable())
<tr class="polarion-rpw-table-content-row">
<td>$counter</td>
<td>$planAtStart.items().size()</td>
<td>$planAtEnd.items().size()</td>
</tr>
#set($counter=$math.add($counter, 1))
#end
#end
#end
</tbody>
</table>
This example shows how to use the Field selector widget parameter and how to define which fields are selected by default.
#set($myFields = $objectFactory.newSet())
#set($void = $myFields.add("priority"))
#set($void = $myFields.add("severity"))
$parameters.put("myFieldsParameter", $factory.fields("My Fields Parameter").fields($myFields).build())
6.5 Get a historical object by date
The following code example details how to get a respective revision for a given date. (Followed by how to use that revision to get the historical data of an
object.)
Example displays number of work items linked to plans when started and finished.
<table class="polarion-rpw-table-content">
<tbody>
<tr class="polarion-rpw-table-header-row">
<th>Plan #</th>
<th># of Work Items at Start</th>
<th># of WIs at End</th>
</tr>
#foreach($plan in $transaction.plans().search())
#set($revisionStarted = $transaction.revisions().getBy().dateOrAfter($plan.fields().startedOn().get()).fields().id().get())
#set($planAtStart = $transaction.plans().getBy().revision($revisionStarted).path($plan.getReference().toPath()))
#set($revisionFinished = $transaction.revisions().getBy().dateOrAfter($plan.fields().finishedOn().get()).fields().id().get())
#set($planAtEnd = $transaction.plans().getBy().revision($revisionFinished).path($plan.getReference().toPath()))
<tr class="polarion-rpw-table-content-row">
<td>$plan.fields().name().get()</td>
<td>$planAtStart.items().size()</td>
<td>$planAtEnd.items().size()</td>
</tr>
#end
</tbody>
</table>
<table class="polarion-rpw-table-content">
<tbody>
<tr class="polarion-rpw-table-header-row">
<th>Plan #</th>
<th># of Work Items at Start</th>
<th># of WIs at End</th>
</tr>
#set($counter=1)
#foreach($plan in $transaction.plans().search().limit(19))
#if($plan.fields().startedOn().get() && $plan.fields().finishedOn().get() && $plan.fields().name().get().contains("Team"))
#set($revisionStarted = $transaction.revisions().getBy().dateOrAfter($plan.fields().startedOn().get()).fields().id().get())
#set($planAtStart = $transaction.plans().getBy().revision($revisionStarted).path($plan.getReference().toPath()))
#set($revisionFinished = $transaction.revisions().getBy().dateOrAfter($plan.fields().finishedOn().get()).fields().id().get())
#set($planAtEnd = $transaction.plans().getBy().revision($revisionFinished).path($plan.getReference().toPath()))
#if(!$planAtStart.isUnresolvable() && !$planAtEnd.isUnresolvable())
<tr class="polarion-rpw-table-content-row">
<td>$counter</td>
<td>$planAtStart.items().size()</td>
<td>$planAtEnd.items().size()</td>
</tr>
#set($counter=$math.add($counter, 1))
#end
#end
#end
</tbody>
</table>
The examples below refer to a page parameter with "Name" as the ID, "String" as the Type and "John Doe" as the Value.
To access the instance:
$pageParameters.Name => StringParameterImpl: Name, John Doe
Examples below refer to a page parameter "Year" as the ID, "Integer" as the Type and "2014" as the Value.
To access the instance:
$pageParameters.Year => IntegerParameterImpl: Year, 2014
Examples below refer to a page parameter with "Advanced" as the ID, "Boolean" as the Type and "Yes" as the Value.
To access the instance:
$pageParameters.Advanced => BooleanParameterImpl: Advanced, true
Examples below refer to a page parameter with "reqtype" as the ID, "Enumeration" as the Type and "Functional" and "Business" as the Values.
To access the instance:
$pageParameters.reqtype => EnumParameterImpl: Requirement Types, [functional, business]
To obtain the first value (or the sole value for single-value enumeration):
$pageParameters.reqtype.singleValue => ProxyEnumOption id:functional
Examples below refer to a page parameter with "color" as the ID, "Custom Enumeration" as the Type, "Red", "Green" and "Blue" as the Names and "#f00", "#0f0", "#00f" as the Values.
To access the instance:
$pageParameters.color => com.polarion.alm.shared.api.model.rp.parameter.impl.enumeration.CustomEnumParameterImpl@16b57246
To obtain the first value (or the sole value for single-value enumeration):
$pageParameters.color.singleValue => #f00
To obtain the first name (or the sole name for single-value enumeration):
$pageParameters.color.singleName => Red
Examples below refer to a page parameter with "From" as the ID, "Date" as the Type and "March 20th 2015" as the Absolute Date.
To access the instance:
$pageParameters.From => DateParameterImpl: From, Fri Mar 20 00:00:00 CET 2015
Method calls toSql() and toLucene() are automatically added when Page Parameters are used in "Lucene + Velocity" and "SQL + Velocity" queries. So given a page parameter with
"Year" as the ID, you can use the query for all items resolved in that year: resolvedOn:[${pageParameters.Year}0101 TO ${pageParameters.Year}1231]
For more information see the Javadoc for methods defined by the com.polarion.alm.shared.api.model.rp.parameter.ParameterUsableInQuery interface.
7 Page Script
The Page Script is executed before widgets and can be used to:
The Page Script can use the same Velocity context variables as widgets with following exceptions:
The results of executing the Page Script can be displayed using the Show Results action in the sidebar toolbar. (Useful for debugging.)
The errors and warnings logged by Velocity can be displayed using the Show Problems action in the sidebar menu. (Displayed only if problems are reported.)
Page Context is the holder of the variables prepared by the Page Script and then accessed by scripted widgets. It can be modified only by the Page Script.
The rendering of widgets runs concurrently in some cases, so the variables placed in the Page Context must be thread-safe objects if they are accessed by
more than 1 widget on the page.
API objects returned from a transaction like WorkItem or Document should not be stored to the Page Context, because they are only usable inside the given
transaction and the rendering of widgets is sometimes executed in different transactions. Instead, store references like WorkItemReference that you get from
the WorkItem.getReference() method (and later in the widget). Use the $reference.get($transaction) to get the WorkItem again.
The following Page Script is an example of how to prepare common parts of SQL queries that can then be used by multiple widgets to display the same data in different ways:
#set($uncoveredReqWhere = $objectFactory.newStringBuilder)
$!uncoveredReqWhere.append("and C_TYPE in $pageParameters.reqtypes.toSql ${esc.n}").null
#if(!$pageParameters.version.values.empty)
$!uncoveredReqWhere.append("and CUSTOM_FIELD.FK_WORKITEM = WORKITEM.C_PK ${esc.n}").null
$!uncoveredReqWhere.append("and CUSTOM_FIELD.C_NAME = 'targetVersion' ${esc.n}").null
$!uncoveredReqWhere.append("and CUSTOM_FIELD.C_STRING_VALUE = '$pageParameters.version.singleValue().id()' ${esc.n}").null
#end
#if(!$pageParameters.status.values.empty)
$!uncoveredReqWhere.append("and C_STATUS IN $pageParameters.status.toSql ${esc.n}").null
#end
#set($coveredReqWhere = $objectFactory.newStringBuilder)
$!coveredReqWhere.append($uncoveredReqWhere).null
#set($testQuery = $objectFactory.newStringBuilder)
$!testQuery.append("select TEST.C_PK from WORKITEM TEST, STRUCT_WORKITEM_LINKEDWORKITEMS LINK ${esc.n}").null
$!testQuery.append(" where LINK.FK_WORKITEM = WORKITEM.C_PK ${esc.n}").null
$!testQuery.append(" and LINK.FK_P_WORKITEM = TEST.C_PK ${esc.n}").null
$!testQuery.append(" and LINK.C_ROLE = '$pageParameters.verifiesLinkRole.toSql'").null
$!uncoveredReqWhere.append("and not exists ($!testQuery)").null
$!coveredReqWhere.append("and exists ($!testQuery)").null
$!pageContext.put("uncoveredReqWhere", "$uncoveredReqWhere")
$!pageContext.put("coveredReqWhere", "$coveredReqWhere")
#if(!$pageParameters.version.values.empty)
$!pageContext.put("joinCustomField", ",CF_WORKITEM CUSTOM_FIELD").null
#end
## show the values in the result for debugging
<pre>
uncoveredReqWhere:
$uncoveredReqWhere
coveredReqWhere:
$coveredReqWhere
</pre>
The example was developed for the Drive Pilot demo project and uses the following page parameters:
reqtypes - Requirement Item Types - Multi-enumeration parameter for the workitem-type enumeration.
version - Version - Enumeration parameter for Plans with query: template.id:release.
status - Status - Enumeration parameter for the status enumeration.
uncoveredReqWhere:
and C_TYPE in ('systemRequirement', 'softwareRequirement', 'mechanicalRequirement', 'electricalRequirement')
and CUSTOM_FIELD.FK_WORKITEM = WORKITEM.C_PK
and CUSTOM_FIELD.C_NAME = 'targetVersion'
and CUSTOM_FIELD.C_STRING_VALUE = 'Version_2_0'
and C_STATUS IN ('approved')
and not exists (select TEST.C_PK from WORKITEM TEST, STRUCT_WORKITEM_LINKEDWORKITEMS LINK
where LINK.FK_WORKITEM = WORKITEM.C_PK
and LINK.FK_P_WORKITEM = TEST.C_PK
and LINK.C_ROLE = 'verifies')
coveredReqWhere:
and C_TYPE in ('systemRequirement', 'softwareRequirement', 'mechanicalRequirement', 'electricalRequirement')
and CUSTOM_FIELD.FK_WORKITEM = WORKITEM.C_PK
and CUSTOM_FIELD.C_NAME = 'targetVersion'
and CUSTOM_FIELD.C_STRING_VALUE = 'Version_2_0'
and C_STATUS IN ('approved')
and exists (select TEST.C_PK from WORKITEM TEST, STRUCT_WORKITEM_LINKEDWORKITEMS LINK
where LINK.FK_WORKITEM = WORKITEM.C_PK
and LINK.FK_P_WORKITEM = TEST.C_PK
and LINK.C_ROLE = 'verifies')
An example widget that uses the variables. The parameters of the widget are shown on the right side:
7.2 Scripted Page Parameters
Page Script can add additional page parameters on top of the page parameters defined in the Page Parameters sidebar. Page Script cannot add a page parameter with the same ID as
a parameter already defined in the sidebar and an error will be logged in the Page Script error log if it tries to.
The Page Script below shows how to add 2 date type Page Parameters with values taken from Plan Start Date and Due Date fields.
The example is meant to be used in a Plan report.
#set($startDate = $plan.fields.startDate.getIfCan)
#set($startDateBuilder = $factory.date("Start Date"))
#if ($!startDate)
$!startDateBuilder.absolute($!startDate)
#end
$!scriptedPageParameters.put("startDate", $startDateBuilder.build())
#set($dueDate = $plan.fields.dueDate.getIfCan)
#set($dueDateBuilder = $factory.date("Due Date"))
#if ($!dueDate)
$!dueDateBuilder.absolute($!dueDate)
#end
$!scriptedPageParameters.put("dueDate", $dueDateBuilder.build())
These parameters can be then used for any date parameters in widgets, for example in chart widgets as shown below:
It is possible to define dependencies between widget parameters. When a report designer changes the value of a widget parameter that is marked as 'dependency source', any other
parameters that are marked as 'dependency target' can be reconfigured accordingly.
8.1 Example
- The first is the object selector parameter where a user can select a Work Item.
- The second is an enumeration parameter for selecting link roles.
The second parameter should provide the possibility to select a link role from a Project when defined in the Work Item.
A complete implementation of this example is available in the Work Records (Java and Velocity) widget examples .
Definition of Parameters:
parameters.put(PARAMETER_USER_STORY, factory.objectSelector("User
Story").allowedPrototypes(PrototypeEnum.WorkItem).dependencySource(true).build());
parameters.put(PARAMETER_LINK_ROLE, factory.enumeration("Link Role", "workitem-link-role").dependencyTarget(true).build());
EnumParameter parameter = context.parameter(WorkRecordReportWidget.PARAMETER_LINK_ROLE);
parameter.set().scope(scope);
Definition of Parameters:
$parameters.put("userStory", $factory.objectSelector("User Story").allowedPrototypes(["WorkItem"]).dependencySource(true).build())
$parameters.put("linkRole", $factory.enumeration("Link Role", "workitem-link-role").dependencyTarget(true).build())
#if (!$workItem)
#set($scope = $null)
#else
#set($scope = $workItem.getReference().scope())
#end
$linkRoleParameter.set().scope($scope)
9 Actions in widgets
It is possible to create a button in a widget that triggers a server side action when clicked. (For example, a button that starts a Plan.)
A rendered widget contains elements with the following special attribute (RichPageWidget.ATTRIBUTE_ACTION_ID) defined.
When a user clicks on it, a request is sent to the server and RichPageWidget.executeAction(RichPageWidgetActionContext) is triggered.
A widget developer can handle the event by implementing executeAction in the widget.
Note: The standard action handling persists some changes, so its good practice to request a user confirmation up front.
(See RichPageWidget.ATTRIBUTE_CONFIRM_* keys.)
A widget developer can also define whether the page should be refreshed after the action executes, or if only the widget will be re-rendered.
This can be done by calling RichPageWidgetActionContext.refresh(boolean).
It's important to understand that there can be several widgets of the same kind on the same page, so identifying exactly what should be done should be based on the
ATTRIBUTE_ACTION_ID value and the widget parameters.
9.2 Example
private void renderAction(@NotNull HtmlContentBuilder htmlContentBuilder, @NotNull DurationValue total) {
HtmlTagBuilder a = htmlContentBuilder.tag().a();
a.append().text("Update time spent in the user story");
a.attributes().byName(RichPageWidget.ATTRIBUTE_ACTION_ID, total.toString());
a.attributes().byName(RichPageWidget.ATTRIBUTE_CONFIRM_TITLE, "Update time spent");
a.attributes().byName(RichPageWidget.ATTRIBUTE_CONFIRM_TEXT, "Do you want to update time spent?");
}
public void executeAction(@NotNull RichPageWidgetActionContext context) {
ObjectSelectorParameter parameter = context.parameter(PARAMETER_USER_STORY);
WorkItem workItem = (WorkItem) parameter.value();
if (workItem == null) {
return;
}
Duration value;
try {
value = new Duration(context.actionId());
} catch (Exception e) {
return;
}
UpdatableWorkItem updatableWorkItem = workItem.getUpdatable(context.transaction());
updatableWorkItem.fields().timeSpent().set(value);
updatableWorkItem.save();
context.refresh(true);
}
Complete implementation of this example is available in the Java Work Records widget example.
transaction
com.polarion.alm.shared.api.transaction.ReadOnlyTransaction
localization
com.polarion.alm.shared.api.utils.SharedLocalization
me
java.lang.String
current user ID (shortcut for $transaction.context.currentUserId)
objectFactory
com.polarion.alm.shared.api.utils.velocity.ObjectFactory
trackerService
com.polarion.alm.tracker.ITrackerService
projectService
com.polarion.alm.projects.IProjectService
securityService
com.polarion.platform.security.ISecurityService
platformService
com.polarion.platform.IPlatformService
testManagementService
com.polarion.alm.tracker.ITestManagementService
date
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/DateTool.html
math
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/MathTool.html
number
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/NumberTool.html
esc
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/EscapeTool.html
alternator
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/AlternatorTool.html
lists
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ListTool.html
sorter
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/SortTool.html
mill
http://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/IteratorTool.html
All of the following are also available in "Lucene + Velocity" and "SQL + Velocity" queries.
renderingContext
com.polarion.alm.shared.api.model.rp.widget.RichPageRenderingContext in Page Script
com.polarion.alm.shared.api.model.rp.widget.RichPageWidgetRenderingContext in other cases
widgetContext
Synonym for renderingContext.
Not available in Page Script.
pageContext
java.util.Map<Object, Object>
Not available in details.vm and parameters.vm.
parameters
com.polarion.alm.shared.api.utils.collections.ReadOnlyStrictMap<String, ? extends com.polarion.alm.shared.api.model.rp.parameter.RichPageParameter>
Not available in details.vm and Page Script.
pageParameters
com.polarion.alm.shared.api.utils.collections.ReadOnlyStrictMap<String, ? extends com.polarion.alm.shared.api.model.rp.parameter.RichPageParameter>
Not available in details.vm and parameters.vm.
scriptedPageParameters
com.polarion.alm.shared.api.utils.collections.StrictMap<String, ? extends com.polarion.alm.shared.api.model.rp.parameter.RichPageParameter>
Available only in Page Script.
urlParameters
com.polarion.alm.shared.api.utils.collections.ReadOnlyStrictMap<String, String>
Not available in details.vm and parameters.vm.
page
current page: com.polarion.alm.shared.api.model.rp.RichPage
Available for stand-alone pages. Not available in details.vm and parameters.vm.
plan
current Plan object: com.polarion.alm.shared.api.model.plan.Plan
Available only on Plans that use Rich Page technology.
testRun
current TestRun object: com.polarion.alm.shared.api.model.tr.TestRun
Available only on Test Runs that use Rich Page technology.
object
current object: com.polarion.alm.shared.api.model.ModelObject
Reference to a Plan or Page (dependent on context).
factory
com.polarion.alm.shared.api.model.rp.parameter.ParameterFactory
Available in parameters.vm and Page Script.
Derived Field accessors in the Polarion Rendering API are prefixed with an underscore. The Velocity parser cannot deal with such methods, but will accept the method name without a
leading underscore or parentheses, i.e., $transaction.userGroups.getBy.id('someId').fields.users.size works while
$transaction.userGroups.getBy.id('someId').fields._users.size does not.
All of the above mentioned examples can be used. Just replace $!scriptedPageParameters with $!parameters
Example combining DataSetParameter with FieldsParameter and SortingParameter. (The way they are used in the Table widget.)
There is a set of predefined Velocity macros that can be used in Script widgets.
#message("some plain text")
#info("something")
Info: something
#warning("something")
Warning: something
#error("something")
Error: something
Load CSS
#loadCss("http://mywebsite.com/myCSS.css")
1. Set up the initial java script configuration to associate part or all of the widget with the Work Item Properties sidebar. This should be done at the beginning of the rendering
process and is accomplished by using com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguration
2. Set up the configuration to have the Work Item Properties sidebar open on click during the rendering of each individual item. This is done by adding html attributes to the
elements where the item is rendered by using com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguredContainer
13.1 The HTML attributes configured on a Work Item so that the Work Items sidebar is displayed
Path to the item (for Work Items: project id/work item id):
com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguredContainer.Attributes.referencePath()
Css class for styling before clicking:
com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguredContainer.Attributes.clickableCssClass()
Css class for highlighting the item once the sidebar is open:
com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguredContainer.Attributes.highlightingCssClass()
(Optional) Attribute for associating the list of fields displayed in the sidebar for a group of Work Items:
com.polarion.alm.shared.api.model.rp.widget.PropertiesSidebarConfiguredContainer.Attributes.fieldsConfigurationKey().
See "13.2 Showing Different Fields for Different Groups of Work Items". for more details.
Example:
For the Work Items Board Widget (that has a structure with Swimlanes that contain User Stories and Cards that contain Implementation tasks or Issues), you might want to show a
different set of fields in the sidebar:
For example:
Note: The different field lists can be read from different widget field parameters.
You can customize the appearance of the Cards by adding custom velocity snippets. You can change the color of the card, remove the status border color, show different Work Item
fields, re-arrange the fields already rendered and more. The custom Velocity scripts will be rendederd instead of the default Java scripts.
Default Velocity snippets are included with the widget under the Board Script and Card Script parameters and are a great starting point.
(The sample scripts mimic the java rendered output out of the box.)
First, set the Enable Customization widget parameter to "Yes". The Board Script and Card Script parameters appear below.
The Board Script is inserted at the beginning of the board and should always be used to add custom css styles and/or Java script common for all your Cards.
Warning: The styles inserted in this script are applied to the whole page.
The Card Script defines the content that appears within the cards. The Card Script Velocity script option allows for the following additional objects:
You can always revert to using the internal Java rendering by setting Enable Customization to "No".
Here are a few examples on how to customize the look and content of your Kanban board's Cards:
14.1 Examples
3. Click on Advanced at the bottom and click Yes under Enable Customizations.
4. Click on Board Script. (For a full screen view of the script hit F11. Hit Esc to exit full screen view.)
The only changes to the default "Board Script" are the bold lines in the example below:
...
.kanbanWorkItemDiv {
padding: 7px 3px 3px 7px;
box-sizing: border-box;
border-left: 5px solid;
border-right: 1px solid #EEEEEE;
border-top: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
border-radius: 5px;
position: relative;
background-color: #d0d2e0;
}
...
.kanbanWorkItemTitleGradientDiv {
bottom: 0px;
height: 12px;
left: 0;
position: absolute;
width: 100%;
display: inline-block;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #d0d2e0) repeat scroll 0 0 rgba(0, 0, 0, 0);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00FFFFFF', endColorstr='#FFFFFFFF', GradientType=0);
}
...
.polarion-sidebar-highlight .kanbanWorkItemDiv {
background-color: #fff9e8;
}
...
8. Click Apply.
You can customize what content appears within the cards in Card Script.
3. Click on Advanced at the bottom and click Yes under Enable Customizations.
4. Click on Card Script. (For a full screen view of the script hit F11. Hit Esc to exit full screen view.)
5. Paste the bold table text below under the <div class="kanbanWorkItemDiv" style="border-left-color: $wiStatusColor;"> tag.
6. Click Apply.
...
<div class="kanbanWorkItemDiv" style="border-left-color: $wiStatusColor;">
<table width="100%">
<tbody>
<tr>
<td class="kanbanWorkItemTitleDiv">
<div class="kanbanWorkItemTitleGradientDiv"></div>
<a href="$wiLink" target="_top">$workItem.fields().title().render()</a>
</td>
#set($treeLink =
$transaction.context().createPortalLink().project("$wiProjectId").workItems().query("id:$workItem.getReference().id()").toEncodedRelativeUrl())
#set($suffix = '&tree_depth=2&tab=tree')
<td style="vertical-align: top;">
<a href="$treeLink$suffix" target="_blank">
<img style="float: right;" title="View Item in a Tree Structure" src="/polarion/ria/images/details/treetable.gif"/>
</a>
</td>
</tr>
</tbody>
</table>
<table class="kanbanWorkItemTable">
...
6. A tree icon with a link to the card's Work Item in Tree view is added to the card.
15 F.A.Q
A: In Velocity: $page.reference.projectId
Q: What to do when HTML table exported to PDF loses styles and/or there are no columns?
A: PDF export requires that HTML tags <tr>, <th> and <td> are closed with </tr>, </th> and </td>.