Show only results for:












Toolkit Administration Guide

Welcome to the administration guide for UPV Toolkit. This guide provides detailed instructions for managing the application efficiently.

License

The License Management section allows administrators to manage the application’s license key. This ensures compliance and enables access to application features. All license keys are granted by CAXperts.

Features

1. License Key Input

  • Provides a secure interface to input or update the license key.

  • Dynamically toggles between masked and unmasked views for the license key by using the Eye icon to the right of the textbox.

License input masking

2. Validation and Feedback

  • Displays toast notifications to confirm successful updates.

  • Ensures that the provided license key is valid and up-to-date.

  • If the license key is invalid, an error notification is displayed, and the following screen is shown.

Invalid License

License Management Actions

View and Edit License Key

  1. Navigate to the License page.

  2. The current license key is preloaded in the input field upon page load.

  3. To update the license key:

  • Enter the new key in the text field.

  • Use the Eye icon to toggle between masked and unmasked views of the key.

Submit the License Key

  1. After entering the new key, click the Upload button.

  2. The system performs the following actions:

  • Validates the license key.

  • Updates the license key for the project.

  • Displays a success notification confirming the update.

  1. Upon successful update, you are redirected to the Home page.

Roles

The Roles page serves as a placeholder for all roles available in the application. These roles are sourced from Keycloak and are used to populate dropdown selections within the system. This table does not control user permissions but ensures that all possible roles from Keycloak are listed for reference.

The roles page

Tips

  • Double-check role edits before pressing Enter to avoid accidental changes.

  • Deleted roles cannot be recovered—ensure confirmation before proceeding.

Keycloak User Synchronization

The Toolkit includes an automated synchronization system that keeps user accounts and their assigned roles in sync between Keycloak (the identity provider) and the application database.

How the Synchronization Works

  • Keycloak is the Source of Truth: The synchronization process treats Keycloak as the authoritative source for user roles and group assignments.

  • Automated Daily Sync: By default, the system runs a scheduled synchronization job every day at 3:00 AM (03:00).

  • What Gets Synchronized:

    • All users with email addresses in Keycloak are processed
    • User group memberships in Keycloak are compared with role assignments in the database
    • Missing roles are added to the database
    • Extra roles (present in database but not in Keycloak) are removed
    • User accounts are created or updated as needed

Configuration

The synchronization behavior can be customized using environment variables in your deployment configuration:

Enable/Disable Synchronization

ENABLE_CRON=true

Set this to true to enable the cron job system (including user synchronization). Set to false or leave empty to disable.

Customize Sync Schedule

KC_GROUP_SYNC_CRON=0 3 * * *

This variable controls when the user synchronization runs using standard cron expression syntax (5-field format):

  • Default: 0 3 * * * (runs daily at 3:00 AM)
  • Format: minute hour day-of-month month day-of-week
  • Examples:
    • 0 2 * * * — Run daily at 2:00 AM
    • 0 */6 * * * — Run every 6 hours
    • 0 0 * * 0 — Run weekly on Sunday at midnight
    • 30 1 * * 1-5 — Run weekdays at 1:30 AM

Note: The cron expression must be valid. If an invalid expression is provided, the system will default back to 0 3 * * * and log a warning.

Workflows

The Workflows page allows administrators to create, view, edit, delete and assign default workflows.

The workflows administration page

Overview

  • Workflows are assigned to specific punch items. They are used to define the steps that must be completed to resolve a punch.

  • The admin defines those steps and who is authorized to complete them.

  • When the workflow is successfully finished (once the last step is approved), and if the last step contains a coded step closeWorkflow(), the punchlist item is closed.

1. Workflow Navigation

  • The Workflow Management page displays a list of existing workflows and their details.

  • Admins can add new workflows or edit existing ones.

Navigating the workflow

2. Default Workflow Assignment

  • The Assign Default Workflow feature lets administrators designate or reassign the workflow that is automatically applied to new punch items.

  • This option is accessible by clicking on the Workflow Tools dropdown menu in the management pane.

Using the assign default workflow feature

3. Workflow Interface

  • Administrators can create a new workflow by clicking the Add Workflow button.

  • A popup prompts users to enter a unique workflow title.

Adding a new workflow
  • Once inside a new/existing workflow, the administrator can start adding steps using the Plus button in the top right of the page.

  • Once a step is added the different fields in the row can be edited by double clicking in the respective cell.

  • Step Number, Title, Description and Responsible Person are all mandatory fields and must be filled in otherwise an error will be thrown.

  • After making any changes, the Save button in the top right will become active and display a red background. Administrators can save their modifications by clicking this button.

  • The step number denotes the order in which the steps will need to be completed to successfully finish the workflow.

  • The workflow step can have different use actions: “None”, “Activity”, “Decision”.

    “None” does not require any interaction from a user.

    “Activity” requires the user to approve or disapprove the step with a button click.

    “Decision” requires the user to approve or disapprove with or without signature.

4. Workflow Columns

  • Workflow Visible Steps column specifies which workflow steps will be visible when the workflow step is pending. The cell accepts comma separated numbers that represent workflow steps.

  • Responsible Person column specifies who is authorized to approve or deny the workflow step. The roles that are shown are roles that are specified by admin in Keycloak Groups.

  • Forward Step ID column specifies what is the next workflow step when the pending step is approved.

  • Backward Step ID column specifies what is the next workflow step when the pending step is disapproved.

Note: The default behavior of the Forward Step ID and Backward Step ID columns can be overridden using Custom Code functions:

  • stepForwardJumpTo(stepNumber: number, message: string | null): Jumps to the specified step number and, if a message is provided, it is printed to the activity chat. This jump is treated as a success.
  • stepBackwardJumpTo(stepNumber: number, message: string | null): Jumps to the specified step number and, if a message is provided, it is printed to the activity chat. This jump is treated as a failure.

When used, these functions take priority over the Forward Step ID and Backward Step ID values defined in the workflow table.

5. Workflow Code

Allows users to define Custom Code that is run when workflow step is accepted or disapproved.

Before saving the code, it must be compiled with a mockup interface that does not influence original punch items. The admin can choose different punches for examplary compilation if they specify a number in “PunchlistID for compilation” field. If the compilation is successful the code can be saved.

Related Features:

  • Use Event Listeners to trigger actions based on workflow events (step acceptance, field changes, etc.)
  • Use Field Validators to enforce data validation rules before field values are saved

6. Workflow Email Message

Allows users to send an email with the provided html body to the specified responsible group in the workflow step.

Available Dynamic Variables:

  • Ticket Fields - Include any punch field value:

    ${Details["<field name>"]}

    Example: Pipe in Area System: ${Details["Area System"]} broken.

  • Ticket ID - Include the punch item ID:

    ${PunchItem}

    Example: Ticket #${PunchItem} requires attention.

  • Server Address - Include the application server URL:

    ${serverAddress}

    Example: View ticket at: ${serverAddress}/tickets/${PunchItem}

  • Current Date - Include formatted date using the Date() function:

    ${Date("format")}

    Common Date Formats:

    • ${Date("yyyy-MM-dd")} → 2025-12-01
    • ${Date("MM/dd/yyyy")} → 12/01/2025
    • ${Date("dd-MM-yyyy")} → 01-12-2025
    • ${Date("yyyy-MM-dd HH:mm:ss")} → 2025-12-01 14:30:00
    • ${Date("MMMM dd, yyyy")} → December 01, 2025

    Example: This notification was sent on ${Date("yyyy-MM-dd")}

Email Template Example:

<h2>Ticket Update Notification</h2>
<p>Dear Team,</p>
<p>Ticket <strong>#${PunchItem}</strong> has been updated.</p>
<ul>
  <li><strong>Status:</strong> ${Details["Status"]}</li>
  <li><strong>Priority:</strong> ${Details["Priority"]}</li>
  <li><strong>Area System:</strong> ${Details["Area System"]}</li>
  <li><strong>Date:</strong> ${Date("MMMM dd, yyyy")}</li>
</ul>
<p>
  <a href="${serverAddress}/tickets/${PunchItem}"
    >Click here to view the ticket</a
  >
</p>
<p>This is an automated notification from ${serverAddress}</p>

Note: Subject lines can also use dynamic variable replacement with the same syntax shown above.

Workflows Kanban

The Kanban Settings page allows administrators to configure the appearance of the Kanban cards that appear in the “Planning” section by selecting fields for the title, subtitle, and content zones. These settings impact how information is displayed within the Kanban view, enabling a tailored experience to suit specific workflows.

The workflows kanban settings page

Kanban Settings Actions

  • Purpose: Define what information appears on the Kanban cards for the title, subtitle, and content areas.

  • How to Use:

    • Open the drop-down menus for Title, Subtitle, and Content.

    • Select a field from the list of available options, which are fetched from the system’s punch details available fields.

Adjusting the fields
  • Each selection updates the Kanban card preview in real time, allowing you to instantly see how your choices affect the card layout. The preview is displayed to the right of the select boxes.

  • The values from the fields you select in the drop-down menus will automatically populate the corresponding sections of each individual Kanban card.

Utilizing the drop-down menus
  • After finalizing your selections, click the Save button.

  • A confirmation message will appear, notifying you that the settings have been saved successfully.

Punchlist Fields

The Punchlist Fields page allows administrators to add, configure and manage available punchlist fields effectively. These fields define how information is structured and displayed in punchlists, ensuring adaptability to various workflows and requirements.

Punchlist fields

Managing Punchlist Fields

Administrators can add, edit, delete, and reorder punchlist fields using the following actions:

Adding a New Punchlist Field

  1. Add a Field:
  • Click the Plus (+) button in the top right corner to add a new punchlist field.
  1. Fill in Field Details:

