> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Velocity Templates

> Nextedy RISKSHEET uses Apache Velocity templates for dynamic server-side rendering of the top panel, PDF export scripts, and configuration values.

export const LastReviewed = ({date}) => {
  if (!date) return null;
  const formatted = new Date(`${date}T00:00:00Z`).toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
    timeZone: "UTC"
  });
  return <p className="mt-10 text-sm text-gray-400 dark:text-zinc-500 not-prose">
      Last reviewed on {formatted}
    </p>;
};

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/yWl5nA2D0IzEnZC1/risksheet/diagrams/reference/templates/velocity-templates/diagram-1.svg?fit=max&auto=format&n=yWl5nA2D0IzEnZC1&q=85&s=e54884f418d385aa5fbb220151f0e29b" alt="diagram" style={{ maxWidth: "480px", width: "100%" }} width="480" height="370" data-path="risksheet/diagrams/reference/templates/velocity-templates/diagram-1.svg" />
</Frame>

## Template Files

| File                    | Purpose                                                               | Endpoint         | Required |
| ----------------------- | --------------------------------------------------------------------- | ---------------- | -------- |
| `risksheetTopPanel.vm`  | Renders customizable HTML panel above the Risksheet grid              | `/api/panel`     | No       |
| `risksheetPdfExport.vm` | Generates JavaScript export script for PDF generation                 | `/api/pdfscript` | No       |
| sheet configuration     | Primary sheet configuration (supports Velocity expressions in values) | `/api/config`    | Yes      |

## Template Resolution Properties

Templates are loaded from document attachments with fallback to the template hierarchy. The resolution mechanism tracks where the configuration was found using these properties:

| Property       | Type      | Default                               | Description                                                                                                                                                                                                      |
| -------------- | --------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`       | `string`  | File name (e.g., sheet configuration) | Name of the sheet configuration attachment to load from the Polarion document. If not found on the document, the system searches the document's template hierarchy.                                              |
| `fromTemplate` | `boolean` | `false`                               | Flag indicating whether the configuration was loaded from a template document rather than the target document itself. Set to `true` when configuration is inherited from a template module.                      |
| `configPath`   | `string`  | None                                  | URI path to the configuration attachment that was actually loaded, whether from the document itself or from a template. Used for debugging and configuration source tracking.                                    |
| `templateName` | `string`  | None                                  | Display name of the template document from which configuration was inherited. Includes project name prefix if template is from a different project. Empty if configuration is directly attached to the document. |
| `fileName`     | `string`  | None                                  | Path and name of the document where configuration was requested (not necessarily where it was found). Formatted as `folder/documentTitle`.                                                                       |
| `revision`     | `string`  | None                                  | Data revision identifier of the cached configuration attachment. Used to invalidate cache when attachment content changes.                                                                                       |

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/yWl5nA2D0IzEnZC1/risksheet/diagrams/reference/templates/velocity-templates/diagram-2.svg?fit=max&auto=format&n=yWl5nA2D0IzEnZC1&q=85&s=081c4d1b01f6502d9537eff970f8e2f8" alt="diagram" style={{ maxWidth: "620px", width: "100%" }} width="620" height="100" data-path="risksheet/diagrams/reference/templates/velocity-templates/diagram-2.svg" />
</Frame>

<Tip title="Template inheritance reduces duplication">
  Define templates once at the template document level. All documents created from that template inherit the Velocity templates automatically. Override individual templates by attaching a file with the same name directly to a specific document.
</Tip>

## Velocity Context Variables

All Risksheet Velocity templates receive a context containing Polarion services, document objects, and utility tools. The available context variables depend on the template type.

### Common Context (All Templates)

| Variable             | Type                   | Description                                                                               |
| -------------------- | ---------------------- | ----------------------------------------------------------------------------------------- |
| `$document` / `$doc` | Polarion Module object | Current Polarion document (module) with access to metadata, custom fields, and work items |
| `$repositoryService` | Polarion service       | Access to Polarion repository operations for querying projects, documents, and work items |
| `$transaction`       | Polarion transaction   | Current database transaction for read/write operations within the template                |
| Velocity Tools       | Utility objects        | Standard Velocity utility tools for formatting, math, and string operations               |

### Top Panel Template Context (`risksheetTopPanel.vm`)

The top panel template renders at the `/api/panel` endpoint and has full access to the common Velocity context plus:

| Additional Context        | Description                                         |
| ------------------------- | --------------------------------------------------- |
| Document custom fields    | Access via `$doc.getOldApi().getValue("fieldId")`   |
| Project configuration     | Available through `$repositoryService`              |
| Polarion tracker services | Query work items and links from within the template |

Errors in the top panel template render as a red error message box in place of the panel content, displaying the exception details.

### PDF Export Template Context (`risksheetPdfExport.vm`)

The PDF export template renders at the `/api/pdfscript` endpoint and includes additional context:

| Additional Context   | Type            | Description                                                                             |
| -------------------- | --------------- | --------------------------------------------------------------------------------------- |
| `pdfExportMacros.vm` | Velocity macros | Helper macros for PDF-specific formatting and layout operations                         |
| `revision` parameter | `string`        | Required document revision identifier for the export. Must be specified in the request. |

See [PDF Export Template](/risksheet/reference/templates/pdf-export-template) for detailed template structure and macro reference.

## Velocity Syntax Reference

### Variables and Properties

```velocity theme={null}
## Access a simple variable
$variableName

## Access a nested property
$document.customFields.productFamily

## Access via method call (required for some Polarion APIs)
$doc.getOldApi().getValue("customFieldID")

## Quiet reference (no output if variable is null)
$!{variableName}
```

### Directives

```velocity theme={null}
## Set a variable
#set($myVar = "value")

## Conditional rendering
#if($condition)
  content when true
#elseif($otherCondition)
  alternative content
#else
  default content
#end

## Iteration over a collection
#foreach($item in $collection)
  $item.name ($velocityCount of $collection.size())
#end

## Include another template
#parse("included-template.vm")
```

### Embedding JavaScript in Velocity

A key pattern in Risksheet templates is bridging server-side Polarion data to client-side JavaScript logic. The Velocity template executes on the server and generates HTML/JavaScript that runs in the browser:

```velocity theme={null}
## Extract document-level custom field on the server
#set($productFamily = $doc.getOldApi().getValue("productFamily"))
#set($projectId = $document.projectId)

<script>
  // Server-rendered values become client-side JavaScript variables
  var productFamily = "$productFamily";
  var projectId = "$projectId";

  // Register a queryFactory in the named map. The engine looks factories
  // up by name; a column references one via typeProperties.queryFactory.
  window.risksheet = window.risksheet || {};
  window.risksheet.queryFactories = window.risksheet.queryFactories || {};
  window.risksheet.queryFactories["filterByProductFamily"] = function(info) {
    return "customFields.productFamily:" + productFamily;
  };
</script>
```

<Warning title="String escaping in JavaScript blocks">
  When embedding Velocity variables into JavaScript strings, ensure the variable values do not contain characters that would break JavaScript syntax (quotes, backslashes, newlines). Use `$esc.javascript($value)` if the Velocity EscapeTool is available, or validate that custom field values contain only safe characters.
</Warning>

## PDF Export Configuration Properties

The PDF export configuration service manages loading of the `risksheetPdfExport.vm` template:

| Property                 | Type      | Default                 | Description                                                                                                                                                      |
| ------------------------ | --------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `risksheetPdfExport.vm`  | `string`  | `risksheetPdfExport.vm` | Name of the Velocity template file containing PDF export configuration. Attached to Polarion documents to customize PDF export behavior per document or project. |
| `pdfExportConfiguration` | `string`  | None                    | The full content of the PDF export Velocity template as a string. Contains the script/configuration that controls how Risksheet data is exported to PDF format.  |
| `templateName`           | `string`  | None                    | Name of the template used for PDF export configuration. Set when the configuration is loaded from a template.                                                    |
| `fromTemplate`           | `boolean` | `false`                 | Flag indicating whether the PDF export configuration was loaded from a template rather than directly from a document attachment.                                 |
| `configPath`             | `string`  | None                    | File system or repository path to the sheet configuration. Indicates where the PDF export configuration Velocity template is stored.                             |
| `fileName`               | `string`  | None                    | Name of the sheet configuration. Used to track which file contains the PDF export configuration.                                                                 |

## Project Template Installation

Risksheet ships with predefined project templates that can be installed via the administration interface:

| Template ID              | Description                         | Use Case                                                                                       |
| ------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------- |
| `risksheet_template`     | Standard Risksheet project template | General FMEA risk analysis with default column layout and severity/occurrence/detection scales |
| `risksheet_templateHara` | HARA-specific project template      | Hazard Analysis and Risk Assessment (HARA) workflows per ISO 26262                             |

### Installation Properties

| Property               | Description                                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Installation endpoint  | `POST /admin/setup`                                                                                                      |
| Duplicate detection    | System automatically checks if `risksheet_template` is already installed before attempting installation                  |
| Overwrite behavior     | Re-installing templates deletes existing template data first, then uploads fresh versions                                |
| Transaction safety     | Installation is wrapped in database transactions with automatic rollback on failure                                      |
| Environment detection  | Automatically detects development vs. production environment and loads template files from appropriate locations         |
| Multi-template support | Template ZIP files can contain multiple templates, each identified by a `template.properties` file in its directory root |

<Warning title="Template overwrite protection">
  Re-installing templates overwrites previous versions completely. The system removes old template data before uploading new versions to ensure a clean state. Back up any customizations made to installed templates before re-running setup.
</Warning>

## Runtime Configuration Properties

When templates are loaded at runtime, the application exposes version and configuration metadata through the window context:

| Property          | Type      | Source                      | Description                                                                                                   |
| ----------------- | --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `version`         | `string`  | `risksheet.version`         | Full version string of the Risksheet application including build metadata                                     |
| `shortVersion`    | `string`  | `risksheet.shortVersion`    | Shortened version identifier without build metadata for display                                               |
| `baseUrl`         | `string`  | `risksheet.baseUrl`         | Base URL for the Risksheet application, used to construct API endpoints                                       |
| `projectId`       | `string`  | `risksheet.projectId`       | Polarion project identifier used in API endpoint construction                                                 |
| `revision`        | `string`  | `risksheet.revision`        | Document revision identifier; empty string indicates head revision, non-empty forces read-only mode           |
| `currentRevision` | `string`  | `risksheet.currentRevision` | Latest revision number of the document                                                                        |
| `canAdmin`        | `boolean` | `risksheet.canAdmin`        | Whether the current user has administrative privileges to modify configuration                                |
| `configEditUrl`   | `string`  | Constructed                 | URL to the Risksheet configuration editor: `${baseUrl}/risksheet/configuration/`                              |
| `documentUrl`     | `string`  | Constructed                 | Direct URL to the source Polarion document in the standard Polarion UI                                        |
| `source`          | `string`  | Configuration               | Path to configuration source file (document or template) used to load the current configuration               |
| `templateName`    | `string`  | Configuration               | Name of the template when configuration is loaded from a global template rather than document-specific config |

## Error Handling

| Error Type                                                  | Template   | Behavior                                                                                                        |
| ----------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------- |
| Velocity syntax error                                       | Top panel  | Error details rendered as red HTML message box in the panel area                                                |
| Velocity syntax error                                       | PDF export | Export fails with error message in the export output                                                            |
| Missing template variable                                   | All        | Empty string rendered (Velocity default quiet reference behavior)                                               |
| Template file not found                                     | Top panel  | Default empty panel displayed                                                                                   |
| Template file not found                                     | PDF export | Export uses default behavior or fails gracefully                                                                |
| Runtime exception (e.g., `StringIndexOutOfBoundsException`) | All        | Red error message box with exception details; typically caused by misconfigured template or sheet configuration |
| `UnsupportedOperationException` for `renderingLayouts`      | All        | Non-functional log error; fixed in Risksheet 24.7.0+                                                            |

<Tip title="Debugging template errors">
  When a Velocity template error occurs, the error message is rendered directly in the panel or export output. Check the Polarion server logs for the full stack trace. Common causes include misconfigured `risksheetTopPanel.vm` files and references to document custom fields that do not exist.
</Tip>

## Complete Example

A top panel template that extracts a document custom field and registers a `queryFactory` function for filtering linked items by product family:

```velocity theme={null}
## risksheetTopPanel.vm
## Extract document-level custom fields using Polarion API
#set($productFamily = $doc.getOldApi().getValue("productFamily"))
#set($riskOwner = $doc.getOldApi().getValue("riskOwner"))
#set($projectName = $document.projectId)

<div class="risksheet-top-panel" style="padding: 8px; background: #f5f5f5; border-bottom: 1px solid #ddd;">
  <span><strong>Product Family:</strong> $!{productFamily}</span>
  <span style="margin-left: 16px;"><strong>Risk Owner:</strong> $!{riskOwner}</span>
  <span style="margin-left: 16px;"><strong>Project:</strong> $projectName</span>
</div>

<script>
  // Bridge server-side document data to client-side queryFactory
  var _productFamily = "$!{productFamily}";

  // Register queryFactory for filtering linked items by product family
  window.risksheet = window.risksheet || {};
  window.risksheet.queryFactories = window.risksheet.queryFactories || {};
  window.risksheet.queryFactories["filterByFamily"] = function(item) {
    if (_productFamily) {
      return "customFields.productFamily:" + _productFamily;
    }
    return "";
  };
</script>
```

This pattern demonstrates:

1. Accessing document custom fields with `$doc.getOldApi().getValue()`
2. Rendering server-side data into HTML for display
3. Passing server-side values to client-side JavaScript variables
4. Registering a `queryFactory` function that uses document-level context to filter which items are available for linking in Risksheet columns

A column references the registered factory by name through its `typeProperties.queryFactory` property in the sheet configuration:

```yaml theme={null}
columns:
  - bindings: linkedRequirement
    header: Linked Requirement
    type: itemLink
    typeProperties:
      queryFactory: "filterByFamily"
```

## See Also

* [Top Panel Template](/risksheet/reference/templates/top-panel-template) -- detailed reference for `risksheetTopPanel.vm` structure and customization
* [PDF Export Template](/risksheet/reference/templates/pdf-export-template) -- detailed reference for `risksheetPdfExport.vm` and export macros
* [Custom Renderer Templates](/risksheet/reference/templates/custom-renderers) -- client-side JavaScript cell renderers for custom column display
* [Velocity Template Context](/risksheet/reference/api/velocity-context) -- complete reference for available context variables and services
* [Configuration Properties Index](/risksheet/reference/configuration/properties-index) -- all sheet configuration properties
* [Template Path Configuration](/risksheet/reference/configuration/template-path-configuration) -- configuring document template paths

<LastReviewed date="2026-06-24" />
