Dashboards

Dashboards is used to present information in a easy way. It can contain information from multiple sources and gives the user a good overview for eg. an employee or a customer. Onify includes a dashboard editor where customers can design their own dashboards.

Create new dashboard

Create empty dashboard template

For more information about form templates, see sections below.

  1. Go to dashboard templates resources (/admin/resources?activedirectory=templates%2Fdashboard&isdirectoryopen=true)
  2. Right click on dashboard folder and click Create new file
  3. Pick a name for the dashboard template (eg. mydashboard.pug)
  4. Copy this text extends ../views/dashboard/default-dashboard to first row of file
  5. Click Save

Create dashboard configuration

  1. Go to dashboard configuration page (/admin/configuration/dashboards)
  2. Click Create new button
  3. Enter Slug (url friendly name, eg. mydashboard )
  4. Enter Title (eg. My Dashboard)
  5. Enter Description (optional)
  6. Select Template (eg. mydashboard.pug)

That was the minimum setup for a dashboard...

Dashboard templates

For every dashboard, we need dashboard templates (pug). These templates should be placed in the customer-{customer code}-hub-app GitHub repo in /templates/dashboard folder.

Example dashboard

extends ../views/dashboard/default-dashboard

block append dashboardConfig
  +dashboardOptions({
    width: "large"
})

block dashboardContent

  +dashboardElement({
    name: "image",
    layout: {
      x: '1',
      y: '0',
      width: '3',
      height: '3'
    },
    type: "image",
    nodatamessage: "",
    config: {
      url: "{{user.custom.pictureurl}}"
    }
  })

  +dashboardElement({
    name: "name",
    type: "standardheader",
    layout: {
      x: '1',
      y: '4',
      width: '3',
      height: '1'
    },
    config: {
      header: "{{user.name}}",
      subheader: "{{user.email}}"
    }
  })

Dashboard options

Dashboard options are optional options/config.

  • width (default: "standard") - The width of the dashboard. Choose between small, standard or large.
  • dashboardTitle (default: dashboard title) - The dashboard title
  • dashboardDescription (default: dashboard description) - The dashboard description

_Example: Custom title and description and large dashboard

+dashboardOptions({
  width: "large",
	dashboardTitle: "Test",
	dashboardDescription: "This is a test"
})

Dashboard elements

Elements are widgets that should show on the Dashboard.

General settings