Fields are accessed by single-clicking on the respective cell.

  • Detail (Required): Enter the name of the punchlist field.

  • Type (Required): Select the field type. See options below.

    • dxTextBox: A textbox for user input of text data.
    • dxSelectBox: A dropdown select box allowing users to choose from predefined options. These options are specified by the administrator in the “Items” column.
    • dxDateBox: A date picker for selecting dates.
    • dxHyperLink: A hyperlink element that navigates to a user specified URL.
    • Breakline: Inserts a horizontal line to separate content sections in punchlist user form.
  • Additional Options:

  • Column Span: Specify the number of columns this field should occupy on the punch item’s detail page.

  • Default View: Choose whether this field should be displayed by default in the main punchlist table.

  • Items (for Selectbox): If the type is Selectbox, specify the available options in the Items column.

  • Editors: Grant the selected roles permission to edit the specified field. The field will be in a read-only state for roles not included in this option.

Making a field read-only
  1. Save or Revert:
  • Save: Click the Save button at the end of the row to save the new field.

  • Revert: Click the Revert button to discard the new entry.

Editing an Existing Punchlist Field

  • Click the Pencil icon at the end of the row corresponding to the field you wish to edit.

  • Modify the necessary details.

  • Click Save to apply changes or Revert to cancel.

Deleting a Punchlist Field

  • Click the Trash icon at the end of the row for the field you want to delete.

  • Warning: Deleted fields cannot be recovered. Confirm the deletion when prompted.

Reordering Punchlist Fields

  • Drag and Drop:

  • Click and hold the Six-Dot icon (⋮⋮) to the left of a row.

  • Drag the row to your desired position within the table.

  • Release to drop the row in the new position.

  • The order of the rows in the table defines the order in which the fields appear in the punchlist user form.

Re-ordering fields

Attribute Mapping

The Attribute Mapping section enables administrators to define relationships between ticket detail fields and model attributes. These mappings are applied to the comments of ticket items that are created using the “Create with Comment” option in main tickets table.

The attributes mapping page

Features

1. Mapping Interface Overview

  • Punch Details List: Displays un-mapped ticket details available for mapping.

  • Mapped Attributes List: Lists existing mappings with details such as the mapped attribute(s) and type (2D, 3D, or Code).

2. Mapping Actions

Add Detail to Mapping

  1. Click the “+” button to move the detail to the mapped attributes list.

  2. The detail is now ready to be mapped to an attribute.

  3. Select up to 3 ticket details to generate a custom ticket comment.

Adding detail to mapping

Map Attribute to Detail

  • In the Mappings pane click the Edit button of the field you would like to map an attribute to.

  • This will open a pop-up that has options to either map to a 3D, 2D or custom code attribute.

  • Click on any of these options to choose a mapping type:

    • 3D Single Mapping: Map the field to a 3D attribute. A list is available for the administrator to select from which contains all possible model attributes.

    • 2D Single Mapping: Map the field to a 2D attribute. These attributes can be user-defined in the textbox.

    • Code Mapping: Map the field using a Custom Code

  • Save changes to finalize the mapping.

Editing map attribute

Creating a ticket with the option “Create with Comment” now reflect changes made with regards to attribute mapping:

Create with Comment

Delete Mapping

  • Click the Trash button next to a mapped attribute to remove the mapping.

  • The detail returns to the Ticket Details list for future use.

Event Listeners

The Event Listeners section provides administrators with tools to manage event-driven automation throughout the Toolkit application. Event listeners enable custom actions or behaviors triggered by specific conditions, such as field value changes, workflow actions, ticket creation, email sending, or scheduled intervals.

Unlike Field Validators which prevent invalid data from being saved, event listeners react to events after they occur, executing custom code to automate workflows, send notifications, update related fields, or trigger external integrations.

The event listener section

Understanding Listener Types

Each listener must have a Type that determines when and how it triggers. The listener’s required fields vary based on the selected type. Administrators must select the appropriate type and configure type-specific fields to create functional listeners.

Available Listener Types

1. onWorkflowAccepted

Description: Triggers when a specific workflow step is accepted by a user.

When it triggers: After a user approves/accepts a workflow step and the step status changes to “Accepted”.

Required Fields:

  • Type: onWorkflowAccepted
  • Checked Field: Step number (e.g., “1”, “2”, “3”)
  • Checked Value: “Accepted”
  • Workflow ID: The workflow this listener applies to
  • Custom Code: JavaScript code to execute when triggered

Use Cases:

  • Send notification when critical step is approved
  • Auto-populate fields after approval
  • Create comments or logs for audit trail

Example:

Type: onWorkflowAccepted
Checked Field: 3
Checked Value: Accepted
Workflow ID: 5
Custom Code: sendMailTo(["manager@example.com"], "Step 3 approved", "Workflow Progress")

2. onPunchlistDetail

Description: Triggers when a specific punch detail field value changes to a specified value.

When it triggers: After a ticket field is updated and the new value matches the specified CheckedValue.

Required Fields:

  • Type: onPunchlistDetail
  • Checked Field: Field name (e.g., “Status”, “Priority”)
  • Checked Value: The value that triggers the listener (e.g., “Closed”, “High”)
  • Workflow ID (or Default: true): Either specify a workflow or make it workflow-independent
  • Custom Code: JavaScript code to execute when triggered

Use Cases:

  • Notify team when status changes to “Closed”
  • Auto-populate related fields when priority is set
  • Trigger external API when specific conditions are met

Example:

Type: onPunchlistDetail
Checked Field: Status
Checked Value: Closed
Default: false
Workflow ID: 5
Custom Code: setTicketValue("ClosedDate", Date())

3. onTicketCreated

Description: Triggers when a new ticket is created.

When it triggers: Immediately after a new ticket is created in the system.

Required Fields:

  • Type: onTicketCreated
  • Default: Typically set to true (apply to all new tickets)
  • Custom Code: JavaScript code to execute when triggered (can include filtering logic)

Use Cases:

  • Auto-assign new tickets based on criteria
  • Set initial field values
  • Send creation notifications
  • Apply default workflows

Example:

Type: onTicketCreated
Default: true
Custom Code:
  const area = getTicketValue("Area");
  if (area === "Engine Room") {
    setTicketValue("AssignedTo", "engineering@example.com");
  }

4. onEmailSend

Description: Triggers when an interaction email is sent from the support ticket system, filtered by regex patterns matching the email subject and/or body content.

When it triggers: After an email is sent through the Interactions feature, if the email subject or body matches the specified regex patterns.

Required Fields:

  • Type: onEmailSend
  • Subject Regex: Regular expression pattern to match email subject (max 500 characters)
  • Content Regex: Regular expression pattern to match email body (max 500 characters)
  • Custom Code: JavaScript code to execute when triggered

Important Notes:

  • The system tracks processed emails using the ProcessedEmailListeners table to prevent duplicate triggers for the same email
  • Both regex fields are optional, but at least one should be specified for effective filtering
  • Regex patterns are case-sensitive unless specified otherwise in the pattern

Use Cases:

  • Track specific keywords in outgoing emails
  • Log emails containing certain phrases
  • Trigger actions based on email content (e.g., escalate tickets with “urgent” in subject)
  • Create audit trail for compliance

Regex Examples:

Match emails with “Invoice” in subject:

Subject Regex: Invoice
Content Regex: (leave empty or .*)

Match emails containing specific order numbers in body:

Subject Regex: .*
Content Regex: ORDER-\d{6}

Match urgent emails:

Subject Regex: (?i)(urgent|critical|emergency)
Content Regex: .*

Configuration Example:

Type: onEmailSend
Subject Regex: (?i)urgent
Content Regex: .*
Custom Code:
  setTicketValue("Priority", "High");
  sendMailTo(["manager@example.com"], "Urgent email detected", "Priority Escalation");

5. onTicketOverdue

Description: Triggers on a scheduled basis (cron job) for tickets that exceed a specified overdue threshold.

When it triggers: At the specified interval (cron schedule), checks all tickets and triggers for those whose age exceeds the overdue threshold.

Required Fields:

  • Type: onTicketOverdue
  • Interval: Cron expression defining when to check (e.g., “0 /6 * *” = every 6 hours)
  • Overdue: Time threshold in milliseconds (e.g., 86400000 = 24 hours)
  • Custom Code: JavaScript code to execute for each overdue ticket
  • Disabled: Should be false for the cron job to run

Important Notes:

  • Setting Disabled to true stops the cron job completely
  • The listener runs as a scheduled background job
  • Executes for each ticket that meets the overdue criteria

Common Interval Values:

  • * * * * * - Every minute (testing only)
  • 0 * * * * - Every hour
  • 0 */6 * * * - Every 6 hours
  • 0 0 * * * - Daily at midnight
  • 0 9 * * 1 - Every Monday at 9 AM

Common Overdue Values:

  • 3600000 - 1 hour
  • 86400000 - 24 hours (1 day)
  • 604800000 - 7 days (1 week)

Use Cases:

  • Send reminder notifications for overdue tickets
  • Escalate tickets that haven’t been updated
  • Auto-update priority for old tickets
  • Generate overdue reports

Configuration Example:

Type: onTicketOverdue
Interval: 0 9 * * *  (daily at 9 AM)
Overdue: 172800000  (48 hours)
Disabled: false
Custom Code:
  sendMailTo(
    [getTicketValue("AssignedTo")],
    "Ticket #" + getTicketValue("PunchItem") + " is overdue!",
    "Overdue Ticket Reminder"
  );

Special Configuration Fields

Default Flag

Type: Boolean (checkbox) Default Value: false

Purpose: The Default flag transforms workflow-dependent listeners into workflow-independent (global) listeners.

How it works:

  • Default = false: Listener only triggers for tickets assigned to the specified Workflow ID
  • Default = true: Listener triggers for ALL tickets regardless of workflow assignment, making it globally applicable

When to use Default = true:

  • Organization-wide automation that applies to all tickets
  • Global monitoring and notifications
  • Universal field updates based on conditions
  • System-wide audit logging

