Skip to main content
Resource Publishing

Custom Dashboard Schema

A custom dashboard groups patient reports, custom reports, and inline count or indicator tabs into a named clinical view. Dashboards appear in a configurable section of the Medicus UI (controlled by subnavItem).

A dashboard can reference separately-published reports by identifier, or define inline tabs that embed patient queries directly.

See also the Custom Report Schema for the report types that dashboards reference, and the Patient Query Language reference for writing inline patient queries.

Examples

Dashboard referencing published reports

<?xml version="1.0" encoding="UTF-8"?>
<dashboard>
<name>Diabetes Register</name>
<identifier>my-org/diabetes-register</identifier>
<subnavItem>registers</subnavItem>
<patientReport>my-org/diabetes-patients</patientReport>
<indicatorReport>my-org/diabetes-indicators</indicatorReport>
</dashboard>

Dashboard with an inline count tab

<?xml version="1.0" encoding="UTF-8"?>
<dashboard>
<name>Medication Monitoring</name>
<identifier>my-org/medication-monitoring</identifier>
<subnavItem>medication-monitoring</subnavItem>
<reportCountTab identifier="on-monitoring" label="On Monitoring" type="patient">
<row identifier="warfarin-patients" label="Warfarin">
<patientQuery>
<!-- inline patient query XML -->
</patientQuery>
</row>
</reportCountTab>
</dashboard>

Full dashboard with an inline report tab

Putting it all together: a one-tab dashboard listing every patient with a ring pessary recorded. This example is checked automatically against the current schema (npm run check-schema-examples, wired into prebuild) - if a schema change breaks it, the build fails rather than the example silently going stale.

<?xml version="1.0" encoding="UTF-8"?>
<dashboard>
<name>Ring Pessary Review</name>
<identifier>my-org/ring-pessary-review</identifier>
<subnavItem>local-enhanced-services</subnavItem>
<section>LES</section>
<reportTab identifier="my-org/ring-pessary-patients" name="Ring Pessary Patients">
<patientReport schemaVersion="3">
<name>Ring Pessary Patients</name>
<rows>
<patientQuery>
<name>RingPessary</name>
<description>Patients with a ring pessary</description>
<population><patientQueryReference>ALL</patientQueryReference></population>
<codeLists>
<codeList>
<name>RING_PESSARY_COD</name>
<codeListDefinition>
<rules>
<inclusion>&lt;&lt; 274228008 |Insertion of pessary|</inclusion>
</rules>
</codeListDefinition>
</codeList>
</codeLists>
<variables>
<codedEntryVariable name="PESSARY_DAT" code="RING_PESSARY_COD" select="clinically_relevant_date" order="clinically_relevant_date" take="latest"/>
</variables>
<rules>
<rule>
<if>PESSARY_DAT NOTEQ NULL</if>
<then>select</then>
<else>reject</else>
</rule>
</rules>
</patientQuery>
</rows>
<columns>
<demographicInformationColumn headerName="Patient" value="patientName"/>
<demographicInformationColumn value="patientPrimaryIdentifier"/>
<demographicInformationColumn headerName="Age" value="patientAge"/>
</columns>
</patientReport>
</reportTab>
</dashboard>

