Skip to main content

Custom Dashboard Widgets

Should I implement a Dashboard widget or a Dashboard report?

Custom Dashboard widgets are useful when certain information needs to be (a) readily available for some users or user roles, and (b) when the parameters to query the database are fixed (i.e. the user cannot specify parameters through the GUI). On the other hand, more customizable data insights should be implemented as Dashboard reports (i.e. when the user needs to be able to slice and dice the data by passing custom parameters).

Dashboard widget configuration

The definitions for dashboard widgets will be held in the dashboard configuration which can be accessed through the Configuration App.

If a dashboard configuration does not already exist in a system, the first time the Dashboard app is opened, a configuration named dashboard will be generated with the default dashboard widgets.

The dashboard configuration consists of a few sections:

  • The ESP_DASH_ELEMENTS section will define the individual dashboard widgets.

  • The defaultLayout section will define the order that the widgets appear in. 

  • The roles and workgroups sections will allow for configuration of which widgets groups of users will be able to see (by roles and workgroups respectively). 

The dashboard configuration can be imported and exported as needed. 

 

Custom dashboard widget definition

Each widget definition in the ESP_DASH_ELEMENTS section should be formatted as follows:

{
	"ESP_DASH_ELEMENTS": {
		"WIDGET REFERENCE": {
			"label": "My New Widget Name",
      		"type": "bar",
      		"resolver": {
				"type": "query",
				"query": "my_registered_db_query"}
      		},
      		"transform": {
					"type": "bar",
        			"parameters": {
          				"countField": "count_from_db_query_result",
          				"labelField": "label_from_db_query_result"
          	}
      	}
	}
}
  • WIDGET REFERENCE can be used in the defaultLayout, roles, and workgroups section to specify which widgets should appear and the order that they should appear in.

  • label will be the name that appears at the top of the widget.

  • type defines how the data will be displayed in the widget. It can be one of the following types:

    • line

    • bar

    • pie

    • radar

    • polar

    • table

  • resolver will define how the data should be retrieved. The type can be one of the following:

    • query

      • query will be the query name registered in L7|ESP. A list of registered queries can be found at the /api/v2/queries/list endpoint. Additional custom query can be yaml files placed in the content/queries folder.

    • api

      • endpoint will be api endpoint to retrieve data from. 

        • parameters will be an object with any additional query parameters.

  • transform will define how to transform the data retrieved for display and can the type can be one of the following:

    • pie which supports the parameters: countField and labelField

    • line which supports the parameters: countField , labelField, and seriesLabel

    • multi_line which supports the parameters: countField , labelField, seriesField, routeField, uuidField, and routeParamName

    • table which supports the parameters: testid, colors, columns (which is an object consisting of label, property and format)

Default dashboard configuration

The default configuration generated when the Dashboard app is opened for the first time.