Examples:

Workflow-Specific Listener (Default = false):

Type: onPunchlistDetail
Checked Field: Status
Checked Value: Closed
Default: false
Workflow ID: 5
Custom Code: sendMailTo(["team@example.com"], "Project X ticket closed", "Notification")

→ Only triggers for tickets with Workflow ID = 5

Global Listener (Default = true):

Type: onPunchlistDetail
Checked Field: Status
Checked Value: Closed
Default: true
Workflow ID: (can be null)
Custom Code: setTicketValue("ClosedDate", Date())

→ Triggers for all tickets when Status changes to “Closed”, regardless of workflow

Disabled Flag

Type: Boolean (checkbox) Default Value: false

Purpose: The Disabled flag completely stops listener execution without deleting the configuration.

How it works:

  • Disabled = false: Listener is active and will trigger when conditions are met
  • Disabled = true: Listener is completely inactive and will never trigger, even if conditions are met

Special behavior for onTicketOverdue:

  • Setting Disabled = true stops the associated cron job
  • Setting Disabled = false starts/resumes the cron job

When to use Disabled = true:

  • Temporarily pause automation during maintenance
  • Disable problematic listeners while debugging
  • Seasonal or conditional listeners (enable/disable as needed)
  • Testing alternative implementations

Best Practice: Use Disabled instead of deleting listeners to preserve configuration for future use.

Listeners Table

The listeners table

The Listeners Table:

  • Displays all configured event listeners in a tabular format
  • Shows Type, Checked Field, Checked Value, Workflow, Default, Disabled, and other type-specific columns
  • Provides an interface to add, edit, and delete listeners
  • Integrates with punch workflows and punch details

Managing Event Listeners

Add a Listener

  1. Click the Add Row (+) button above the table

  2. Select the Type from the dropdown (required first step)

  3. Enter the type-specific required fields:

    • For onWorkflowAccepted: Checked Field (step number), Checked Value (“Accepted”), Workflow ID
    • For onPunchlistDetail: Checked Field (field name), Checked Value (trigger value), Workflow ID or Default
    • For onTicketCreated: Default (typically true)
    • For onEmailSend: Subject Regex and/or Content Regex
    • For onTicketOverdue: Interval (cron expression), Overdue (milliseconds)
  4. Configure special flags:

    • Default: Check to make listener workflow-independent (applies globally)
    • Disabled: Check to temporarily disable the listener
  5. Write Custom Code:

    • Click the Custom Code cell to open the code editor
    • Write JavaScript using available Custom Code functions
    • Test and save the code
  6. Press Enter or click the Save icon at the end of the row to save the new listener

Edit a Listener

  1. Click the Edit (pencil) icon on the listener row

  2. Modify any fields:

    • Change Type (note: required fields will change)
    • Update Checked Field/Value
    • Modify regex patterns for email listeners
    • Adjust Interval/Overdue for scheduled listeners
    • Toggle Default or Disabled flags
    • Update Custom Code
  3. Click Save to apply changes

Delete a Listener

  1. Click the Trash icon on the listener row

  2. Confirm deletion when prompted

Note: For onTicketOverdue listeners, deletion also stops the associated cron job.

Test a Listener

Before Activating:

  1. Configure the listener with Disabled = true
  2. Test the custom code using the Custom Code editor
  3. Verify the trigger conditions are correct
  4. Set Disabled = false to activate

Live Testing:

  1. Create or modify a ticket to match the trigger conditions
  2. Verify the listener executes (check logs, email notifications, field updates)
  3. Review any errors in the system logs

Custom Code Integration

Event listeners utilize the full Custom Code API. When a listener triggers, the custom code executes with access to:

  • All ticket fields via getTicketValue() and setTicketValue()
  • Workflow control functions like stepForwardJumpTo()
  • Communication functions like sendMailTo()
  • File operations like createPdfReport()
  • Utility functions like Date()

Important: Event listeners execute after the triggering event has already occurred and been saved to the database. They cannot prevent or block the event (unlike Field Validators).

Comparison: Event Listeners vs Field Validators

Feature Event Listeners Field Validators
Trigger Timing After event occurs (post-save) Before save (immediate)
Blocking Non-blocking (cannot prevent events) Blocks invalid changes
Purpose React to changes, automate actions Prevent invalid data entry
User Feedback Background execution, no immediate feedback Immediate error message in toast
Multi-field Support Single field per listener Multiple fields per validator
Execution Context Full Custom Code API Validation-specific helpers

When to use Event Listeners:

  • Send notifications when conditions are met
  • Auto-populate fields after changes
  • Trigger external integrations
  • Log events for audit trail
  • Schedule periodic checks

When to use Field Validators:

  • Enforce data format requirements
  • Validate business rules before saving
  • Prevent invalid field values
  • Cross-field validation
  • Role-based field restrictions

See Field Validators for detailed validation documentation.

Best Practices

Listener Design

  • Use descriptive naming in Custom Code comments
  • Test listeners thoroughly before deploying to production
  • Use Default = true sparingly (only for truly global automation)
  • Keep custom code focused and maintainable

Performance

  • Avoid heavy processing in frequently-triggered listeners
  • For onTicketOverdue, choose appropriate intervals (avoid overly frequent checks)
  • Consider using Disabled flag during high-load periods

Error Handling

  • Include error handling in custom code (try/catch blocks)
  • Test edge cases (null values, missing fields, etc.)
  • Monitor system logs for listener execution errors

Regex for Email Listeners

  • Test regex patterns before deploying
  • Use case-insensitive matching when appropriate: (?i)pattern
  • Escape special regex characters: \., \?, \+, etc.
  • Keep patterns under 500 characters

Workflow Integration

  • Document which workflows have listeners attached
  • Coordinate with workflow designers to avoid conflicts
  • Use Default flag consistently across related listeners

Custom Code

The Custom Code feature enables administrators to write JavaScript code that executes custom logic and automation throughout the Toolkit application. This powerful feature is used in multiple components:

  1. Workflow Steps - Execute actions when workflow steps are accepted or disapproved
  2. Email Message Templates - Generate dynamic email content with ticket data
  3. Punchfield Mapping - Transform attribute values during ticket creation
  4. Event Listeners - Automate actions triggered by specific events (see Event Listeners)
  5. Field Validators - Enforce custom validation rules on ticket fields (see Field Validators)

Security & Execution Environment

Custom code is run as JavaScript in a secured sandbox environment with the following protections:

  • Sandboxed Execution: Restricts access to internal system functions and prevents malware execution
  • Rate Limiting: 10 requests per minute per user to prevent abuse
  • Code Length Limit: Maximum 10,000 characters per code block
  • Dangerous Pattern Detection: Automatically blocks code containing SQL injection attempts, eval(), process access, and other security risks
  • Server-Side Execution: All custom code runs on the server, never exposing sensitive operations to the client

Available Objects

Custom code has access to the following predefined objects:

  • ActionResult: Enum containing workflow action results

    ActionResult = {
      Yes: "Yes",
      No: "No",
      Undefined: "Undefined",
    };
  • userAction.Result: Contains the result of the current workflow step action (ActionResult value)

  • language: String containing the current user’s language code (e.g., “en-US”, “ko”)

Usage example:

if (userAction.Result === ActionResult.Yes) {
  console.log("The step was approved");
  setStatus("Approved");
} else {
  console.log("The step was disapproved");
  setStatus("Rejected");
}

Available Functions

Ticket Management Functions

  • getPunchlistDetails() Returns an object containing all ticket field names and their current values.

    const details = getPunchlistDetails();
    console.log(details["Status"]); // "Open"
  • updatePunchlistDetails(data: Map<string, string>[]) Updates multiple ticket fields with new values. Takes an array of objects with Detail (field name) and Value properties.

    updatePunchlistDetails([
      { Detail: "Status", Value: "In Progress" },
      { Detail: "Assigned To", Value: "John Doe" },
    ]);
  • getTicketValue(fieldName: string) Returns the current value of a specific ticket field.

    const currentStatus = getTicketValue("Status");
  • setTicketValue(fieldName: string, value: any) Sets the value of a specific ticket field.

    setTicketValue("Priority", "High");
    setTicketValue("Due Date", Date("yyyy-MM-dd"));
  • createHiddenField(detail: any) Creates a field that is specific only to the current ticket item (not visible in field configuration).

    createHiddenField({ Detail: "InternalNotes", Value: "Auto-generated" });
  • setStatus(status: string) Sets the status of the current ticket to the specified value.

    setStatus("Closed");
  • closeWorkflow() Closes the current workflow and sets the ticket status to “Closed”.

    if (userAction.Result === ActionResult.Yes) {
      closeWorkflow();
    }

Workflow Control Functions

  • stepForwardJumpTo(stepNumber: number, message?: string) Jumps to the specified workflow step number as a success/forward action. If a message is provided, it is printed to the activity chat. This function overrides the Forward Step ID column value.

    // Jump to step 5 with a message
    stepForwardJumpTo(5, "Skipping steps 2-4 - auto-approved");

    Note: This function has priority over the default Forward Step ID column when utilized for workflows.

  • stepBackwardJumpTo(stepNumber: number, message?: string) Jumps to the specified workflow step number as a failure/backward action. If a message is provided, it is printed to the activity chat. This function overrides the Backward Step ID column value.

    // Jump back to step 1 with a message
    stepBackwardJumpTo(1, "Additional information required");

    Note: This function has priority over the default Backward Step ID column when utilized for workflows.

Communication Functions

  • sendMailTo(recipients: string[], message: string, subject: string, attachments?: any[]) Sends an email to the specified recipients with optional attachments.

    sendMailTo(
      ["user@example.com", "manager@example.com"],
      "Ticket #" + getTicketValue("PunchItem") + " has been approved.",
      "Ticket Approval Notification"
    );
    
    // With attachments
    sendMailTo(
      ["user@example.com"],
      "Please see attached report.",
      "Weekly Report",
      [reportPdfBuffer]
    );
  • createComment(message: string) Creates a comment on the current ticket.

    createComment("Automatically updated by workflow step 3");

File Operations Functions

  • createPdfReport(templateName?: string, ...params) Generates a PDF report using the configured template or specified template name. Additional parameters can be passed to customize the report.

    const reportBuffer = createPdfReport();
    // Or with specific template
    const customReport = createPdfReport("CustomTemplate", {
      includeImages: true,
    });
  • extractUpvf(fileName?: string) Extracts a UPVF file as a buffer. If no fileName is provided, extracts the ticket’s associated UPVF file.

    const upvfBuffer = extractUpvf();
    // Or specific file
    const specificFile = extractUpvf("project-model-v2.upvf");
  • deleteUpvf(fileID: number) Deletes a UPVF file by its ID.

    deleteUpvf(123);

Utility Functions

  • Date(formatString?: string) Returns the current date formatted according to the specified format string. Default format is “yyyy-MM-dd”.

    setTicketValue("CreatedDate", Date()); // "2025-12-01"
    setTicketValue("Timestamp", Date("yyyy-MM-dd HH:mm:ss")); // "2025-12-01 14:30:00"

Practical Examples

Example 1: Auto-populate fields based on status change

// When ticket is marked as "Closed", auto-populate closure date and notify team
if (getTicketValue("Status") === "Closed") {
  setTicketValue("ClosedDate", Date("yyyy-MM-dd"));
  setTicketValue("ClosedBy", language === "en-US" ? "System" : "システム");

  sendMailTo(
    ["team@example.com"],
    "Ticket #" + getTicketValue("PunchItem") + " has been closed.",
    "Ticket Closure Notification"
  );
}

Example 2: Conditional workflow jumps

// If priority is "Critical", skip review step and go directly to approval
const priority = getTicketValue("Priority");
if (userAction.Result === ActionResult.Yes && priority === "Critical") {
  stepForwardJumpTo(5, "Critical priority - skipping review step");
} else if (userAction.Result === ActionResult.Yes) {
  stepForwardJumpTo(3, "Moving to standard review");
}

Example 3: Cross-field updates

// When Area is selected, auto-populate System based on mapping
const area = getTicketValue("Area");
const areaSystemMap = {
  "Engine Room": "Propulsion",
  "Bridge": "Navigation",
  "Cargo Hold": "Cargo Handling",
};

if (areaSystemMap[area]) {
  setTicketValue("System", areaSystemMap[area]);
}

Example 4: Date calculations and validations

// Calculate and set due date to 7 days from now
const today = new Date();
const dueDate = new Date(today.setDate(today.getDate() + 7));
const formattedDueDate = dueDate.toISOString().split("T")[0];
setTicketValue("DueDate", formattedDueDate);

// Notify if ticket is overdue
const currentDueDate = new Date(getTicketValue("DueDate"));
if (currentDueDate < new Date() && getTicketValue("Status") !== "Closed") {
  sendMailTo(
    [getTicketValue("AssignedTo")],
    "Ticket #" + getTicketValue("PunchItem") + " is overdue!",
    "OVERDUE: Action Required"
  );
}

Example 5: Multi-language support

// Send notifications in user's language
const statusMessage =
  language === "ko" ? "티켓이 승인되었습니다" : "Ticket has been approved";

createComment(statusMessage);
sendMailTo(
  [getTicketValue("AssignedTo")],
  statusMessage,
  language === "ko" ? "티켓 승인" : "Ticket Approval"
);

Field Validators

The Field Validators section provides administrators with powerful tools to enforce custom business rules and data validation on ticket fields. Field validators trigger immediately when ticket detail values change, validating the new value before it is saved to the database.

Unlike Event Listeners which react to changes after they occur, field validators prevent invalid data from being saved in the first place. When a validator fails, the user receives an immediate error message via toast notification, and the field retains its previous value.

Field validators use Custom Code with specialized validation functions to enforce rules such as:

  • Data format requirements (uppercase, email format, regex patterns)
  • Business logic validation (date ranges, conditional requirements)
  • Cross-field dependencies (multi-field validation)
  • Role-based field restrictions (admins only, etc.)

Accessing Field Validators

To manage field validators:

  1. Navigate to Settings → Workflows → Validators in the administration menu
  2. Select the workflow you want to configure from the dropdown
  3. Field validators are workflow-specific - they only apply when the selected workflow is active on a ticket

Key Differences from Event Listeners

Feature Field Validators Event Listeners
Trigger Timing Before save (immediate, on field change) After save (event-driven)
Blocking Blocks invalid changes - prevents save Non-blocking - cannot prevent events
Purpose Prevent invalid data from entering system React to data changes with automation
User Feedback Immediate error message in toast notification Background execution, no immediate feedback
Multi-field Support Yes - one validator can validate multiple fields Single field per listener
Execution Context Validation-specific helper functions Full Custom Code API
Workflow Scope Workflow-specific (only when workflow is active) Can be workflow-specific or global (Default flag)

When to use Field Validators:

  • Enforce data format requirements (uppercase, email, phone numbers)
  • Validate business rules before saving (end date > start date)
  • Prevent invalid field values (negative numbers, invalid statuses)
  • Cross-field validation (if A then B is required)
  • Role-based field restrictions (only admins can set certain values)

When to use Event Listeners:

  • Send notifications when conditions are met
  • Auto-populate fields after changes
  • Trigger external integrations or workflows
  • Log events for audit trail
  • Schedule periodic checks

Validator Configuration

Validator Fields

When creating or editing a field validator, you configure the following:

  • Workflow - Select which workflow this validator applies to (required - validators are workflow-scoped)
  • Fields - Multi-select TagBox to choose one or more fields to validate
    • Single-field validation: Select one field (e.g., “Description”)
    • Cross-field validation: Select multiple fields (e.g., “Start Date” and “End Date”)
    • When multiple fields are selected, the validator runs whenever ANY of those fields change
  • Error Message - The message shown to the user when validation fails (max 500 characters)
    • Be specific and actionable (e.g., “End Date must be after Start Date”)
  • Active - Toggle to enable/disable the validator without deleting it
  • Order - Execution order (drag-and-drop to reorder)
    • Validators execute in ascending order
    • Lower numbers execute first
    • If any validator fails, subsequent validators still run (all errors are collected)
  • Custom Code - JavaScript validation logic that returns true (allow) or false (block)

Validator Execution Flow

When a user changes a ticket field value:

  1. Check for Active Workflows: System checks if the ticket has any active (non-closed) workflows assigned
  2. Find Applicable Validators: For each active workflow, system fetches all Active validators that include the changed field
  3. Execute in Order: Validators execute in ascending Order
  4. Collect Errors: If any validator returns false, its ErrorMessage is added to the error list
  5. Block or Allow:
    • All validators pass (return true): Change is saved to database
    • Any validator fails (return false): Change is BLOCKED, error messages shown in toast, field retains old value

Writing Validation Code

Field validator custom code must return a boolean value:

  • return true → Validation PASSES (allow save)
  • return false → Validation FAILS (block save, show ErrorMessage)

Validation-Specific Helper Functions

Field validators have access to specialized functions for validation context:

getCurrentFieldValue()

Returns: The value being validated (the new value the user is trying to save)

Usage:

// Ensure Description field is uppercase
return getCurrentFieldValue() === getCurrentFieldValue().toUpperCase();

getFieldValue(fieldName: string)

Args: fieldName - Name of any field in the ticket Returns: Current value of the specified field

Usage:

// Cross-field validation: End Date must be after Start Date
const startDate = new Date(getFieldValue("Start Date"));
const endDate = new Date(getCurrentFieldValue());
return endDate >= startDate;

getAllFields()

Returns: Object containing all field names and their current values

Usage:

// Multi-field business logic
const fields = getAllFields();
if (fields["Status"] === "Closed" && !fields["Resolution"]) {
  return false; // Error: "Resolution required for closed tickets"
}
return true;

hasRole(roleName: string)

Args: roleName - Name of the role to check Returns: true if current user has the specified role, false otherwise

Usage:

// Only admins can set Priority to "Critical"
if (getCurrentFieldValue() === "Critical") {
  return hasRole("Admin");
}
return true;

Available Context Variables

In addition to helper functions, the following variables are available directly in validation code:

  • currentValue - The field value being validated (same as getCurrentFieldValue())
  • fieldName - Name of the field being validated (e.g., “Description”, “Status”)
  • punchDetails - Object with ALL field values for the ticket (same as getAllFields())
  • userRoles - Array of current user’s role names (e.g., ["Admin", "Editor"])

Validation Examples

Example 1: Format Validation - Uppercase Only

Ensure a field only contains uppercase letters:

// Validation code for "Description" field
return getCurrentFieldValue() === getCurrentFieldValue().toUpperCase();

Error Message: “Description must be in uppercase letters only”

Example 2: Format Validation - Email Format

Validate email address format:

// Validation code for "Email" field
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(getCurrentFieldValue());

Error Message: “Please enter a valid email address”

Example 3: Cross-Field Date Validation

Ensure End Date is after Start Date:

// Validation code for "Start Date" and "End Date" fields (both selected)
if (fieldName === "End Date") {
  const startDate = new Date(getFieldValue("Start Date"));
  const endDate = new Date(getCurrentFieldValue());
  return endDate >= startDate;
}
return true; // For Start Date changes, allow (End Date validator will catch issues)

Error Message: “End Date must be on or after Start Date”

Example 4: Role-Based Validation

Only admins can set priority to “Critical”:

// Validation code for "Priority" field
if (getCurrentFieldValue() === "Critical") {
  return hasRole("Admin");
}
return true; // Allow all other priority values

Error Message: “Only administrators can set Priority to Critical”

Example 5: Conditional Required Field

Resolution is required when Status is “Closed”:

// Validation code for "Status" and "Resolution" fields (both selected)
const fields = getAllFields();

if (fieldName === "Status" && getCurrentFieldValue() === "Closed") {
  // When closing, Resolution must be filled
  return fields["Resolution"] && fields["Resolution"].trim() !== "";
}

if (fieldName === "Resolution" && fields["Status"] === "Closed") {
  // When status is already closed, Resolution cannot be empty
  return getCurrentFieldValue() && getCurrentFieldValue().trim() !== "";
}

return true;

Error Message: “Resolution is required when Status is Closed”

Example 6: Numeric Range Validation

Ensure Budget is within acceptable range:

// Validation code for "Budget" field
const budget = parseFloat(getCurrentFieldValue());

// Check for valid number
if (isNaN(budget)) {
  return false;
}

// Check range
return budget >= 0 && budget <= 1000000;

Error Message: “Budget must be between 0 and 1,000,000”

Example 7: Complex Multi-Field Business Logic

Validate project milestone dates and dependencies:

// Validation code for "Phase Start", "Phase End", "Project Status" fields
const fields = getAllFields();
const phaseStart = new Date(getFieldValue("Phase Start"));
const phaseEnd = new Date(getFieldValue("Phase End"));
const projectStatus = getFieldValue("Project Status");

// Validate date range
if (fieldName === "Phase End" || fieldName === "Phase Start") {
  if (phaseEnd <= phaseStart) {
    return false; // End must be after start
  }
}

// Cannot set status to "In Progress" without phase dates
if (
  fieldName === "Project Status" &&
  getCurrentFieldValue() === "In Progress"
) {
  if (!fields["Phase Start"] || !fields["Phase End"]) {
    return false;
  }
}

return true;

Error Message: “Phase End must be after Phase Start, and phase dates are required before starting the project”

Management Actions

Add a Validator

  1. Navigate to Settings → Workflows → Validators
  2. Select the target workflow from the dropdown
  3. Click the Add button (plus icon)
  4. Configure the validator:
    • Fields: Click the TagBox and select one or more fields to validate
    • Error Message: Enter a clear, specific error message
    • Active: Check to enable (default: true)
    • Order: Set execution order (default: 0)
    • Custom Code: Click to open the integrated code editor
  5. Write validation code:
    • Write JavaScript code that returns true (pass) or false (fail)
    • Use helper functions: getCurrentFieldValue(), getFieldValue(), getAllFields(), hasRole()
  6. Test the code:
    • Click Compile button to check syntax errors
    • Click Test button to run with sample data
    • Review any error messages
  7. Click Save in the code editor
  8. Click Save in the validator form to persist to database

Edit a Validator

  1. Locate the validator in the table
  2. Double-click the row OR click the Edit (pencil) icon
  3. Modify any fields:
    • Add/remove fields from the TagBox
    • Update error message
    • Toggle Active status
    • Change Order
    • Update Custom Code
  4. Re-test if code was changed (Compile/Test buttons)
  5. Click Save to apply changes

Delete a Validator

  1. Locate the validator in the table
  2. Click the Trash icon at the end of the row
  3. Confirm deletion in the dialog

Warning: Deleted validators cannot be recovered. Consider using Active = false instead to preserve configuration.

Reorder Validators

Execution order matters - validators execute in ascending Order:

  1. Locate the six-dot handle (⋮⋮) at the left of each validator row
  2. Click and drag the handle up or down
  3. Release to drop the validator in the new position
  4. The Order field updates automatically
  5. Validators now execute in the new order

Best Practice: Order validators from simple to complex:

  • Simple format checks first (fail fast)
  • Cross-field validations next
  • Complex business logic last

Testing Validators

Using the Integrated Code Editor

Before activating a validator, test it thoroughly:

  1. Syntax Check:

    • Click the Compile button
    • Review any syntax errors highlighted in red
    • Fix errors and compile again
  2. Test with Sample Data:

    • Click the Test button
    • The editor runs your code with sample field values
    • Review the console output
    • Verify return value is boolean (true or false)
  3. Review Error Messages:

    • Ensure your Error Message is clear and actionable
    • Test with invalid data to see the message

Live Testing

After saving a validator, test it with real tickets:

  1. Create or open a test ticket that has the configured workflow assigned

  2. Try to enter an invalid value in the validated field

  3. Verify the behavior:

    • Error message appears in toast notification at top of screen
    • Toast is red/error styled
    • Field retains its old value (change is blocked)
    • You cannot save the invalid value
  4. Try entering a valid value:

    • No error message appears
    • Field updates successfully
    • Value is saved to database
  5. Test edge cases:

    • Empty values
    • Null values
    • Boundary values (min/max)
    • Special characters
    • Very long strings

Debugging Validators

If a validator isn’t working as expected:

  1. Check the basics:

    • Validator is Active (checkbox checked)
    • Workflow is assigned to the ticket
    • Field name matches exactly (case-sensitive)
    • Field is included in the validator’s Fields list
  2. Review execution order:

    • Earlier validators might be blocking before yours runs
    • Check Order values and execution sequence
  3. Test the code in isolation:

    • Use Compile button to check syntax
    • Use Test button with sample data
    • Add console.log() statements for debugging
    • Check browser console for runtime errors
  4. Verify field names:

    • Field names in getFieldValue('FieldName') must match exactly
    • Check field configuration in Punchlist Fields section
    • Names are case-sensitive
  5. Test with simple code first:

// Simplest test - always fail
return false;

If this doesn’t show an error, there’s a configuration issue (not a code issue)

Best Practices

Error Messages

  • Be specific: “End Date must be after Start Date” not “Invalid date”
  • Be actionable: Tell users what they need to fix
  • Use examples: “Format: ABC-12345” or “Must be uppercase”
  • Keep it concise: Under 200 characters when possible
  • Avoid technical jargon: Write for end users, not developers

Validation Code

  • Keep it simple: Complex logic is harder to maintain and debug
  • Fail fast: Check simple conditions first (null, empty, format)
  • Handle edge cases: Check for null, undefined, empty strings
  • Use consistent return values: Always return boolean, never undefined
  • Comment your code: Explain business rules for future maintainers
  • Test thoroughly: Test with valid, invalid, null, and boundary values

Multi-Field Validators

  • Be explicit: Use fieldName to check which field triggered the validation
  • Validate both directions: If validating A against B, handle changes to both A and B
  • Consider order: Validators run for all included fields

Performance

  • Avoid heavy operations: Validators run on every field change
  • Don’t call external APIs: Validators must be fast and synchronous
  • Minimize getAllFields() calls: Call once and store result if needed multiple times
  • Consider validator count: Too many validators can slow down field updates

Organization

  • Use descriptive Order values: 10, 20, 30 instead of 1, 2, 3 (easier to insert new ones)
  • Group related validators: Use Order to keep related validations together
  • Document complex logic: Add comments explaining business rules
  • Review regularly: Outdated validators should be deactivated or deleted

Security

  • Never trust client data: Always validate on the server (validators run server-side ✓)
  • Use role-based validation: Restrict sensitive fields with hasRole()
  • Validate format strictly: Use regex for formats like email, phone, IDs
  • Prevent injection: Don’t use eval() or construct SQL queries in validators

Troubleshooting

Validator Not Triggering

Problem: Validator doesn’t execute when field changes

Solutions:

  1. Verify validator is Active (checkbox checked)
  2. Check that the workflow is assigned to the ticket
  3. Confirm workflow is not Closed (validators only run on active workflows)
  4. Verify field name matches exactly (case-sensitive)
  5. Check that field is in the validator’s Fields list
  6. Review Order - try setting to 0 to execute first

Custom Code Errors

Problem: Validator code throws runtime errors

Solutions:

  1. Use Compile button to check syntax errors
  2. Test with sample data before saving
  3. Check browser console for detailed error messages
  4. Verify field names in getFieldValue() calls are correct
  5. Handle null/undefined values:
const value = getCurrentFieldValue();
if (!value) return false; // Require non-empty
  1. Ensure you always return a boolean (true or false)

Validation Too Strict

Problem: Validator blocks valid data

Solutions:

  1. Review validation logic - may be too restrictive
  2. Test edge cases (empty, null, special characters)
  3. Consider role-based exceptions using hasRole()
  4. Update error message to clarify requirements
  5. Add logging to understand what values are being rejected:
console.log("Validating:", getCurrentFieldValue());

Validation Too Loose

Problem: Validator allows invalid data

Solutions:

  1. Review validation logic - may have loopholes
  2. Test with known invalid values
  3. Check for missing null/empty checks
  4. Ensure you’re returning false for invalid cases
  5. Verify regex patterns match your requirements

Cross-Field Validation Issues

Problem: Multi-field validation not working correctly

Solutions:

  1. Check which field triggered with fieldName variable
  2. Ensure both fields are included in the Fields list
  3. Handle validation for each field explicitly:
if (fieldName === "StartDate") {
  // Validate start date logic
}
if (fieldName === "EndDate") {
  // Validate end date logic
}
  1. Use getFieldValue() to get the other field’s value
  2. Consider creating separate validators for each field

Performance Issues

Problem: Field updates are slow when validators are active

Solutions:

  1. Reduce number of validators
  2. Simplify complex validation logic
  3. Remove unnecessary getAllFields() calls
  4. Avoid loops and recursion in validation code
  5. Consider combining multiple simple validators into one
  6. Use Disabled flag to temporarily pause validators during bulk updates

API Reference

For detailed information about all available Custom Code functions, see the Custom Code section.

Validation-specific functions:

  • getCurrentFieldValue() - Get value being validated
  • getFieldValue(fieldName) - Get any field value
  • getAllFields() - Get all field values
  • hasRole(roleName) - Check user role

Available variables:

  • currentValue - Value being validated
  • fieldName - Field being validated
  • punchDetails - All field values
  • userRoles - User’s roles array

Comment Configuration

The Comment Configuration section allows administrators to customize how comments are automatically generated when creating punch items using the “Create with comment” option. This feature enables a standardized naming convention for comments by selecting which punchlist detail fields should be included in the generated comment description.

Comment Generation

Overview

  • Comment Configuration controls the automatic generation of comment descriptions when punch items are created with associated comments.

  • Administrators can select up to three mapped punchlist detail fields to include in the comment description.

  • The selected fields determine how the comment will be named, following the format: “PI-[PunchID] : [Field1Value] : [Field2Value] : [Field3Value]”.

  • Only punchlist details that have been mapped in the Attribute Mapping section are available for selection.

  • The feature includes a toggle to enable or disable automatic comment generation entirely.

Features

1. Mapped Details Selection

The page displays all punchlist details that have been mapped to 3D attributes, 2D attributes, or custom code in the Attribute Mapping section.

  • Each mapped detail is shown with its name and mapping information (3D attribute, 2D attribute, or code mapping).

  • If no mapped details are available, the page prompts administrators to configure attribute mappings first.

2. Field Selection for Comments

Administrators select which fields to include in auto-generated comments:

  • Click the Check button next to a detail to add it to the comment configuration.

  • Up to 3 fields can be selected at once.

  • If you select a 4th field while 3 are already selected, the first selected field is automatically removed.

  • The order in which fields are selected determines their appearance order in the generated comment.

  • Fields can be deselected by clicking their Check button again.

3. Comment Preview

  • The Ticket Comment Preview section shows a live preview of how the selected fields will appear in the comment.

  • Fields are displayed in the format: “Field1-Field2-Field3”, separated by hyphens.

  • A counter shows how many fields are currently selected (e.g., “Selected: 2/3”).

  • If no fields are selected, the preview displays “No fields selected”.

4. Comment Generation Toggle

The Comment Generation Enabled checkbox controls whether automatic comment creation is active:

  • When enabled, punch items created with the “Create with comment” option will automatically generate comments using the configured field values.

  • When disabled, no automatic comments will be generated regardless of field selection.

  • This toggle updates immediately without requiring a save action.

Components

The Components section allows administrators to customize the available attributes and control default column visibility for the components table in the main punchlist details (Components tab).

Components Page

Features

  1. All available model attributes are displayed in the Available Model Attributes List. Click an attribute to move it from the Available Model Attributes list to the Selected Attributes list. Attributes in the Selected Attributes list are available as columns in the main components table.

  2. To remove an attribute, click it in the Selected Attributes list to move it back to the Available Model Attributes list.

  3. Four columns are permanent and cannot be removed: Type, UID, Bounding Box, and Drawing Name.

  4. Administrators also have the ability to set the default visibility of each selected attribute using checkboxes located at the end of each row.

  5. The visibility of the permanent columns can also be toggled as needed.

  6. This configuration is applied by default for a user accessing the application for the first time.

Components Page Actions

Disable Features

Navigate to Enabled Pages in Admin menu

View and Edit Hidden Routes

  1. Specify the route in 1st column of Toolkit Pages table as “/<route>” e.g. “/clashes”
  2. Specify with boolean if it is allowed to view the specified route with checkbox in 2nd column

View and Edit Punchlist Tabs Visibility and Order

  1. In the Punchlist Tabs table, administrators can toggle the Visible checkbox to control which tabs appear in the punchlist details section.
  2. They can also set the order of the tabs by dragging and dropping rows using the six dots to the left of each row.
Enabled Pages

Ticket Report Designer

The Ticket Report Designer page provides a powerful, fully-featured PDF template editor that allows administrators to create and customize professional reports for ticket items. Built on the open source PDFME playground editor, this tool offers complete control over report layout, fields, and styling.

Ticket Report Designer

Overview

  • Design custom PDF reports with a visual drag-and-drop interface
  • Map ticket detail fields to report elements
  • Support for text, images, tables, signatures, QR codes, and more
  • Real-time preview of report layouts
  • Save templates to the database for use when generating ticket reports
  • Load and modify existing templates or start from scratch

Features

1. Visual Template Designer

The embedded PDFME designer provides an intuitive interface for creating PDF report templates:

  • Drag-and-Drop Elements: Add text fields, images, shapes, tables, barcodes, QR codes, and signature fields to your template
  • Real-Time Preview: See exactly how your report will look as you design it
  • Page Management: Create multi-page reports with different layouts per page
  • Precise Positioning: Use pixel-perfect positioning and alignment tools
  • Zoom Controls: Adjustable zoom with a draggable zoom bar for detailed editing

2. Field Naming Convention

To populate report fields with actual ticket data, use the following naming conventions in the field “Name” property:

Regular Ticket Fields

Format: reportData.DetailName

Example: reportData.Tag No

  • References the “Tag No” field from the Ticket Fields configuration
  • Automatically populates with the value from the ticket’s details
  • Works with any custom field defined in the Punchlist Fields admin section

Screenshot Images

Format: Initial or Final

  • Initial — Displays the uploaded initial screenshot image
  • Final — Displays the uploaded final screenshot image
  • These fields should be added as image elements in the designer

Important: The field name must exactly match the Detail name as defined in the Punchlist Fields administration page (case-sensitive).

3. Base PDF Management

Change Base PDF

  • Upload a PDF file to use as the base template for your reports
  • The base PDF appears as a background, with dynamic fields overlaid on top
  • Useful for incorporating pre-designed features
  • File Requirements: Must be a valid PDF file

How to use:

  1. Click “Change Base PDF (must be PDF)” in the top navigation
  2. Select a PDF file from your computer
  3. The PDF pages become the background for your template
  4. Add dynamic fields on top of the base PDF

4. Template Management

Save Template

  • Click the “Save” button to save your current template design to the database
  • The saved template is used when generating reports for tickets
  • A success notification confirms when the template is saved
  • Templates persist across sessions and are available to all users

Load Template

  • Upload a previously saved template JSON file
  • Useful for importing templates created elsewhere or restoring backups
  • File Requirements: Must be a valid JSON file in PDFME format

How to use:

  1. Click “Load Template (must be JSON)”
  2. Select a JSON template file
  3. The designer loads the template for editing

Download Template

  • Export your current template as a JSON file
  • Use this to create backups or share templates
  • Click “DL Template” to download

Reset Template

  • Click the “Reset” button to clear the current template
  • Returns to a blank template with default settings
  • Warning: This action cannot be undone

Troubleshooting

Fields not populating with data

  • Verify the field name matches exactly (case-sensitive) with the Detail name in Punchlist Fields
  • Ensure the naming convention reportData.DetailName is used correctly
  • Check that the ticket has data in the specified field

Base PDF not displaying

  • Confirm the uploaded file is a valid PDF format
  • Check the PDF file size is reasonable (under 10MB recommended)
  • Verify the PDF is not password-protected or encrypted

Template not saving

  • Check browser console for error messages
  • Ensure you have administrator permissions
  • Verify database connectivity

Power BI

The Power BI section lets administrators manage embedded reports. Reports are grouped by type and configured in-app without modifying environment variables.

1.  One‑Time Azure & Power BI Setup

Azure Setup for Power BI Embedding

Follow these 7 steps to configure your Azure and Power BI environment. Once complete, no additional Azure changes are required — everything else is managed inside the app.

# Task What to Do
1 Register an Azure AD App Go to Azure PortalAzure Active DirectoryApp registrationsNew registration.
Save the Application (Client) ID and Directory (Tenant) ID.
No extra API permissions are needed.
2 Generate a Client Secret Go to Certificates & SecretsNew client secret.
Copy the value and store it securely (used as POWERBI_SECRET).
3 Enable Tenant Settings In Power BI ServiceAdmin PortalTenant Settings, enable:
▪ Embed content in apps
▪ Allow service principals to use Power BI APIs
Scope = Entire organization or a security group containing the service principal.
4 Add Service Principal to Workspace In each target workspace → AccessAdd member → search for the app name.
Set Role to Member or Admin.
5 Publish Reports Open Power BI Desktop and publish your .pbix file to the same workspace.
6 Provision Embedded Capacity Go to Azure PortalPower BI Embedded → choose a capacity tier (e.g., A1).
In Power BI workspace: SettingsPremium → assign the capacity.
7 (If report connects to Azure SQL) In SQL ServerNetworking → enable “Allow Azure services and resources to access this server”.

Once these steps are completed, your Azure environment is ready. All further actions are handled within the app.

2.  Server‑Side Environment Variables

  • Only three secrets live in the deployment environment (never in the UI):
POWERBI_TENANT_ID = <Directory / Tenant GUID>
POWERBI_CLIENT_ID = <Application / Client GUID>
POWERBI_SECRET = <Client Secret>
  • The application reads them through:
{
  authenticationMode: 'ServicePrincipal',
  authorityUrl: 'https://login.microsoftonline.com/',
  scopeBase: 'https://analysis.windows.net/powerbi/api/.default',
  tenantId:   process.env.POWERBI_TENANT_ID,
  clientId:   process.env.POWERBI_CLIENT_ID,
  clientSecret: process.env.POWERBI_SECRET,
}
  • Note: Authentication Mode must remain ServicePrincipal – this is the Microsoft‑recommended approach for App‑Owns‑Data embeds and avoids user consent pop‑ups.

3. Adding & Maintaining Reports inside the App

Use the Power BI UI page to:

Report Management Actions

Action Steps
Add a Report 1. Navigate to Admin › Power BI.
2. Click “+ Add Report”.
3. Enter: Report Name, Report ID, Workspace ID, and Type (copy GUIDs from Power BI Service URL).
4. Click Save – the app validates IDs by contacting Power BI.
Edit a Report Click ✎ (edit) → change values → Save.
Delete a Report Click 🗑 on the appropriate report to delete the report.
Create a Report Type Type a new value into the Report Type field when adding a report — it will be created automatically.
Delete a Report Type Click 🗑 next to a type to remove it and all its reports._
Hide / Show the Navbar Click « or » to collapse the left pane and view the report full‑width.
Power BI Page