Schema

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- ===== Dashboard subnavItem enumeration =====
these represent all of the available values users can configure for subnavitem -->
<xs:simpleType name="dashboardSubnavItemType">
<xs:restriction base="xs:string">
<xs:enumeration value="cqc"/>
<xs:enumeration value="local-enhanced-services"/>
<xs:enumeration value="medication-monitoring"/>
<xs:enumeration value="preventative-care"/>
<xs:enumeration value="registers"/>
<xs:enumeration value="screening"/>
<xs:enumeration value="vaccination-recalls"/>
</xs:restriction>
</xs:simpleType>
<!-- ===== Shared enums ===== -->
<xs:simpleType name="countTabTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="patient"/>
<xs:enumeration value="prescription"/>
<xs:enumeration value="prescription-issue"/>
<xs:enumeration value="appointment"/>
<xs:enumeration value="activity"/>
</xs:restriction>
</xs:simpleType>
<!-- ===== Opaque types ===== -->
<xs:complexType name="patientQueryType" mixed="true">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- ===== Runtime value structures ===== -->
<xs:complexType name="tabRuntimeValueEntryType">
<xs:sequence>
<xs:element name="value" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="tabRuntimeValuesType">
<xs:sequence>
<xs:element name="runtimeValue" type="tabRuntimeValueEntryType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- ===== Tab types ===== -->
<xs:complexType name="reportTabType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="identifier" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="countRowType">
<xs:sequence>
<xs:element name="patientQuery" type="patientQueryType"/>
</xs:sequence>
<xs:attribute name="identifier" type="xs:string" use="required"/>
<xs:attribute name="label" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="reportCountTabType">
<xs:sequence>
<xs:element name="runtimeValues" type="tabRuntimeValuesType" minOccurs="0"/>
<xs:element name="row" type="countRowType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="identifier" type="xs:string" use="required"/>
<xs:attribute name="label" type="xs:string" use="required"/>
<xs:attribute name="type" type="countTabTypeType" use="required"/>
</xs:complexType>
<xs:complexType name="indicatorRowType">
<xs:sequence>
<xs:element name="numerator">
<xs:complexType>
<xs:sequence>
<xs:element name="patientQuery" type="patientQueryType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="denominator">
<xs:complexType>
<xs:sequence>
<xs:element name="patientQuery" type="patientQueryType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="identifier" type="xs:string" use="required"/>
<xs:attribute name="label" type="xs:string" use="optional"/>
<xs:attribute name="target" type="xs:decimal" use="optional"/>
<xs:attribute name="matchLabel" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="reportIndicatorTabType">
<xs:sequence>
<xs:element name="runtimeValues" type="tabRuntimeValuesType" minOccurs="0"/>
<xs:element name="row" type="indicatorRowType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="identifier" type="xs:string" use="required"/>
<xs:attribute name="label" type="xs:string" use="required"/>
<xs:attribute name="type" type="countTabTypeType" use="optional"/>
</xs:complexType>
<!-- ===== Root element ===== -->
<xs:element name="dashboard">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="identifier" type="xs:string"/>
<xs:choice>
<xs:element name="subnavItem" type="dashboardSubnavItemType"/>
<xs:element name="type" type="dashboardSubnavItemType"/>
</xs:choice>
<xs:element name="section" type="xs:string" minOccurs="0"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="patientReport" type="xs:string"/>
<xs:element name="indicatorReport" type="xs:string"/>
<xs:element name="patientCountReport" type="xs:string"/>
<xs:element name="activityCountReport" type="xs:string"/>
<xs:element name="reportTab" type="reportTabType"/>
<xs:element name="reportCountTab" type="reportCountTabType"/>
<xs:element name="reportIndicatorTab" type="reportIndicatorTabType"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Key elements and attributes

Element / AttributeRequiredDescription
nameYesDisplay name of the dashboard.
identifierYesUnique identifier, e.g. my-org/diabetes-register.
subnavItem / typeYes (one of)Controls which section of the Medicus UI the dashboard appears under. Allowed values: cqc, local-enhanced-services, medication-monitoring, preventative-care, registers, screening, vaccination-recalls.
sectionNoOptional sub-section label within the chosen nav area.
patientReportNoIdentifier string of a separately-published patient report.
indicatorReportNoIdentifier string of a separately-published indicator report.
patientCountReportNoIdentifier string of a separately-published patient count report.
activityCountReportNoIdentifier string of a separately-published activity count report.
reportTabNoInline tab embedding a report. Requires identifier and name attributes.
reportCountTabNoInline count tab. Requires identifier, label, and type attributes. type is one of patient, prescription, prescription-issue, appointment, activity.
reportIndicatorTabNoInline indicator tab. Each row has a numerator and denominator patient query. Optional target percentage (decimal).