Here are some settings that can be defined for all elements.

  • name - Unique name/id for the element
  • type - What type of element it is
  • title (default: none) - Title for the element
  • description (default: none) - Description for the element
  • class (default: none) - Specify a custom css class for the element
  • layout.* - Placement and size of the element, see details below
  • config.* - Element type specific configuration, see each dashboard element type for more details
  • lookup.* - See Lookups section (Lookups)[#lookups]

Layout

  • layout.x - is used for left position
  • layout.y - is used for top position
  • layout.width - element width
  • layout.height - element height

Example: Header element that uses lookup to get item data

+dashboardElement({
    name: "element1",
    type: "standardheader",
    layout: {
        x: '0',
        y: '0',
        width: '6',
        height: '1'
    },
    lookup: {
        "type": "item",
        "key": "{{item.key}}"
    },
    config: {
        header: "{{item.attribute['display_name']}}",
        subheader: "{{item.attribute['email_address']}}"
    }
})

Standard header element

Settings

  • config.header - Widget header
  • config.subheader (default: none) - Widget sub-header

Example: Simple header with current logged in users name

+dashboardElement({
    name: "name",
    type: "standardheader",
    layout: {
      x: '0',
      y: '0',
      width: '8',
      height: '1'
    },
    config: {
      header: "{{user.name}}"
    }
  })

Image element

Settings

  • config.url - Widget header

Example: Get users custom profile picture

+dashboardElement({
    name: "image",
    layout: {
      x: '0',
      y: '0',
      width: '3',
      height: '3'
    },
    type: "image",
    nodatamessage: "",
    config: {
      url: "{{user.custom.pictureurl}}"
    }
})

KPI element

More docs coming soon...

Example: Number style

  +dashboardElement({
	"title" : "Active assets",
	"data" : {
		"activeassets" : "{{config.api.url}}/api/v1/my/items/itam?term=*&filter=status.name:In%20use&filter=tag:asset",
	},
	"widget" : "kpi",
	"config" : {
		"style" : "number",
		"showmore" : {
			"link" : "/"
		},
		"expression" : "{{activeassets.totalresults}}",
		"color" : {
			"green" : "< 50",
			"red" : ">= 50",
			"yellow" : "> 5000"
		}
	}
})

Example: Percent style

  +dashboardElement({
	"data" : {
		"activeassets" : "{{config.api.url}}/api/v1/my/items/itam?term=*&filter=status.name:In%20use&filter=tag:asset",
		"totalassets" : "{{config.api.url}}/api/v1/my/items/itam?term=*&filter=tag:asset"
	},
	"widget" : "kpi",
	"config" : {
		"style" : "percent",
		"showmore" : {
			"text" : "Active Assets",
			"link" : "/"
		},
		"expression" : "{{activeassets.totalresults}} / {{activeassets.totalresults}} * 100",
		"color" : {
			"#555" : "< 50",
			"#999" : ">= 50"
		}
	}
})

Conversation element

More docs coming soon...

Example: Get events (like comments) for specific item

  +dashboardElement({
    name: "conversation_1",
    title: "Conversation element from result",
    layout: {
      x: '0',
      y: '0',
      width: '4',
      height: '5'
    },
    "lookup": {
      "type": "events",
      "workspace": "{{item.workspace}}",
      "query": "Lorem",
      "item": "{{item.key}}",
      "sort": ["category,asc", "level,desc"],
      "level": "info",
      "tag": "consent",
      "pagesize": 10
    },
    "type": "conversation",
    "config": {
      "fields": [{
        "name": "align",
        "value": "{{event.level}}"
      }, {
        "name": "class",
        "value": "{{event.category}}"
      }, {
        "name": "text",
        "value": "{{event.meta.details}}"
      }, {
        "name": "footer",
        "value": "{{event.timestamp}}"
      }, {
        "name": "maxwords",
        "value": "100"
      }]
    }
  })

Example: Static example

  +dashboardElement({
    name: "conversation",
    title: "Conversation element static",
    layout: {
      x: '5',
      y: '0',
      width: '4',
      height: '5'
    },
    "type": "conversation",
    "config": {
      "conversations": [{
        "align": "left",
        "class": "test-class-left",
        "text": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
        "footer": "Test footer left"
      }, {
        "align": "right",
        "class": "test-class-right",
        "text": "Test text right",
        "footer": "Test footer right",
        "maxwords": 100
      }, {
        "align": "center",
        "class": "test-class-center",
        "text": "This is **help** _text_ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
        "footer": "Test footer center",
        "maxwords": 100
      }, {
        "text": "Test text center",
        "footer": "Test footer center"
      }, {
        "text": "This is **help** _text_"
      }]
    }
  })

Actions element

Example: List item actions

    +dashboardElement({
      name: "actions",
      class: "transparent",
      layout: {
        x: '0',
        y: '8',
        width: '8',
        height: '1'
      },
      "lookup": {
        "type": "item",
        "key": "{{user.key}}"
      },
      "type": "actions",
      "nodatamessage": "",
      "config": {
        "target": "_self",
        "actions": "item.action | prepareAction : item.key"
      }
    })

Example: Advanced example with translations, excluding actions and adding custom actions

  +dashboardElement({
    name: "element6",
    layout: {
      x: '6',
      y: '2',
      width: '6',
      height: '2'
    },
    "title": "<%app.actions%>",
    "lookup": {
      "type": "item",
      "key": "{{item.key}}"
    },
    "type": "actions",
    "nodatamessage": "<%app.filters%> {{item.name}}",
    "config": {
      "target": "_self",
      "exclude": ["dashboard"],
      "actions": "item.action | prepareAction : item.key",
      "custom": [
        {
          "name": "Reset password",
          "url": "/form/demo-passwordreset?item={{item.key}}&workspace={{item.workspace}}",
          "order": 1,
          "target": "_blank",
          "role": [
            "servicedesk",
            "admin"
          ]
        }
      ]
    }
  })

Attachments element

Example: List item attachments

  +dashboardElement({
    name: "attachments",
    layout: {
      x: '6',
      y: '4',
      width: '4',
      height: '2'
    },
    "lookup": {
      "type": "item",
      "key": "{{item.key}}"
    },
    "type": "attachments",
    "nodatamessage": "",
    "config": {
      "attachments": "item.attachment | getField"
    }
  })

Attributes element

Example: List specific item attributes

  +dashboardElement({
    name: "general",
    layout: {
      x: '1',
      y: '12',
      width: '10',
      height: '3'
    },
    "title": "GENERAL",
    "lookup": {
      "type": "item",
      "key": "{{item.key}}",
      "workspace": "my-workspace"
    },
    "type": "attributes",
    "config": {
      "attributes": [
      {
        "name": "first name",
        "value": "{{item.attribute.firstname}}"
      },
      {
        "name": "last name",
        "value": "{{item.attribute.lastname}}"
      },
      {
        "name": "user type",
        "value": "{{item.attribute.user_type}}"
      },
        {
          "name": "username",
          "value": "{{item.attribute.adaccount}}"
        },
        {
          "name": "status",
          "value": "{{item.status}}"
        },
        {
          "name": "Employee id",
          "value": "{{item.attribute.employee_id}}"
        },
        {
          "name": "company",
          "value": "{{item.attribute.company}}"
        },
        {
          "name": "email",
          "type": "link",
          "link": "mailto:{{item.attribute.email}}",
          "value": "{{item.attribute.email}}"
        },
        {
          "name": "mobile phone",
          "type": "link",
          "link": "tel:{{item.attribute.mobilephone}}",
          "value": "{{item.attribute.mobilephone}}"
        }
      ]
    }
  })

Form element

Example: Embed form and inlcude form parms

  +dashboardElement({
    name: "element11",
    layout: {
      x: '0',
      y: '10',
      width: '12',
      height: '3'
    },
    "type": "form",
    "config": {
      "form": "demo-createincident",
      "parms": "title=Problem%20with%20printer&item={{item.key}}&workspace={{item.workspace}}&css=widget-form&embed=embed-page-form-inner"
    }
  })

HTML element

Example: Show item description

  +dashboardElement({
    name: "description",
    layout: {
      x: '4',
      y: '1',
      width: '6',
      height: '1'
    },
    "type": "html",
    "lookup": {
      "type": "item",
      "key": "{{item.key}}"
    },
    "nodatamessage": "",
    "config": {
      "content": "{{item.description}}"
    }
  })

Example: Simple HTML text

  +dashboardElement({
    name: "element8",
    layout: {
      x: '0',
      y: '6',
      width: '3',
      height: '2'
    },
    "title": "Custom HTML/TEXT",
    "type": "html",
    "config": {
      "content": "<span>Custom html</span>"
    }
  })

Example: List with custom classes

+dashboardElement({
  name: "address",
  title: "Adress",
  class: "address",
  layout: {
    x: '4',
    y: '5',
    width: '4',
    height: '4'
  },
  "type": "html",
  "config": {
    "content": `
      <div class="visiting-element">
          <div class="attr">
            <ul>
                <li>
                    <span class="name">Address</span>
                    <span class="value">{{item.attribute.visitingaddress}}</span>
                </li>
                <li>
                    <span class="name">Zip</span>
                    <span class="value">{{item.attribute.visitingzipcode}}</span>
                </li>
                <li>
                    <span class="name">City</span>
                    <span class="value">{{item.attribute.visitingcity}}</span>
                </li>
            </ul>
          </div>
      </div>    `
  }
})

Tags element

Example: List tags for item

  +dashboardElement({
    name: "tags",
    layout: {
      x: '1',
      y: '15',
      width: '10',
      height: '1'
    },
    "lookup": {
      "type": "item",
      "key": "{{item.key}}"
    },
    "type": "tags",
    "config": {
      "tags": "item.tag | prepareFilter : 'tag'"
    }
  })

Trafficlight element

Example: Show item status based on custom color

    +dashboardElement({
      name: "status",
      layout: {
        x: '10',
        y: '0',
        width: '1',
        height: '1'
      },
      "type": "trafficlight",
      "lookup": {
        "type": "item",
        "key": "{{item.key}}"
      },
      "nodatamessage": "",
      "config": {
        "color": "{{result.item.attribute._status_color}}",
        "message": "{{result.item.status}}"
      }
    })

Listitems element

Example: List tickets for specific person (item)

    +dashboardElement({
      name: "tickets",
      layout: {
        x: '1',
        y: '1',
        width: '10',
        height: '3'
      },
      "title": "Tickets (Open)",
      "lookup": {
        "type": "items",
        "workspace": "{{item.workspace}}",
        "query": "filter=tag:incident&filter=owner:{{item.key}}&filter=!status:Closed",
        "term": "*",
        "sort": "key,asc",
        "pagesize": 3
      },
      "type": "listitems",
      "config": {
        "style": "table",
        "showmore": {
          "text": "<%app.seemore%>",
          "link": "/workspace/{{item.workspace}}/search?term=*&filter=tag:incident&filter=owner:{{item.key}}&filter=!status:Closed&filter=!status:On Hold&sort=key,asc"
        },
        "fields": [{
          "name": "number",
          "type": "link",
          "link": "/workspace/{{item.workspace}}/search?term={{result.item.key}}",
          "value": "{{result.item.key}}"
        }, {
          "name": "title",
          "value": "{{result.item.name}}"
        }, {
          "name": "priority",
          "value": "{{result.item.attribute.priority}}",
          "class": "{{result.item.attribute._priority_class}}"
        }, {
          "name": "action",
          "type": "link",
          "link": "/form/demo-itemcomment?title=Comment {{result.item.key}}&description=Incident title: {{result.item.name}}&header=Please%20enter%20comment&button=Add%20comment",
          "value": "Add comment",
          "target": "_blank"
        }
        ]
      }
    })