LOTO Administration

The LOTO (Lockout/Tagout) administration section enables administrators to configure templates, metadata fields, and catalogue items that define how Lockout/Tagout work programs operate throughout the application.

Overview

The LOTO system provides a comprehensive framework for managing Lockout/Tagout work programs in industrial environments. Administrators configure:

  • Templates: Reusable step sequences for different work program types
  • Metadata Fields: Dynamic columns that appear in work program list tables
  • Catalogue Items: Placeable symbols and equipment types for P&ID drawings

Users leverage these configurations to create, execute, and track work programs with proper safety procedures and documentation.

LOTO Templates

Navigate to Settings → LOTO Settings to manage reusable templates that define step sequences for work programs.

What are LOTO Templates?

Templates are pre-configured sets of steps organized by phase (Preparation, De-commissioning, Repair, Commissioning) that can be applied to new work programs. They ensure consistency and best practices across similar work activities.

Template Management Actions

View All Templates

The Templates page displays all available templates in a table format with the following columns:

  • Template Name: Descriptive name for the template
  • Type: Category or classification (e.g., “Maintenance”, “Inspection”)
  • Description: Detailed explanation of the template’s purpose
  • Category: Grouping classification for organizing templates
  • Last Modified: Date of last modification
  • Last Modified By: User who last updated the template

Add a New Template

  1. Click the Add (+) button in the toolbar
  2. Enter the required fields:
    • Template Name: Unique identifier (required)
    • Type: Classification category
    • Description: Purpose and usage details
    • Category: Organizational grouping
  3. Click Save to create the template
  4. The template appears in the list and can now be opened to add steps

Edit Template Properties

  1. Click the Edit (pencil) icon on the template row
  2. Modify any field:
    • Template Name
    • Type
    • Description
    • Category
  3. Click Save to apply changes

Delete a Template

  1. Click the Trash icon on the template row
  2. Confirm deletion in the dialog
  3. Warning: Deleting a template does not affect work programs that were created using it. However, the template will no longer be available for new work programs.

Configure Template Steps

  1. Double-click a template row OR click the template name
  2. Navigate to the Template Steps page for that template

Template Steps Configuration

After selecting a template, administrators can configure the steps for each phase.

Phase Tabs

Template steps are organized into four phases:

  • Preparation: Initial setup and safety procedures
  • De-commissioning: Shutdown and isolation procedures
  • Repair: Maintenance or repair work activities
  • Commissioning: Startup and restoration procedures

Click each tab to view and edit steps for that phase.

Steps Table Columns

Column Description
Order Sequential number determining execution order (drag to reorder)
Step Title Name of the step (required)
Step Type Classification (e.g., “Safety”, “Isolation”, “Verification”)
Responsible Party Role or person accountable for completing the step
Comment Additional notes, instructions, or requirements
Interdependency Other steps (by Order number) that must be completed first

Add a Template Step

  1. Select the phase tab (Preparation, De-commissioning, Repair, or Commissioning)
  2. Click the Add (+) button
  3. Enter step details:
    • Step Title: Clear, actionable description (required)
    • Step Type: Category or classification
    • Responsible Party: Who performs this step
    • Comment: Detailed instructions or safety notes
    • Interdependency: Select prerequisite steps by Order number
  4. Click Save or press Enter

Edit a Template Step

  1. Click the Edit (pencil) icon on the step row
  2. Modify any field
  3. Click Save to apply changes

Note: Changes to template steps do NOT affect existing work programs that were created from this template. They only apply to newly created work programs.

Delete a Template Step

  1. Click the Trash icon on the step row
  2. Confirm deletion
  3. The step is removed from the template

Reorder Template Steps

  1. Locate the six-dot handle (⋮⋮) at the left of the row
  2. Click and drag the step to the desired position
  3. Release to drop
  4. The Order numbers update automatically

Set Step Interdependencies

Interdependencies ensure that prerequisite steps must be completed before a step becomes available.

  1. Edit the step
  2. Click the Interdependency cell
  3. Select one or more prerequisite steps by their Order number
  4. Save the step

Using Templates in Work Programs

When users create a new work program, they can import a template through the Planning → Template tab. The template steps are copied to the work program, where users can then execute them.

Key Point: Template changes do not retroactively affect existing work programs. Only new work programs created after the template is modified will include the updates.

LOTO Metadata Configuration

Navigate to Settings → LOTO Metadata to define the dynamic columns (metadata fields) that appear in work program list tables (e.g., Blind List, Valves List, Electrical Drives List, Drains List, Hose List, Other List). These fields control what users can view and edit in each list.

What you can do here

  • Add new columns (fields) to specific lists.
  • Edit field properties (labels, data source, input type, etc.).
  • Delete fields you no longer want shown.
  • Reorder fields by dragging rows to change the column order in the list tables.

Field Reference

Field What it means / how it’s used
Field Name Internal identifier; must be unique, start with a letter, and use only letters, numbers, or underscores.
Display Label The column header shown to users in list tables.
Item Type Determines which list/table shows this field (e.g., Blind List, Valves List, etc.).
Data Source Where the value comes from: UserEntered (users type/select values) or ConnectedItem (auto-filled from P&ID object).
Connected Item Attribute Attribute to display when Data Source = ConnectedItem.
Input Type (UserEntered only) Editor control for manual entry: Text, Dropdown, Boolean, Number, or Date.
Dropdown Options (Dropdown only) Allowed choices for Input Type = Dropdown; provide as a comma-separated list.
Data Type Must match the input type (String/Number/Boolean/Date); enforced automatically.

Common Operations

Common Metadata Operations

Add a Field

  1. Click the “+” button.
  2. Fill out:
    • Field Name: Internal name (letters/numbers/underscores; must start with a letter).
    • Display Label: The column header users will see.
    • Item Type: Which list the field appears in (e.g., Blind List).
    • Data Source: UserEntered (manually entered in lists) or ConnectedItem (auto from connected P&ID object).
    • Input Type (UserEntered only): Text, Dropdown, Boolean, Number, or Date.
    • Dropdown Options (Dropdown only): Comma-separated choices (e.g., Open,Closed,Locked).
    • Data Type:
      • If UserEntered → auto-matched and locked to the Input Type:
        Text → String, Dropdown → String, Boolean → Boolean, Number → Number, Date → Date.
      • If ConnectedItem → choose String/Number/Boolean/Date to match the source attribute.
    • Connected Item Attribute (ConnectedItem only): Attribute to pull from the P&ID object.
  3. Click the Save Icon button. The field is added and positioned at the end of the list’s columns.

Edit a Field

  1. Click the Edit (pencil) icon on the row.
  2. Adjust the properties.
    • When Data Source = ConnectedItem, Input Type and Dropdown Options are disabled.
    • When Data Source = UserEntered, Connected Item Attribute is disabled.
  3. Click the Save Icon button to finalize changes.

Delete a Field

  1. Click the Delete (trash) icon and confirm.
    • The column disappears from the UI for users.
    • Existing values in the database are not deleted.
    • Re-create the same Field Name later to show the values again.

Reorder Fields (Column Order)

  1. Drag the row handle up or down.
  2. Release to drop. The new order is saved and reflected in the list table layout.

Rules & Validation (Quick Guide)

  • Required fields: Field Name, Display Label, Item Type, Data Source, Data Type.
  • Dropdown Options: Required if Input Type = Dropdown.
  • Type Matching: Data Type must match the Input Type (checked automatically).
  • Connected vs UserEntered: Only the relevant inputs are enabled; the others are dimmed and cannot be edited.

What End Users Will See

  • Fields you define here appear as columns in the corresponding work program list types.
  • UserEntered fields can be edited inline by list users (double-click cell, edit, press Enter to save).
  • ConnectedItem fields are read-only, reflecting live data from the connected P&ID object.
  • Type is a special hardcoded column that automatically displays the Connected Item Name (the name of the catalogue item placed on the P&ID).

Catalogue

Use this page to manage the placeable symbols/templates that appear in the Sketching/Placement tools for work program lists (e.g., Blinds, Valves, Electrical Drives, Drains, Hoses, Other). Each catalogue item corresponds to a symbol (SVG) that users can place onto P&IDs when creating or updating work program items.

What is the LOTO Catalogue?

The LOTO Catalogue contains the library of symbols and equipment types that users can place on P&ID drawings when building work programs. Each catalogue item represents a physical device (blind, valve, electrical drive, etc.) and includes:

  • A visual symbol (SVG file) for placement on drawings
  • Associated actions for commissioning and de-commissioning (for Blinds, Valves, and Electrical Drives only)
  • Classification by list type

Catalogue Management Actions

  • Add, Edit, Delete, and Reorder catalogue items
  • Effect for users: Items you configure here appear in the Add list item flow and Sketching Tool catalogue lists

Field Reference

Field Description
Catalogue Item Name Friendly name shown to users in placement dialogs (e.g., “SC-1 Spade Blind”, “Gate Valve 2-inch”)
SVG Path Path to the SVG symbol file in the model/catalogue folder (e.g., IntelliPidCatalogue\LOTO_Symbols\Lototo_V2_w_ll.svg)
List Type Which work program list this item appears under: Blind List, Valves List, Electrical Drives List, Drains List, Hose List, Other List
Display Order Hidden system field updated when you drag rows; controls visible order in placement pickers
Com Action Commissioning action description (Blinds, Valves, Electrical Drives only)
DeCom Action De-commissioning action description (Blinds, Valves, Electrical Drives only)
Com Action Owner Responsible party for commissioning (Blinds, Valves, Electrical Drives only)
DeCom Action Owner Responsible party for de-commissioning (Blinds, Valves, Electrical Drives only)

