Skip to content

Drag & Drop

The Dashboard supports a powerful drag-and-drop feature that enhances user interactivity and flexibility in organizing dashboard elements. This documentation provides an overview of how to use this feature and customize its behavior. It is also assumed that the user has read the Admin chapter, specifically the topic on creating and configuring Dashboards.

Overview

The drag-and-drop functionality allows users to move elements around the dashboard by dragging and dropping them into designated areas. This is achieved using two main CSS classes:

  • dragItem: This class is assigned to HTML elements that can be dragged.
  • dropZone: This class is assigned to HTML elements that act as drop targets for dragItems.

How to Use Drag and Drop

To enable an element to be draggable, simply assign it the dragItem class. Similarly, to designate an element as a drop target, assign it the dropZone class. The elements can also have data attributes and specific classes to pass parameters when an item is dropped.

Example:

<div class="dragItem dragItemValue1-{{value1}} dragItemValue2-{{value2}}" data-val1="{{val1}}" data-val2="{{val2}}">
    ...dragItem content...
</div>

<div class="dropZone dropZoneId-{{id}} dropZoneState-{{state}}" data-rmID="{{id}}" data-state="{{state}}">
    ...dropZone content...
</div>

A very basic example

On the following example we have a dashboard with 2 ways that we can use drag and drop functionalities. The first ROW contains 3 Boards, each with 1 Menu. For each Menu, we iterate over a list of items (in this case they're just numbers). The goal is to enable drag and drop between all the Menus.

To do this, we must mark each Menu as a dropZone (a container) and each menu item/row as a dragItem (so we can drag items between Menus).

To do this, we place dropZone in our Menus' classes, and dragItem in each Texts' classes, as seen below. Note that we are dynamically iterating a list using Handlebars to render each Menu, and their respective items.


Customizing Drag and Drop Behavior

The Dashboard supports customization of the drag-and-drop behavior using a concurrent script. This script is triggered each time a dragItem is dropped into a dropZone.

Configuration:

  • Property: DragDropConcurrent
  • Location: DashboardCustomize settings

You can define a concurrent script in the DashboardCustomize settings using the DragDropConcurrent property. This script will be executed automatically when a draggable item is dropped inside a drop zone.


Data Parsing for Concurrent Scripts

When a dragItem is dropped into a dropZone, the concurrent script receives a set of parameters extracted from both the dragItem and dropZone. These parameters are parsed from data attributes (data-*) OR classes prefixed with dragItem and dropZone.

Example Parameters: Given the following elements:

<div class="dragItem dragItemValue1-{{value1}} dragItemValue2-{{value2}}" data-val1="{{val1}}" data-val2="{{val2}}">
    ...dragItem content...
</div>

<div class="dropZone dropZoneId-{{id}} dropZoneState-{{state}}" data-rmID="{{id}}" data-state="{{state}}">
    ...dropZone content...
</div>

The parameters passed to the concurrent script will be:

{
  // DragItem parameters
  "Value1": "value1",
  "Value2": "value2",
  "val1": "val1",
  "val2": "val2",

  // DropZone parameters
  "Id": "id",
  "State": "state",
  "rmID": "id",
  "state": "state"
}

Extra customization options

dragItemOverrideOrigin

By default, the drag&drop engine only supports calling concurrent scripts when dropping on different origin - that is, only when a dragItem is dropped on a different dropZone from where it originated.

To change this behavior, we can add the keyword dragItemOverrideOrigin to our dragItems. This will make the drag&drop engine call the helper concurrent script if the dragItem is dropped on its origin dropZone.

dropZoneHighlight

The keyword dropZoneHighlight is used to enable highlighting of the dropZone when dropping and hovering a dragItem. It also disables enriching the context with the previous and next html elements.


Tickets Example

For the following example, we want to create a simple drag and drop dashboard that lists Tickets and their responsibles. Our final goal is to drag and drop tickets between responsibles to assign them to another user.

To do this, we start by performing a distinct query in our dashboard's context. This way, we get a list of all the responsibles/ticket owners, and their respective tickets:

{
"responsibles" : distinct("Tickets", "responsible_username","*", 100, 0),
}

Then we configure our Menus and respective items (Tickets), having one menu per responsible/ticket owner:

Notice that we configured the drag and drop just like we did for the previous example: setting dropZone in the Menus' classes, and dragItem for each menu item (in the TextClasses).

This results in the following dashboard with menus and draggable Tickets:

Now the only remaining step is to make sure that we update the Ticket instance when we drag a ticket from one responsible/user to another. To do this, we need the ID of the Ticket, and the new Responsible. These are two parameters that we will configure in our dashboard, that will be parsed and sent into a custom concurrent script:

Having the drag and drop ready, we create a simple concurrent script that updates the Ticket instance.

import groovy.transform.Field
@Field static TICKETS_DEF = 'Tickets'

try {
    def ticketId = argsMap.TicketId
    def new_responsible = argsMap.Responsible
    // Since our Responsible field in Tickets is an extRef to UserM, we use the new
    // responsible username to retrieve the User from UserM and use its ID for the ref
    // in the format /userm/user/id
    def new_responsible_id = userm.getUser(new_responsible).getBody().id
    def updates = ["Responsible": "/userm/user/${new_responsible_id}"]
    recordm.update(TICKETS_DEF, ticketId, updates)
} catch(e) {
    log.info("Error updating ticket: "+e.getMessage())
}

And add the script's name to the DragDropConcurrent field in the Dashboard: