Skip to Content
FrontendAppsReportPages & Integration

Pages & Integration

This page documents all the pages of the report project, which container renders them, which role they need and which API they call.


1. The chain

The pages are not independent, they follow the KPI chain. From the raw query to the rendered report:

Data Collector → DC Results → Data Processor → Widget → Report (execute) (process) (populate) (render)
  1. A Data Collector is the query. We run it from the DC execute page and it produces the DC results.
  2. A Data Processor combines one or many collectors. We run it from the DP process page and it produces the rows.
  3. A Widget points at a DP and carries the template name. The populate page is the widget with its data, the render page is the widget as it will appear on a report.
  4. A Template is the JSON descriptor of the widget. More about it in Creating a template.
  5. A Report is the container. dashboard_reportwidgets is the link record which puts a widget on a report.

2. Show pages and the resolvers

Every entity also has a show page and two resolvers:

/{resource}/{id} the show page /{resource}/id/{id} resolves by id and redirects /{resource}/slug/{slug} resolves by slug and redirects

The slug resolver calls the dedicated endpoint {resource}/by_slug/{slug}, so a report can be linked by a readable slug instead of a numeric id. All three need the SHOW action of that resource.

The identifier decides which call we make. A numeric one goes to {resource}/{id}, anything else goes to by_slug, and the id/ and slug/ routes force the mode. Before we put an identifier in the URL of the id call we validate it, and a slug which doesn’t resolve returns the 404 page instead of an error.

The show pages are not all the same:

PageContainerWhat is on it
/dashboard-reports/{id}ReportDetailThe report, its widgets through dashboard_reportwidgets?report={id}, and the link to the render page
/dashboard-widgets/{id}WidgetDetailThe widget, its DP, its template, and the links to filter, populate and render
/dataanalysis-datacollectors/{id}DataCollectorClientThe collector, its parameters (dataanalysis_datacollectorparameters?dataCollector={id}) and its query
/dataanalysis-dataprocessors/{id}DataProcessorDetailThe processor and its collectors (dataanalysis_dataprocessorcollectors?processor={id})
/templates/{id}TemplateThe template record and its JSON source

3. Action pages

These are the pages which are specific to this project. They are the ones we use to test the chain step by step.

3.1 DC Execute

/dataanalysis-datacollectors/{id}/execute role action: EXECUTE

Container: DcExecuteClient.

We run the collector and we display the result. The page reads the parameters of the collector, lets us fill them, and calls dataanalysis_datacollectors/{id}/execute. The raw data can be copied from there (issue #86 ), and the export formats go through dataanalysis_datacollectors/{id}/execute/{format}.

DC Execute page with the Input, Query, Output and Export sections, the Filters tab filled and the Execute button

The page has four sections: Input (Filters, Parameters, Raw), Query, Output (JSON or Table) and Export. Save defaults stores the filled parameters in the KVS, so we don’t type them again on the next run.

3.2 DP Process

/dataanalysis-dataprocessors/{id}/process role action: PROCESS

Container: DpProcessClient.

Same idea but for the processor. We take the parameters from dataanalysis_dataprocessors/{id}/process/metadata, we send them to dataanalysis_dataprocessors/{id}/process, and we display the rows which the widget will receive. The {format} and the async/ variants are used for the exports.

The parameters of the process come from the metadata call, one entry per collector parameter with its type and its defaultValue:

The process metadata request and its JSON response, with the parameters of the collector and their default values

3.3 Widget Filter

/dashboard-widgets/{id}/filter role action: FILTER

Container: WidgetFilterClient.

The filters of the widget, coming from dashboard_filters?dataCollector={id}&order[priority]=asc. This is where we test a filter before putting it on a report. The default values are stored in the KVS.

Widget Filter page with the Input section open on the Filters tab, one field per filter of the collector

The sections are Input (Filters and Parameters), Metadata, Output and Export Result, and View render sends us to the render page of the same widget. Every field is named after its collector prefix, like ProductStockLevelCheckSum_59__dateStart, so we see which collector the filter belongs to.

3.4 Widget Populate

/dashboard-widgets/{id}/populate role action: POPULATE

Container: WidgetPopulateClient.

The widget with its data. We read dashboard_widgets/{id}/metadata to know the parameters and the result columns, then we call dashboard_widgets/{id}/populate. If a widget is empty on a report, this is the page which tells us if the problem is the data or the template.

Widget Populate page with the Metadata section showing the viewNameApi and the parameters, and the Output section in JSON

Metadata shows what the widget declares, the viewNameApi of its template and its parameters. Output shows the rows, in JSON or in a table, with the time the call took. Same sections as the filter page.

3.5 Widget Render

/dashboard-widgets/{id}/render role action: RENDER

Container: WidgetRenderClient.

The widget as it will be displayed on the report, template included. One widget alone, so we can work on a template without opening the whole report.

Widget Render page with the Populated data, Schema, Directive and Render result sections

The sections are Populated data (Load from populate, Load sample, Copy into directive), Schema which tells us if the data and the directive are valid, Directive which is the template JSON, and Render result.

3.6 Template Render

/templates/{id}/render role action: SHOW

Container: TemplateRender.

The template rendered alone, with the sample data of the descriptor instead of a DP result. This is the fastest loop when we are writing a template.

Template Render page with the Sample data, Schema and Directive sections and the Save to template button

Same sections as the widget render, but the data is the sample of the descriptor. From the Directive section we can Load from template, Generate and Save to template, so the whole loop stays on one page.

3.7 Report Render

/dashboard-reports/{id}/render role action: RENDER

Container: ReportRenderClient.

The page renders the skeleton of every widget first (RenderSkeleton), then it populates each one with its DP result, so the grid doesn’t jump while the data is loading. The filters are pulled from the widget metadata at render time.

Report Render page with the filters panel on top and a listing widget below

The filters panel is on top, and the widgets follow in the grid, each one with the colSpan of its template.

The render pages have their own role action (RENDER), separated from SHOW. A user can be allowed to see a report record and not to render it.


5. API calls

https://{tenant}{NEXT_PUBLIC_API_PHPR_ENV}.phpr.link/{API_ENDPOINT_VERSION}/

The default version is open-api/v3 and the locale is sent as Accept-Language: {locale}_CA. The URL is built by buildPhprUrl() and the call is made by callPhprApi(), both coming from frontend-utils.

The endpoints used by the pages above:

EndpointUsed by
dashboard_reports/{id}Report show and render
dashboard_widgets/{id}Widget show and render
dashboard_widgets/{id}/metadataPopulate and render, the parameters and the result columns
dashboard_widgets/{id}/populatePopulate and render, the data of the widget
dashboard_reportwidgets?report={id}The widgets of a report, ?widget={id} for the other way
templates/{id}, templates?name={name}The template of a widget
dataanalysis_datacollectors/{id}/executeDC Execute, /{format} for the exports
dataanalysis_datacollectors/{id}/get_queryThe query of the collector on the show page
dataanalysis_datacollectorparameters?dataCollector={id}The parameters of a collector
dataanalysis_dataprocessors/{id}/processDP Process, with /metadata for the parameters
dataanalysis_dataprocessorcollectors?processor={id}The collectors of a processor
{resource}/by_slug/{slug}Every slug route, for reports, widgets, templates, collectors and processors
dashboard_filters?dataCollector={id}The filters of a widget, ordered by priority
keyvaluestore_keyvaluesThe KVS, for the listing fields and the filter defaults

Last updated on