Note: Action fields (Com Action, DeCom Action, Com Action Owner, DeCom Action Owner) are only available for Blind List, Valves List, and Electrical Drives List. These fields are automatically disabled for Drains List, Hose List, and Other List.

Common Operations

Common Catalogue Operations

Add a Catalogue Item

  1. Click the Add (+) button
  2. Fill out the required fields:
    • Catalogue Item Name: The name users see when selecting an item to place (e.g., “SC-1 Spade Blind”, “Gate Valve 2-inch”)
    • SVG Path: The file path to the symbol (SVG) in your model/catalogue folder (e.g., IntelliPidCatalogue\LOTO_Symbols\Lototo_V2_w_ll.svg)
      • Ensure the SVG exists and is accessible in the deployment environment
    • List Type: Which work program list this item belongs to
  3. (Optional) For Blinds, Valves, and Electrical Drives, enter:
    • Com Action: Description of commissioning action
    • DeCom Action: Description of de-commissioning action
    • Com Action Owner: Responsible party for commissioning
    • DeCom Action Owner: Responsible party for de-commissioning
  4. Click the Save icon button
  5. The new item appears for users in the corresponding placement catalogue

Tip: Use descriptive names that help users quickly identify the correct item (e.g., “Spectacle Blind 6-inch” instead of just “Blind”).

Edit a Catalogue Item

  1. Click the Edit (pencil) icon on the row
  2. Update any field:
    • Name
    • SVG Path
    • List Type
    • Action fields (if applicable)
  3. Click Save to finalize changes

Note: If you change the List Type from Blinds/Valves/Electrical Drives to Drains/Hose/Other, the action fields are automatically cleared.

Delete a Catalogue Item

  1. Click the Delete (trash) icon on the row
  2. Confirm deletion in the dialog

Important:

  • The item is removed from the placement catalogue for users
  • Already-placed objects using that SVG are not deleted from P&IDs or work programs
  • Users can no longer select this item for new placements

Reorder Catalogue Items

  1. Drag the six-dot handle (⋮⋮) up or down to change order
  2. Release to drop
  3. The Display Order updates automatically
  4. Items appear in this order in the placement picker for users

Best Practice: Order items logically (e.g., group similar items together, or order by frequency of use).

SVG Symbol Requirements

  • File Format: Must be a valid SVG file
  • Location: Must exist in the model/catalogue folder accessible by the application
  • Path Format: Use backslashes for Windows paths (e.g., IntelliPidCatalogue\LOTO_Symbols\symbol.svg)

Languages

The Languages page allows administrators to manage all language translations used throughout the application. This section enables administrators to add new languages, edit existing translations, import/export standard translations from Excel, and configure default language settings.

The languages administration page

Overview

  • The Language Management system uses a two-table architecture:

    • Standard Translations: Base translations loaded from Excel files that serve as read-only templates
    • Custom Translations: User-editable translation overrides that take priority over standard translations
  • Administrators can set a default language, from Standard Translations that serves as the fallback for all translations.

  • Users can select their preferred language from available custom languages, which persists across sessions.

  • Translation priority system ensures the best available translation is displayed:

    1. Custom translation in current language (highest priority)
    2. Standard translation in current language
    3. Custom translation in default language
    4. Standard translation in default language

Features

1. Language Selection

Current Language

  • Select which custom language dictionary the app will use.

Default Language

  • Defines the base language used as the fallback when translations are missing in other languages.

  • Can be set from the dropdown and saved with the “Set Default Language” button.

  • Serves as the template for creating new custom languages.

Edit Language

  • Select which custom language dictionary to view and edit in the translation grid.

  • Displays all translation key-value pairs.

2. Translation Grid

  • Displays a merged view of all translation keys and their corresponding values for the selected language.

  • Visual Indicators: Rows with:

    • Green dot: Custom translation (editable, stored in Custom Translations)
    • Yellow/Orange dot: Standard translation (read-only, from Standard Translations)
      • These rows indicate missing keys/rows from Custom Translations, that are present in Standard Translations.
Visual Indicator
  • Key Column: Contains the translation key (read-only, cannot be edited).

  • Value Column: Contains the translated text (editable for custom translations).

  • Editing Translations:

    • Click the edit icon to modify a value
    • Edits to standard translations rows(Yellow/Orange dot) automatically create a custom override, adding them to the custom translations for the edited language.
  • Features filter row for quick searching of specific translations.

3. Standard Translations

Standard translations serve as the base translation templates and are loaded from the translations.xlsx file when the application starts.

Excel File Format:

  • Multi-sheet workbook where each sheet represents one language
  • Each sheet has 3 columns: language, key, value
  • The language column contains the language code for all rows in that sheet
  • Sheet name typically matches the language code

Updating Standard Translations:

To update standard translations, edit the translations.xlsx file in the project root directory and restart the application. The translations will be automatically loaded from the file at startup.

4. Add Custom Language

Create a new custom language dictionary that can be edited directly in the interface:

  1. Click the Add Language button.

  2. Select a language code from the ISO language list (e.g., en-US, ko, ar).

  3. Click Create Language.

  4. A new custom language is created with:

    • All keys copied from the default language’s standard translations
    • Empty values that you can fill in
  5. The new language appears in the “Edit Language” dropdown.

  6. Edit translations directly in the translation grid.

Adding a new language

5. Import Custom Language from Excel

Import a custom language dictionary from a Excel file:

  1. Click the Import Language Dictionary button.

  2. Select a language code or enter a custom one.

  3. Download a template Excel:

    • Download Template: Gets all keys from default language with empty values
  4. Fill in the Excel file:

key value
Add Language 언어 추가
Update Language 언어 업데이트
Select a file 파일 선택
  1. Upload the completed Excel file.

  2. Click Import to save the custom language.

Note: If the language already exists, importing will update the existing custom translations

Managing Languages

Update Existing Custom Translations (In detail)

  1. Select the custom language to edit from the Edit Language dropdown.

  2. Use the filter row to search for specific translations.

  3. Click the edit icon button to edit the row.

  4. Modify the value and click the Save button.

Editing translations

Set Default Language

  1. Select the desired language from the Default Language dropdown.

  2. The system updates the default language.

Understanding Translation Priority

When the application displays a translation, it follows this priority order:

  1. Custom translation in user’s current language - User-specific overrides
  2. Standard translation in user’s current language - Base translations from Excel
  3. Custom translation in default language - Fallback custom translations
  4. Standard translation in default language - Fallback base translations

This ensures users always see the most appropriate translation available.

Excel File Format

When importing custom language dictionaries via Excel, the file must follow this exact column layout:

language key value
ko Add Language 언어 추가
ko Update Language 언어 업데이트
ko Select a file 파일 선택

Requirements

  • The Excel file must contain a header row with exactly these columns:

    • language
    • key
    • value
  • Each row represents a single translation entry.

  • Each sheet represents one language (e.g., en-US, ko, he-IL) if using multi-sheet format.

  • Keys must match the standard translation keys exactly (do not modify keys).

  • Values should contain your custom translations.

Right-to-Left (RTL) Language Support

The application automatically supports Right-to-Left languages such as Arabic (ar), and Hebrew (he).

  • When a language with RTL directionality is selected, the interface layout automatically adjusts to display content from right to left.

  • Text alignment, menu positioning, and component layouts are automatically reversed to provide a natural reading experience.

  • RTL support is determined by the language code, languages like ar, ar-SA, he, fa, and ur will trigger RTL mode.

  • All UI components adapt to the RTL layout automatically.

RTL

General Settings

Navigate to Settings at the bottom of the navigation bar

Change the Toolkit Theme

  • Users can personalize the Toolkit’s appearance by selecting a theme from a dropdown menu.

  • Each theme modifies the application’s visual style to match the selected design.

  • Once a theme is chosen, the selection is saved.

  • The selected theme is automatically applied across all future sessions for that user.

Setting Theme

Configure Language Options

Users can select their preferred language from the Language Settings section.

  • Use the dropdown menu to select from available custom languages.

  • The selected language is tied to the user account and is saved automatically.

  • The language preference is applied across all future sessions.

  • If a translation is missing in the selected language, the system will fall back to:

    1. Standard translation in the selected language
    2. Custom translation in the default language
    3. Standard translation in the default language
    4. en-US as the ultimate fallback

Note: Only languages with custom translations (created by administrators in the Languages admin page) appear in this dropdown. For information on creating and managing languages, see the Languages section.

Signature Settings

The Signature Settings section on the Settings page allows administrators to manage their own personal Interactions email signature.

  • This signature is automatically included in the default message body when composing an Interactions email.

  • Automatically appends a consistent sign-off to each email.

  • Updates to the signature are saved to the user’s profile and persist across sessions, eliminating the need to re-enter it each time.

Setting Theme

Company Settings

The Company Settings section allows administrators to customize branding for the Toolkit application by setting a company name and uploading a company logo.

Company Settings

Company Name

  • Enter your organization’s name in the Company Name text field.

  • The name will automatically save.

  • This company name will appear on outgoing communications and throughout UI elements.

  • Use the Clear button (X icon) to quickly remove the current company name if needed.

  • A “Saving…” indicator appears briefly to confirm that your changes are being saved.

  • Upload a custom logo to represent your organization throughout the Toolkit interface.

  • The logo uploader supports all standard image formats (PNG, JPG, JPEG, GIF, SVG, etc.).

  • You can either drag and drop an image file into the upload area or click to browse and select a file from your computer.

  • Once selected, the logo is automatically uploaded and saved.

  • A preview of your uploaded logo is displayed below the uploader for verification.

  • The selected logo persists across all sessions and is visible to all users.

Best Practices:

  • Use a square or wide image for optimal display across different UI components
  • Transparent PNG format is recommended for the best visual results
  • Ensure the logo has sufficient contrast against both light and dark backgrounds
  • Keep file sizes reasonable (under 2MB) for faster loading