{
  "roles": {
    "LabTechnician": [
      "ASSIGNED_TO_WORKFLOWS",
      "EXPERIMENT_STARTS_BY_PROJECT_BY_WEEK",
      "WORKFLOW_TAT"
    ]
  },
  "workgroups": {},
  "defaultLayout": [
    "SAMPLE_COUNT_BY_SAMPLE_TYPE",
    "ASSIGNED_TO_WORKFLOWS",
    "SAMPLE_MOVEMENT_BY_WEEK",
    "SAMPLE_COMPLETES_BY_PROJECT_BY_WEEK",
    "SAMPLE_FAILS_BY_PROJECT_BY_WEEK",
    "EXPERIMENT_STARTS_BY_PROJECT_BY_WEEK",
    "ITEMS_BELOW_REORDER_THRESHOLD",
    "SEQUENCED_PROGRESS",
    "WORKFLOW_TAT"
  ],
  "ESP_DASH_ELEMENTS": {
    "WORKFLOW_TAT": {
      "type": "bar",
      "label": "Workflow TAT (hours)",
      "resolver": {
        "type": "query",
        "query": "workflow_tat"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "workflow_tat",
          "labelField": "workflow_name"
        }
      }
    },
    "SEQUENCED_PROGRESS": {
      "type": "pie",
      "label": "Sequenced/Sequenceable",
      "resolver": {
        "type": "query",
        "query": "sequenced_progress"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "status_count",
          "labelField": "status"
        }
      }
    },
    "SAMPLES_BY_USER_BAR": {
      "type": "bar",
      "label": "Samples By User",
      "resolver": {
        "type": "query",
        "query": "sample_count_by_user"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "sample_count",
          "labelField": "user_name"
        }
      }
    },
    "SAMPLES_BY_USER_PIE": {
      "type": "pie",
      "label": "Samples By User",
      "resolver": {
        "type": "query",
        "query": "sample_count_by_user"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "sample_count",
          "labelField": "user_name"
        }
      }
    },
    "WORKFLOWS_COMPLETED": {
      "type": "pie",
      "label": "Workflows Completed",
      "resolver": {
        "type": "query",
        "query": "workflow_sample_summary"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "completed",
          "labelField": "workflow_name"
        }
      }
    },
    "ASSIGNED_TO_WORKFLOWS": {
      "type": "pie",
      "label": "Samples Assigned To Workflows",
      "resolver": {
        "type": "query",
        "query": "workflow_sample_summary"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "assigned_workflow",
          "labelField": "workflow_name"
        }
      }
    },
    "WORKFLOWS_IN_PROGRESS": {
      "type": "pie",
      "label": "Workflows In Progress",
      "resolver": {
        "type": "query",
        "query": "workflow_sample_summary"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "in_process",
          "labelField": "workflow_name"
        }
      }
    },
    "SAMPLE_MOVEMENT_BY_WEEK": {
      "type": "line",
      "label": "Sample Movement By Week",
      "resolver": {
        "type": "query",
        "query": "sample_movement_last_6_months"
      },
      "transform": {
        "type": "line",
        "parameters": {
          "countField": "sample_steps_completed",
          "labelField": "week",
          "seriesLabel": "Samples"
        }
      }
    },
    "SAMPLE_COUNT_BY_SAMPLE_TYPE": {
      "type": "pie",
      "label": "Sample Count by Sample Type",
      "resolver": {
        "type": "query",
        "query": "sample_count_by_sample_type"
      },
      "transform": {
        "type": "pie",
        "parameters": {
          "countField": "sample_count",
          "labelField": "sample_type"
        }
      }
    },
    "ITEMS_BELOW_REORDER_THRESHOLD": {
      "type": "table",
      "label": "Items Requiring Reorder",
      "resolver": {
        "type": "query",
        "query": "low_inventory"
      },
      "transform": {
        "type": "table",
        "parameters": {
          "colors": [
            "black",
            "black",
            "red"
          ],
          "testid": "reorder-inventory",
          "columns": [
            {
              "label": "Item Type",
              "format": "${value}",
              "property": "name"
            },
            {
              "label": "Threshold",
              "property": "reorder_threshold_qty"
            },
            {
              "label": "Remaining",
              "property": "instock"
            }
          ]
        }
      }
    },
    "SAMPLE_FAILS_BY_PROJECT_BY_WEEK": {
      "type": "line",
      "label": "Sample Fails by Project By Week",
      "resolver": {
        "type": "query",
        "query": "sample_fails_last_6_months_by_project"
      },
      "transform": {
        "type": "multi_line",
        "parameters": {
          "uuidField": "route_uuid",
          "countField": "protocol_samples_failed",
          "labelField": "week",
          "routeField": "route_name",
          "seriesField": "project",
          "routeParamName": "projectId"
        }
      }
    },
    "SAMPLE_COMPLETES_BY_PROJECT_BY_WEEK": {
      "type": "line",
      "label": "Sample Completes by Project By Week",
      "resolver": {
        "type": "query",
        "query": "sample_movement_last_6_months_by_project"
      },
      "transform": {
        "type": "multi_line",
        "parameters": {
          "countField": "experiment_samples_completed",
          "labelField": "week",
          "seriesField": "project"
        }
      }
    },
    "EXPERIMENT_STARTS_BY_PROJECT_BY_WEEK": {
      "type": "line",
      "label": "Experiment Starts By Project By Week",
      "resolver": {
        "type": "query",
        "query": "experiment_starts_last_6_months_by_project"
      },
      "transform": {
        "type": "multi_line",
        "parameters": {
          "countField": "experiment_starts",
          "labelField": "week",
          "seriesField": "project"
        }
      }
    }
  }
}

Example

To add a table widget showing the latest 10 Aliquots in the system along with links to the entities:

  1. Navigate to the dashboard configuration in the Configuration App.

  2. Copy and paste the following widget into the dashboard configuration in the ESP_DASH_ELEMENTS array. 

    "Latest Aliquots": {
          "type": "table",
          "label": "Latest Aliquots",
          "resolver": {
            "type": "api",
            "endpoint": "/api/samples?sample_type=Aliquot&limit=10"
          },
          "transform": {
            "type": "table",
            "parameters": {
              "color": [
                "black",
                "black"
              ],
              "testid": "latest-aliquots",
              "columns": [
                {
                  "label": "Entity Name",
                  "format": "${value}",
                  "property": "name"
                },
                {
                  "label": "Created Date (UTC)",
                  "format": "${value.split('T')[0]}",
                  "property": "created_at"
                }
              ]
            }
          }
        },
  3. Add the “Latest Aliquots” widget name to the defaultLayout array. 

  4. Save the updated configuration. A system restart is not required. 

  5. Navigate to the Dashboard tab of the Dashboard app to see the updated dashboard widget.