The Path to a FOLIO Dashboard
The basics: What is a dashboard? It’s a place where a set of user-defined queries can be stored and the results conveniently displayed without the necessity of a user entering those search terms on each visit. The results of the stored queries are dynamically retrieved each visit. A dashboard is NOT a reporting tool, a backend analysis tool, or a typical CRUD UI where search, detail views are readily available.
The main UI ingredients of a dashboard are a form with which to create the query (a query-builder) in an ‘edit’ mode and a presentation ‘widget’ that’s displays the result of each query in a ‘view’ mode.
Query building
At the end of the day, a ‘query’ is a only a string sent to the backend in the hopes of retrieving data. It’s not plain English, but the backend understands the meaning of the string “locations?limit=1000&offset=1000&query=cql.allRecords%3D1%20sortby%20name”. The query-builder is the UI that assists the user in constructing/contriving this string. It supplies possible segments of the query such as the fields to query on or to sort the results by. This assistance requires backend support from the source of the data.
Possible descriptions for query support are inconsistent across FOLIO modules. Some implement a _jsonSchema
endpoint, but some do not. _jsonSchema
, despite being a possible source of outward-facing meta-information about an API, still falls short of the needs for a query-builder as it can fall short of reaching the depth required to fully populate the user experience. While they do contain ‘type’ information that would be fine for validating responses and setting expectations around the content of responses, it fails to expose possible comparators for queries, or columns available for meaningful presentation in a query-building UI. The Bienvolk team approached a solution for this via their dashboard
interface: The dashboard interface
This interface (currently exposed by mod-licenses, mod-agreements) is polled by mod-service-interaction. It populates the ‘Widget Types’ that are available in the dashboard UI which control the series of fields for users to fill out when they’re adding a new widget to their dashboard or editing an existing widget. Widgets only exist for a handful of modules and each widget type has limits to what it provides. The user can’t query arbitrary endpoints or pull in any subordinate queries to perform joins that are not already implemented internally.
Aside from what is ascribed by the internal configuration of the Widget itself.
There are settings for the URL link back to the ui-module where the data might typically be viewed, and a healthy array of data used to populate a filter UI with various enumerations and comparators for select lists:
A breakdown of the different parts for current dashboard interface response is here: SimpleSearch JSON Breakdown And in-use we see it here: https://github.com/folio-org/mod-licenses/blob/master/service/src/main/okapi/tenant/sample_data/widgetDefinitions/erm_licenses_simple_search_widget_1.1.json NOTE that this is specifically for SimpleSearch Widgets, and while a CQL solution can be modeled around this, it will require the development of a separate front-end widget type.
Result rendering
The data displayed by a dashboard widget isn’t likely just a single query, but can possibly contain data from a group of queries with results that contain human-legible strings associated with unique id’s (UUID’s). For the results to render in a human-legible way, each of the associated queries must finish execution. For example, items in the /users
query contain a field for patron_group
, which contains a UUID that’s associated with an item from results procured from the /group
endpoint. https://s3.amazonaws.com/foliodocs/api/mod-users/r/users.html#users_get Registered components can be created to make their own requests - this currently happens in the licenses widget: https://github.com/folio-org/stripes-erm-components/blob/master/lib/InternalContactsArrayDisplay/InternalContactsArrayDisplay.js
The next major requirement for rendering is describing how the values should be represented in a useful way. Is the value to be rendered as a link? Where in the data does the label for the link or the href
come from? If these questions are not fulfilled, the user will be likely presented by generic, meaningless representation such as [object Object]
or possibly long UUID’s where meaningful data should be.
The dashboard interface includes valueTypes
that the frontend uses to render data. Currently, these rendering methods either result to fallbacks (string rendering) or pull their rendering from the frontend registry, where it's possible for the ui-modules to expose their rendering techniques for consumption by other modules. This frontend system involves setting up an event handler to register a UI ‘registry resource’ associated with a certain value type. Here’s a code example from ui-dashboard where the registry is checked for a way to render a link: ui-dashboard/src/components/TypeComponents/SimpleSearch/Widget/getDefaultRenderFunction.js at 42a3dcbea368ac8e02b1976af8993c4c1aab3c0d · folio-org/ui-dashboard The actual href information for the link is provided from code that’s owned by a ui-module - external to ui-dashboard
(in this example, from ui-agreements
) - that makes use of the registry
API: ui-agreements/src/setUpRegistry.js at 5f3e1a7f9462630783b30bd07d64b28ba822fb58 · folio-org/ui-agreements In the current state of FOLIO, only a few modules make use of the registry
for sharing functionality like this.
Use Cases
The App Interaction SIG compiled a list of use-cases for the dashboard in 2022. Dashboard Use Cases The lengthy list of cases mostly shortcuts to displaying data that might otherwise be cumbersome to obtain through standard search UI. To summarize, challenging queries like users with recently updated permissions, or patrons with fees/fines, lost or overdue items above a specified amount. Users with patron groups that are soon to expire.
Next steps for any team that wants to create/display a widget on Dashboard app
Review the use cases and prioritize/fulfill any backend capabilities with those features. If the backend can’t already resolve a particular query, the dashboard won’t be able to provide an option for it!
Design and implement a widget form that might conform to a number of use cases, given adequate information from associated meta-information about the data.
Can use the currently supported query language KIWT
OR create a new widget that supports CQL
Expose the proper meta-information from backend modules (
dashboard
interface)Expose UI display resources through the frontend registry.
The questions
How can these current implementations be improved?
How easily could the Dashboard app leverage FQM and/or the Lists app?
Are there better ways aside from polling an interface to obtain meta-information about data sources
Could the front-end provide rendering methods in a way that would depend less on the monolithic bundle in the current state of FOLIO platforms? In a way that didn’t require all of the provided presentation code to be present at the time some centralized event is triggered?
Could query-building be shaped in a way that leverages recently run queries in the system? Would that be useful?
How receptive would the users be for a query builder that got their hands a bit dirtier with the raw data, allowing them deeper display customization and query control?
The future
The ideal solution for a dashboard system is a feature that will be capable of gracefully sitting atop a potentially changing, modular platform and have a ‘sit and forget’ agnosticism to change, fulfilled by existing work that’s achieved as part of the standard process for developing FOLIO modules, frontend and backend.