@ministryofjustice/hmpps-digital-prison-reporting-frontend 4.14.2 → 4.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dpr/all.mjs +2 -0
- package/dpr/all.scss +4 -0
- package/dpr/components/_catalogue/catalogue-list/utils.test.ts +1 -1
- package/dpr/components/_charts/chart/clientClass.mjs +4 -3
- package/dpr/components/_charts/chart/heatmap/Heatmap.js +2 -0
- package/dpr/components/_charts/chart/heatmap/Heatmap.js.map +7 -0
- package/dpr/components/_charts/chart/heatmap/Heatmap.ts +278 -0
- package/dpr/components/_charts/chart/heatmap/clientClass.mjs +175 -0
- package/dpr/components/_charts/chart/styles.scss +4 -0
- package/dpr/components/_charts/utils.js +1 -1
- package/dpr/components/_charts/utils.js.map +3 -3
- package/dpr/components/_charts/utils.test.ts +4 -1
- package/dpr/components/_charts/utils.ts +73 -27
- package/dpr/components/_dashboards/dashboard/types.js +1 -1
- package/dpr/components/_dashboards/dashboard/types.js.map +2 -2
- package/dpr/components/_dashboards/dashboard/types.ts +21 -1
- package/dpr/components/_dashboards/dashboard-list/utils.js +1 -1
- package/dpr/components/_dashboards/dashboard-list/utils.js.map +3 -3
- package/dpr/components/_dashboards/dashboard-list/utils.test.ts +1 -0
- package/dpr/components/_dashboards/dashboard-list/utils.ts +5 -1
- package/dpr/components/_filters/types.d.js.map +1 -1
- package/dpr/components/_filters/types.d.ts +12 -8
- package/dpr/components/_filters/utils.js +1 -1
- package/dpr/components/_filters/utils.js.map +3 -3
- package/dpr/components/_filters/utils.ts +24 -2
- package/dpr/components/user-reports/utils.js +1 -1
- package/dpr/components/user-reports/utils.js.map +3 -3
- package/dpr/components/user-reports/utils.ts +13 -3
- package/dpr/data/dashboardClient.js +1 -1
- package/dpr/data/dashboardClient.js.map +2 -2
- package/dpr/data/dashboardClient.ts +1 -1
- package/dpr/routes/journeys/request-report/filters/controller.js +1 -1
- package/dpr/routes/journeys/request-report/filters/controller.js.map +3 -3
- package/dpr/routes/journeys/request-report/filters/controller.ts +6 -2
- package/dpr/routes/journeys/request-report/filters/utils.js +1 -1
- package/dpr/routes/journeys/request-report/filters/utils.js.map +2 -2
- package/dpr/routes/journeys/request-report/filters/utils.ts +9 -3
- package/dpr/routes/journeys/view-report/async/dashboard/utils.js +1 -1
- package/dpr/routes/journeys/view-report/async/dashboard/utils.js.map +3 -3
- package/dpr/routes/journeys/view-report/async/dashboard/utils.ts +12 -3
- package/dpr/routes/journeys/view-report/async/report/tests.cy.js +1 -1
- package/dpr/routes/journeys/view-report/async/report/tests.cy.js.map +2 -2
- package/dpr/routes/journeys/view-report/async/report/tests.cy.ts +44 -8
- package/dpr/routes/journeys/view-report/utils.js +1 -1
- package/dpr/routes/journeys/view-report/utils.js.map +3 -3
- package/dpr/routes/journeys/view-report/utils.ts +6 -1
- package/dpr/services/dashboardService.js +1 -1
- package/dpr/services/dashboardService.js.map +2 -2
- package/dpr/services/dashboardService.ts +1 -1
- package/dpr/types/Charts.js +1 -1
- package/dpr/types/Charts.js.map +1 -1
- package/dpr/types/Charts.ts +10 -3
- package/dpr/types/ExecutionData.d.js +1 -1
- package/dpr/types/ExecutionData.d.js.map +1 -1
- package/dpr/types/ExecutionData.d.ts +1 -0
- package/dpr/utils/DataTableBuilder/DataTableBuilder.js +1 -1
- package/dpr/utils/DataTableBuilder/DataTableBuilder.js.map +2 -2
- package/dpr/utils/DataTableBuilder/DataTableBuilder.ts +37 -19
- package/dpr/utils/DateMapper/DateMapper.js +1 -1
- package/dpr/utils/DateMapper/DateMapper.js.map +2 -2
- package/dpr/utils/DateMapper/DateMapper.ts +4 -0
- package/dpr/utils/UserStoreItemBuilder.js +1 -1
- package/dpr/utils/UserStoreItemBuilder.js.map +3 -3
- package/dpr/utils/UserStoreItemBuilder.ts +6 -4
- package/dpr/utils/requestStatusHelper.js +1 -1
- package/dpr/utils/requestStatusHelper.js.map +2 -2
- package/dpr/utils/requestStatusHelper.ts +1 -1
- package/package.json +5 -2
package/dpr/all.mjs
CHANGED
|
@@ -48,6 +48,7 @@ import RecentlyViewedList from './components/user-reports/viewed/clientClass.mjs
|
|
|
48
48
|
import BarChartVisualisation from './components/_charts/chart/bar/clientClass.mjs'
|
|
49
49
|
import DoughnutChartVisualisation from './components/_charts/chart/doughnut/clientClass.mjs'
|
|
50
50
|
import LineChartVisualisation from './components/_charts/chart/line/clientClass.mjs'
|
|
51
|
+
import MatrixChartVisualisation from './components/_charts/chart/heatmap/clientClass.mjs'
|
|
51
52
|
|
|
52
53
|
// Dashboards
|
|
53
54
|
import ScoreCard from './components/_dashboards/scorecard/clientClass.mjs'
|
|
@@ -86,6 +87,7 @@ function initAll() {
|
|
|
86
87
|
BarChartVisualisation,
|
|
87
88
|
DoughnutChartVisualisation,
|
|
88
89
|
LineChartVisualisation,
|
|
90
|
+
MatrixChartVisualisation,
|
|
89
91
|
ScoreCard,
|
|
90
92
|
ReportActions,
|
|
91
93
|
DownloadMessage,
|
package/dpr/all.scss
CHANGED
|
@@ -29,7 +29,7 @@ describe('CatalogueUtils', () => {
|
|
|
29
29
|
const reportsTableData = await CatalogueUtils.getReportsList(res, services)
|
|
30
30
|
|
|
31
31
|
expect(reportsTableData.head.length).toEqual(4)
|
|
32
|
-
expect(reportsTableData.rows.length).toEqual(
|
|
32
|
+
expect(reportsTableData.rows.length).toEqual(70)
|
|
33
33
|
})
|
|
34
34
|
})
|
|
35
35
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
import Chart from 'chart.js/auto'
|
|
3
3
|
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
|
4
|
+
import { MatrixController, MatrixElement } from 'chartjs-chart-matrix'
|
|
4
5
|
|
|
5
6
|
import { DprClientClass } from '../../../DprClientClass.mjs'
|
|
6
7
|
|
|
@@ -18,7 +19,6 @@ class ChartVisualisation extends DprClientClass {
|
|
|
18
19
|
this.legend = this.getElement().querySelector(`#js-legend-${this.id}`)
|
|
19
20
|
|
|
20
21
|
// ChartCard elements
|
|
21
|
-
|
|
22
22
|
this.tooltipDetailsEl = document.getElementById(`dpr-${this.id}-tooltip-details`)
|
|
23
23
|
this.headlineValuesEl = document.getElementById(`dpr-${this.id}-headline-values`)
|
|
24
24
|
this.labelElement = document.getElementById(`dpr-${this.id}-label`)
|
|
@@ -47,10 +47,11 @@ class ChartVisualisation extends DprClientClass {
|
|
|
47
47
|
|
|
48
48
|
initChart() {
|
|
49
49
|
Chart.defaults.font.family = 'GDS Transport'
|
|
50
|
-
Chart.register(ChartDataLabels)
|
|
51
50
|
Chart.defaults.font.size = 12
|
|
52
|
-
|
|
51
|
+
Chart.register(ChartDataLabels)
|
|
52
|
+
Chart.register(MatrixController, MatrixElement)
|
|
53
53
|
this.chart = new Chart(this.chartContext, this.chartData)
|
|
54
|
+
|
|
54
55
|
this.initChartEvents()
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var k=Object.create;var m=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var M=(o,t)=>{for(var i in t)m(o,i,{get:t[i],enumerable:!0})},d=(o,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of v(t))!g.call(o,s)&&s!==i&&m(o,s,{get:()=>t[s],enumerable:!(e=C(t,s))||e.enumerable});return o};var b=(o,t,i)=>(i=o!=null?k(x(o)):{},d(t||!o||!o.__esModule?m(i,"default",{value:o,enumerable:!0}):i,o)),B=o=>d(m({},"__esModule",{value:!0}),o);var R={};M(R,{HeatmapChart:()=>p,default:()=>T});module.exports=B(R);var u=b(require("dayjs")),D=require("with-alpha-hex"),f=require("../../../_dashboards/dashboard/types"),y=b(require("../../../../utils/datasetHelper"));class p{constructor(t,i,e){this.baseColour="#1d70b8";this.ragColours=["#00703c","#ffdd00","#d4351c"];this.buckets=[];this.data=[];this.dayDateFormat="DD/MM/YYYY";this.hasRag=!1;this.options={};this.initFromResponseData=t=>{this.hasRag=t[0][this.valueKey].rag!==void 0,this.responseData=t};this.initFromDefinition=t=>{this.definition=t,this.columns=t.columns,this.unit=this.columns.measures[0].unit?this.columns.measures[0].unit:void 0,this.type=this.definition.type.split("-")[0],this.options=t.options,this.baseColour=this.options.baseColour||this.baseColour,this.valueKey=this.columns.measures[1].id,this.label=this.columns.measures[1].display,this.onlyBucketColoursDefined=this.options?.buckets?.every(i=>!i.max&&!i.min&&i.hexColour!==void 0)};this.initBuckets=()=>{const{buckets:t}=this.options;this.setBucketCount(),this.initBucketColours(),t?this.onlyBucketColoursDefined?this.initAutomaticThresholdBucket():this.initCustomThresholdBuckets():this.hasRag||this.initAutomaticThresholdBucket()};this.initCustomThresholdBuckets=()=>{this.buckets=this.options.buckets.map((t,i)=>({...this.buckets[i],...t}))};this.initAutomaticThresholdBucket=()=>{const{min:t,max:i,bucketSize:e}=this.setAutomaticThresholdSize();let s=0;this.buckets=this.buckets.map((a,r)=>{let n=t;return r!==0&&(n=s+1),s=e*(r+1),r===this.buckets.length-1&&(s=i),{hexColour:this.options?.buckets?this.options.buckets[r]?.hexColour:a.hexColour,min:n,max:s}})};this.initBucketColours=()=>{const{useRagColours:t}=this.options;if(t&&this.bucketCount===3)this.buckets=Array.from(new Array(this.bucketCount)).map((i,e)=>({hexColour:this.ragColours[e]}));else{const i=1/this.bucketCount;this.buckets=Array.from(new Array(this.bucketCount)).map((e,s)=>{const a=i*(s+1);return{hexColour:(0,D.withAlphaHex)(this.baseColour,a)}})}};this.setAutomaticThresholdSize=()=>{const t=this.responseData.map(a=>Number(a[this.valueKey].raw)),i=Math.min(...t),e=Math.max(...t),s=Math.ceil((e-i)/this.bucketCount);return{min:i,max:e,bucketSize:s}};this.setBucketCount=()=>{const{buckets:t}=this.options;this.hasRag?this.bucketCount=Math.max(...this.responseData.map(i=>i[this.valueKey].rag))+1:t?this.bucketCount=t.length:this.bucketCount=3};this.validateDefinition=()=>{const{id:t,columns:i,type:e}=this.definition,s=[];if(i.measures.length!==2?s.push(`Measures should only have 2 columns defined. Only found ${i.measures.length}`):e===f.DashboardVisualisationType.MATRIX_TIMESERIES&&i.measures[0].id!=="ts"&&s.push(`measure at index 0 has incorrect ID. Expected ID to be "ts". Found "${i.measures[0].id}"`),s.length){const a=`Validation: Visualisaton definition: ID: ${t}, type: ${e}, errors: ${s.join(",")}`;throw new Error(a)}};this.initTimeseriesData=()=>{const t=y.default.groupRowsByTimestamp(this.responseData);this.data=t.map(i=>{const{raw:e,rag:s}=i[0][this.valueKey],a=i[0].ts.raw,r=Number(e),n=s!==void 0?Number(i[0][this.valueKey].rag):void 0;let h,l;switch(this.granularity){case"hourly":break;case"weekly":h=(0,u.default)(a,this.dayDateFormat).format("ddd"),l=(0,u.default)(a,this.dayDateFormat).week();break;case"daily":h=(0,u.default)(a,this.dayDateFormat).format("MMM YY"),l=(0,u.default)(a,this.dayDateFormat).format("D");break;case"monthly":{const c=a.split(" ");h=c[1],l=c[0]}break;case"annually":h="year",l=a;break;default:h=(0,u.default)(a,this.dayDateFormat).format("MMM YY"),l=(0,u.default)(a,this.dayDateFormat).format("D");break}return{y:l,x:h,v:r,r:n}})};this.binDataIntoBuckets=()=>{this.data=this.data.map(t=>{const{v:i,r:e}=t;let s;return e!==void 0?s=this.buckets[e].hexColour:this.buckets.forEach(a=>{const{min:r,max:n}=a;!r&&n&&i<=n&&(s=a.hexColour),r&&i>=a.min&&n&&i<=a.max&&(s=a.hexColour),r&&!n&&i>=r&&(s=a.hexColour)}),{...t,c:s}})};this.build=()=>(this.validateDefinition(),this.initTimeseriesData(),this.binDataIntoBuckets(),{type:this.type,unit:this.unit,timeseries:!0,data:{datasets:[{label:this.label,data:this.data}]}});this.granularity=i,this.initFromDefinition(e),this.initFromResponseData(t),this.initBuckets()}}var T=p;0&&(module.exports={HeatmapChart});
|
|
2
|
+
//# sourceMappingURL=Heatmap.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/dpr/components/_charts/chart/heatmap/Heatmap.ts"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable prefer-destructuring */\nimport dayjs from 'dayjs'\nimport { withAlphaHex } from 'with-alpha-hex'\nimport { Granularity } from '../../../_inputs/granular-date-range/types'\nimport { DashboardDataResponse } from '../../../../types/Metrics'\nimport {\n DashboardVisualisation,\n DashboardVisualisationColumns,\n DashboardVisualisationType,\n MatrixDashboardVisualisationBucket,\n MatrixDashboardVisualisationOptions,\n} from '../../../_dashboards/dashboard/types'\nimport { ChartData, ChartType, MatrixChartData, UnitType } from '../../../../types/Charts'\nimport DatasetHelper from '../../../../utils/datasetHelper'\n\nclass HeatmapChart {\n private baseColour = '#1d70b8'\n\n private ragColours: string[] = ['#00703c', '#ffdd00', '#d4351c']\n\n private buckets: MatrixDashboardVisualisationBucket[] = []\n\n private bucketCount: number\n\n private onlyBucketColoursDefined: boolean\n\n private granularity: Granularity\n\n private responseData: DashboardDataResponse[]\n\n private data: MatrixChartData[] = []\n\n private definition: DashboardVisualisation\n\n private columns: DashboardVisualisationColumns\n\n private unit: UnitType\n\n private type: ChartType\n\n private dayDateFormat = 'DD/MM/YYYY'\n\n private hasRag = false\n\n private valueKey: string\n\n private options: MatrixDashboardVisualisationOptions = {}\n\n private label: string\n\n constructor(responseData: DashboardDataResponse[], granularity: Granularity, definition: DashboardVisualisation) {\n this.granularity = granularity\n this.initFromDefinition(definition)\n this.initFromResponseData(responseData)\n this.initBuckets()\n }\n\n private initFromResponseData = (responseData: DashboardDataResponse[]) => {\n this.hasRag = responseData[0][this.valueKey].rag !== undefined\n this.responseData = responseData\n }\n\n private initFromDefinition = (definition: DashboardVisualisation) => {\n this.definition = definition\n this.columns = definition.columns\n this.unit = this.columns.measures[0].unit ? this.columns.measures[0].unit : undefined\n this.type = this.definition.type.split('-')[0] as ChartType\n\n this.options = <MatrixDashboardVisualisationOptions>definition.options\n this.baseColour = this.options.baseColour || this.baseColour\n this.valueKey = this.columns.measures[1].id\n this.label = this.columns.measures[1].display\n this.onlyBucketColoursDefined = this.options?.buckets?.every(\n (bucket) => !bucket.max && !bucket.min && bucket.hexColour !== undefined,\n )\n }\n\n private initBuckets = () => {\n const { buckets } = this.options\n this.setBucketCount()\n this.initBucketColours()\n if (buckets) {\n if (this.onlyBucketColoursDefined) {\n this.initAutomaticThresholdBucket()\n } else {\n this.initCustomThresholdBuckets()\n }\n } else if (!this.hasRag) this.initAutomaticThresholdBucket()\n }\n\n private initCustomThresholdBuckets = () => {\n this.buckets = this.options.buckets.map((bucket, i) => {\n return {\n ...this.buckets[i],\n ...bucket,\n }\n })\n }\n\n /**\n * Initialises the bucket thresholds by defining the range between the min and max\n * and dividing into 3 equal parts\n */\n private initAutomaticThresholdBucket = () => {\n const { min, max, bucketSize } = this.setAutomaticThresholdSize()\n let maxValue = 0\n this.buckets = this.buckets.map((bucket, i) => {\n let minValue = min\n if (i !== 0) minValue = maxValue + 1\n maxValue = bucketSize * (i + 1)\n if (i === this.buckets.length - 1) maxValue = max\n\n return {\n hexColour: this.options?.buckets ? this.options.buckets[i]?.hexColour : bucket.hexColour,\n min: minValue,\n max: maxValue,\n }\n })\n }\n\n private initBucketColours = () => {\n const { useRagColours } = this.options\n if (useRagColours && this.bucketCount === 3) {\n this.buckets = Array.from(new Array(this.bucketCount)).map((d, i) => {\n return {\n hexColour: this.ragColours[i],\n }\n })\n } else {\n const alphaDivision = 1 / this.bucketCount\n this.buckets = Array.from(new Array(this.bucketCount)).map((d, i) => {\n const division = alphaDivision * (i + 1)\n return {\n hexColour: withAlphaHex(this.baseColour, division),\n }\n })\n }\n }\n\n private setAutomaticThresholdSize = () => {\n const values = this.responseData.map((resData) => Number(resData[this.valueKey].raw))\n const min = Math.min(...values)\n const max = Math.max(...values)\n const bucketSize = Math.ceil((max - min) / this.bucketCount)\n\n return {\n min,\n max,\n bucketSize,\n }\n }\n\n private setBucketCount = () => {\n const { buckets } = this.options\n if (this.hasRag) {\n this.bucketCount =\n Math.max(...this.responseData.map((resData: DashboardDataResponse) => resData[this.valueKey].rag)) + 1\n } else if (buckets) {\n this.bucketCount = buckets.length\n } else {\n this.bucketCount = 3\n }\n }\n\n private validateDefinition = () => {\n const { id, columns, type } = this.definition\n const errors = []\n\n // Validate measures\n if (columns.measures.length !== 2) {\n errors.push(`Measures should only have 2 columns defined. Only found ${columns.measures.length}`)\n } else if (type === DashboardVisualisationType.MATRIX_TIMESERIES) {\n if (columns.measures[0].id !== 'ts') {\n errors.push(`measure at index 0 has incorrect ID. Expected ID to be \"ts\". Found \"${columns.measures[0].id}\"`)\n }\n }\n\n // Throw the error\n if (errors.length) {\n const message = `Validation: Visualisaton definition: ID: ${id}, type: ${type}, errors: ${errors.join(',')}`\n throw new Error(message)\n }\n }\n\n private initTimeseriesData = () => {\n const timeBlockData = DatasetHelper.groupRowsByTimestamp(this.responseData)\n\n this.data = timeBlockData.map((tsData) => {\n const { raw, rag } = tsData[0][this.valueKey]\n const tsRaw = tsData[0].ts.raw\n\n const v = Number(raw)\n const r = rag !== undefined ? Number(tsData[0][this.valueKey].rag) : undefined\n let x\n let y\n\n switch (this.granularity) {\n case 'hourly':\n break\n case 'weekly':\n x = dayjs(tsRaw, this.dayDateFormat).format('ddd')\n y = dayjs(tsRaw, this.dayDateFormat).week()\n break\n case 'daily':\n x = dayjs(tsRaw, this.dayDateFormat).format('MMM YY')\n y = dayjs(tsRaw, this.dayDateFormat).format('D')\n break\n case 'monthly':\n {\n const ts = (<string>tsRaw).split(' ')\n x = ts[1]\n y = ts[0]\n }\n break\n case 'annually':\n x = 'year'\n y = <string>tsRaw\n break\n default:\n x = dayjs(tsRaw, this.dayDateFormat).format('MMM YY')\n y = dayjs(tsRaw, this.dayDateFormat).format('D')\n break\n }\n return { y, x, v, r }\n })\n }\n\n private binDataIntoBuckets = () => {\n this.data = this.data.map((d) => {\n const { v, r } = d\n let c\n if (r !== undefined) {\n c = this.buckets[r].hexColour\n } else {\n this.buckets.forEach((bucket) => {\n const { min, max } = bucket\n // First bucket\n if (!min && max && v <= max) {\n c = bucket.hexColour\n }\n // middle buckets\n if (min && v >= bucket.min && max && v <= bucket.max) {\n c = bucket.hexColour\n }\n // last bucket\n if (min && !max && v >= min) {\n c = bucket.hexColour\n }\n })\n }\n\n return { ...d, c }\n })\n }\n\n build = (): ChartData => {\n this.validateDefinition()\n this.initTimeseriesData()\n this.binDataIntoBuckets()\n\n return {\n type: this.type,\n unit: this.unit,\n timeseries: true,\n data: {\n datasets: [\n {\n label: this.label,\n data: this.data,\n },\n ],\n },\n }\n }\n}\n\nexport { HeatmapChart }\nexport default HeatmapChart\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Heatmap_exports", "__export", "HeatmapChart", "Heatmap_default", "__toCommonJS", "import_dayjs", "import_with_alpha_hex", "import_types", "import_datasetHelper", "responseData", "granularity", "definition", "bucket", "buckets", "min", "max", "bucketSize", "maxValue", "i", "minValue", "useRagColours", "d", "alphaDivision", "division", "values", "resData", "id", "columns", "type", "errors", "message", "timeBlockData", "DatasetHelper", "tsData", "raw", "rag", "tsRaw", "v", "r", "x", "y", "dayjs", "ts", "c"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/* eslint-disable prefer-destructuring */
|
|
2
|
+
import dayjs from 'dayjs'
|
|
3
|
+
import { withAlphaHex } from 'with-alpha-hex'
|
|
4
|
+
import { Granularity } from '../../../_inputs/granular-date-range/types'
|
|
5
|
+
import { DashboardDataResponse } from '../../../../types/Metrics'
|
|
6
|
+
import {
|
|
7
|
+
DashboardVisualisation,
|
|
8
|
+
DashboardVisualisationColumns,
|
|
9
|
+
DashboardVisualisationType,
|
|
10
|
+
MatrixDashboardVisualisationBucket,
|
|
11
|
+
MatrixDashboardVisualisationOptions,
|
|
12
|
+
} from '../../../_dashboards/dashboard/types'
|
|
13
|
+
import { ChartData, ChartType, MatrixChartData, UnitType } from '../../../../types/Charts'
|
|
14
|
+
import DatasetHelper from '../../../../utils/datasetHelper'
|
|
15
|
+
|
|
16
|
+
class HeatmapChart {
|
|
17
|
+
private baseColour = '#1d70b8'
|
|
18
|
+
|
|
19
|
+
private ragColours: string[] = ['#00703c', '#ffdd00', '#d4351c']
|
|
20
|
+
|
|
21
|
+
private buckets: MatrixDashboardVisualisationBucket[] = []
|
|
22
|
+
|
|
23
|
+
private bucketCount: number
|
|
24
|
+
|
|
25
|
+
private onlyBucketColoursDefined: boolean
|
|
26
|
+
|
|
27
|
+
private granularity: Granularity
|
|
28
|
+
|
|
29
|
+
private responseData: DashboardDataResponse[]
|
|
30
|
+
|
|
31
|
+
private data: MatrixChartData[] = []
|
|
32
|
+
|
|
33
|
+
private definition: DashboardVisualisation
|
|
34
|
+
|
|
35
|
+
private columns: DashboardVisualisationColumns
|
|
36
|
+
|
|
37
|
+
private unit: UnitType
|
|
38
|
+
|
|
39
|
+
private type: ChartType
|
|
40
|
+
|
|
41
|
+
private dayDateFormat = 'DD/MM/YYYY'
|
|
42
|
+
|
|
43
|
+
private hasRag = false
|
|
44
|
+
|
|
45
|
+
private valueKey: string
|
|
46
|
+
|
|
47
|
+
private options: MatrixDashboardVisualisationOptions = {}
|
|
48
|
+
|
|
49
|
+
private label: string
|
|
50
|
+
|
|
51
|
+
constructor(responseData: DashboardDataResponse[], granularity: Granularity, definition: DashboardVisualisation) {
|
|
52
|
+
this.granularity = granularity
|
|
53
|
+
this.initFromDefinition(definition)
|
|
54
|
+
this.initFromResponseData(responseData)
|
|
55
|
+
this.initBuckets()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private initFromResponseData = (responseData: DashboardDataResponse[]) => {
|
|
59
|
+
this.hasRag = responseData[0][this.valueKey].rag !== undefined
|
|
60
|
+
this.responseData = responseData
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private initFromDefinition = (definition: DashboardVisualisation) => {
|
|
64
|
+
this.definition = definition
|
|
65
|
+
this.columns = definition.columns
|
|
66
|
+
this.unit = this.columns.measures[0].unit ? this.columns.measures[0].unit : undefined
|
|
67
|
+
this.type = this.definition.type.split('-')[0] as ChartType
|
|
68
|
+
|
|
69
|
+
this.options = <MatrixDashboardVisualisationOptions>definition.options
|
|
70
|
+
this.baseColour = this.options.baseColour || this.baseColour
|
|
71
|
+
this.valueKey = this.columns.measures[1].id
|
|
72
|
+
this.label = this.columns.measures[1].display
|
|
73
|
+
this.onlyBucketColoursDefined = this.options?.buckets?.every(
|
|
74
|
+
(bucket) => !bucket.max && !bucket.min && bucket.hexColour !== undefined,
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private initBuckets = () => {
|
|
79
|
+
const { buckets } = this.options
|
|
80
|
+
this.setBucketCount()
|
|
81
|
+
this.initBucketColours()
|
|
82
|
+
if (buckets) {
|
|
83
|
+
if (this.onlyBucketColoursDefined) {
|
|
84
|
+
this.initAutomaticThresholdBucket()
|
|
85
|
+
} else {
|
|
86
|
+
this.initCustomThresholdBuckets()
|
|
87
|
+
}
|
|
88
|
+
} else if (!this.hasRag) this.initAutomaticThresholdBucket()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private initCustomThresholdBuckets = () => {
|
|
92
|
+
this.buckets = this.options.buckets.map((bucket, i) => {
|
|
93
|
+
return {
|
|
94
|
+
...this.buckets[i],
|
|
95
|
+
...bucket,
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Initialises the bucket thresholds by defining the range between the min and max
|
|
102
|
+
* and dividing into 3 equal parts
|
|
103
|
+
*/
|
|
104
|
+
private initAutomaticThresholdBucket = () => {
|
|
105
|
+
const { min, max, bucketSize } = this.setAutomaticThresholdSize()
|
|
106
|
+
let maxValue = 0
|
|
107
|
+
this.buckets = this.buckets.map((bucket, i) => {
|
|
108
|
+
let minValue = min
|
|
109
|
+
if (i !== 0) minValue = maxValue + 1
|
|
110
|
+
maxValue = bucketSize * (i + 1)
|
|
111
|
+
if (i === this.buckets.length - 1) maxValue = max
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
hexColour: this.options?.buckets ? this.options.buckets[i]?.hexColour : bucket.hexColour,
|
|
115
|
+
min: minValue,
|
|
116
|
+
max: maxValue,
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private initBucketColours = () => {
|
|
122
|
+
const { useRagColours } = this.options
|
|
123
|
+
if (useRagColours && this.bucketCount === 3) {
|
|
124
|
+
this.buckets = Array.from(new Array(this.bucketCount)).map((d, i) => {
|
|
125
|
+
return {
|
|
126
|
+
hexColour: this.ragColours[i],
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
} else {
|
|
130
|
+
const alphaDivision = 1 / this.bucketCount
|
|
131
|
+
this.buckets = Array.from(new Array(this.bucketCount)).map((d, i) => {
|
|
132
|
+
const division = alphaDivision * (i + 1)
|
|
133
|
+
return {
|
|
134
|
+
hexColour: withAlphaHex(this.baseColour, division),
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private setAutomaticThresholdSize = () => {
|
|
141
|
+
const values = this.responseData.map((resData) => Number(resData[this.valueKey].raw))
|
|
142
|
+
const min = Math.min(...values)
|
|
143
|
+
const max = Math.max(...values)
|
|
144
|
+
const bucketSize = Math.ceil((max - min) / this.bucketCount)
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
min,
|
|
148
|
+
max,
|
|
149
|
+
bucketSize,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private setBucketCount = () => {
|
|
154
|
+
const { buckets } = this.options
|
|
155
|
+
if (this.hasRag) {
|
|
156
|
+
this.bucketCount =
|
|
157
|
+
Math.max(...this.responseData.map((resData: DashboardDataResponse) => resData[this.valueKey].rag)) + 1
|
|
158
|
+
} else if (buckets) {
|
|
159
|
+
this.bucketCount = buckets.length
|
|
160
|
+
} else {
|
|
161
|
+
this.bucketCount = 3
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private validateDefinition = () => {
|
|
166
|
+
const { id, columns, type } = this.definition
|
|
167
|
+
const errors = []
|
|
168
|
+
|
|
169
|
+
// Validate measures
|
|
170
|
+
if (columns.measures.length !== 2) {
|
|
171
|
+
errors.push(`Measures should only have 2 columns defined. Only found ${columns.measures.length}`)
|
|
172
|
+
} else if (type === DashboardVisualisationType.MATRIX_TIMESERIES) {
|
|
173
|
+
if (columns.measures[0].id !== 'ts') {
|
|
174
|
+
errors.push(`measure at index 0 has incorrect ID. Expected ID to be "ts". Found "${columns.measures[0].id}"`)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Throw the error
|
|
179
|
+
if (errors.length) {
|
|
180
|
+
const message = `Validation: Visualisaton definition: ID: ${id}, type: ${type}, errors: ${errors.join(',')}`
|
|
181
|
+
throw new Error(message)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private initTimeseriesData = () => {
|
|
186
|
+
const timeBlockData = DatasetHelper.groupRowsByTimestamp(this.responseData)
|
|
187
|
+
|
|
188
|
+
this.data = timeBlockData.map((tsData) => {
|
|
189
|
+
const { raw, rag } = tsData[0][this.valueKey]
|
|
190
|
+
const tsRaw = tsData[0].ts.raw
|
|
191
|
+
|
|
192
|
+
const v = Number(raw)
|
|
193
|
+
const r = rag !== undefined ? Number(tsData[0][this.valueKey].rag) : undefined
|
|
194
|
+
let x
|
|
195
|
+
let y
|
|
196
|
+
|
|
197
|
+
switch (this.granularity) {
|
|
198
|
+
case 'hourly':
|
|
199
|
+
break
|
|
200
|
+
case 'weekly':
|
|
201
|
+
x = dayjs(tsRaw, this.dayDateFormat).format('ddd')
|
|
202
|
+
y = dayjs(tsRaw, this.dayDateFormat).week()
|
|
203
|
+
break
|
|
204
|
+
case 'daily':
|
|
205
|
+
x = dayjs(tsRaw, this.dayDateFormat).format('MMM YY')
|
|
206
|
+
y = dayjs(tsRaw, this.dayDateFormat).format('D')
|
|
207
|
+
break
|
|
208
|
+
case 'monthly':
|
|
209
|
+
{
|
|
210
|
+
const ts = (<string>tsRaw).split(' ')
|
|
211
|
+
x = ts[1]
|
|
212
|
+
y = ts[0]
|
|
213
|
+
}
|
|
214
|
+
break
|
|
215
|
+
case 'annually':
|
|
216
|
+
x = 'year'
|
|
217
|
+
y = <string>tsRaw
|
|
218
|
+
break
|
|
219
|
+
default:
|
|
220
|
+
x = dayjs(tsRaw, this.dayDateFormat).format('MMM YY')
|
|
221
|
+
y = dayjs(tsRaw, this.dayDateFormat).format('D')
|
|
222
|
+
break
|
|
223
|
+
}
|
|
224
|
+
return { y, x, v, r }
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private binDataIntoBuckets = () => {
|
|
229
|
+
this.data = this.data.map((d) => {
|
|
230
|
+
const { v, r } = d
|
|
231
|
+
let c
|
|
232
|
+
if (r !== undefined) {
|
|
233
|
+
c = this.buckets[r].hexColour
|
|
234
|
+
} else {
|
|
235
|
+
this.buckets.forEach((bucket) => {
|
|
236
|
+
const { min, max } = bucket
|
|
237
|
+
// First bucket
|
|
238
|
+
if (!min && max && v <= max) {
|
|
239
|
+
c = bucket.hexColour
|
|
240
|
+
}
|
|
241
|
+
// middle buckets
|
|
242
|
+
if (min && v >= bucket.min && max && v <= bucket.max) {
|
|
243
|
+
c = bucket.hexColour
|
|
244
|
+
}
|
|
245
|
+
// last bucket
|
|
246
|
+
if (min && !max && v >= min) {
|
|
247
|
+
c = bucket.hexColour
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return { ...d, c }
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
build = (): ChartData => {
|
|
257
|
+
this.validateDefinition()
|
|
258
|
+
this.initTimeseriesData()
|
|
259
|
+
this.binDataIntoBuckets()
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
type: this.type,
|
|
263
|
+
unit: this.unit,
|
|
264
|
+
timeseries: true,
|
|
265
|
+
data: {
|
|
266
|
+
datasets: [
|
|
267
|
+
{
|
|
268
|
+
label: this.label,
|
|
269
|
+
data: this.data,
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export { HeatmapChart }
|
|
278
|
+
export default HeatmapChart
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/* eslint-disable prefer-destructuring */
|
|
2
|
+
/* eslint-disable class-methods-use-this */
|
|
3
|
+
import ChartVisualisation from '../clientClass.mjs'
|
|
4
|
+
|
|
5
|
+
export default class MatrixChartVisualisation extends ChartVisualisation {
|
|
6
|
+
static getModuleName() {
|
|
7
|
+
return 'matrix-chart'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
initialise() {
|
|
11
|
+
this.setupCanvas()
|
|
12
|
+
this.settings = this.initSettings()
|
|
13
|
+
this.chartData = this.generateChartData(this.settings)
|
|
14
|
+
this.initChart(this.chartData)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
initSettings() {
|
|
18
|
+
return {
|
|
19
|
+
options: this.setOptions({ scaleType: 'category' }),
|
|
20
|
+
toolTipOptions: this.setToolTipOptions(),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setToolTipOptions() {
|
|
25
|
+
const ctx = this
|
|
26
|
+
return {
|
|
27
|
+
callbacks: {
|
|
28
|
+
title(context) {
|
|
29
|
+
const { raw } = context[0]
|
|
30
|
+
const title = `${raw.y} ${raw.x}`
|
|
31
|
+
return title
|
|
32
|
+
},
|
|
33
|
+
label(context) {
|
|
34
|
+
const { data, label: legend } = context.dataset
|
|
35
|
+
const dataValue = data[context.dataIndex]
|
|
36
|
+
const label = `${dataValue.y} ${dataValue.x}`
|
|
37
|
+
const value = `${dataValue.v}${ctx.suffix}`
|
|
38
|
+
ctx.setHoverValue({ label, value, legend, ctx })
|
|
39
|
+
return `${legend}: ${value}`
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setOptions({ scaleType }) {
|
|
46
|
+
return {
|
|
47
|
+
scales: this.setScales({ scaleType }),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
generateChartData(settings) {
|
|
52
|
+
const { options, plugins, pluginsOptions, toolTipOptions, hoverEvent } = settings
|
|
53
|
+
return {
|
|
54
|
+
type: this.type,
|
|
55
|
+
data: {
|
|
56
|
+
datasets: this.createDatasets(),
|
|
57
|
+
},
|
|
58
|
+
options: {
|
|
59
|
+
responsive: true,
|
|
60
|
+
maintainAspectRatio: false,
|
|
61
|
+
animation: {
|
|
62
|
+
duration: 0,
|
|
63
|
+
},
|
|
64
|
+
hover: {
|
|
65
|
+
animationDuration: 0,
|
|
66
|
+
},
|
|
67
|
+
...(options && options),
|
|
68
|
+
...(hoverEvent && hoverEvent),
|
|
69
|
+
plugins: {
|
|
70
|
+
legend: {
|
|
71
|
+
position: 'bottom',
|
|
72
|
+
display: false,
|
|
73
|
+
},
|
|
74
|
+
...(pluginsOptions && pluginsOptions),
|
|
75
|
+
datalabels: {
|
|
76
|
+
display: false,
|
|
77
|
+
},
|
|
78
|
+
tooltip: {
|
|
79
|
+
...this.setToolTip(),
|
|
80
|
+
...(toolTipOptions && toolTipOptions),
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
plugins: plugins && plugins.length ? [...plugins] : [],
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
createDatasets() {
|
|
89
|
+
const { datasets } = this.chartParams
|
|
90
|
+
return datasets.map((d) => {
|
|
91
|
+
const { label, data } = d
|
|
92
|
+
return {
|
|
93
|
+
label,
|
|
94
|
+
data,
|
|
95
|
+
backgroundColor(c) {
|
|
96
|
+
return c.raw.c
|
|
97
|
+
},
|
|
98
|
+
width: ({ chart }) => (chart.chartArea || {}).width / chart.scales.x.ticks.length - 1,
|
|
99
|
+
height: ({ chart }) => (chart.chartArea || {}).height / chart.scales.y.ticks.length - 1,
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setScales({ scaleType }) {
|
|
105
|
+
let xTime
|
|
106
|
+
let yTime
|
|
107
|
+
let xLabels
|
|
108
|
+
let yLabels
|
|
109
|
+
|
|
110
|
+
switch (scaleType) {
|
|
111
|
+
case 'time':
|
|
112
|
+
yTime = {
|
|
113
|
+
unit: 'week',
|
|
114
|
+
}
|
|
115
|
+
xTime = {
|
|
116
|
+
unit: 'day',
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
case 'category':
|
|
120
|
+
{
|
|
121
|
+
const { datasets } = this.chartParams
|
|
122
|
+
xLabels = [
|
|
123
|
+
...new Set(
|
|
124
|
+
datasets[0].data.map((d) => {
|
|
125
|
+
return d.x
|
|
126
|
+
}),
|
|
127
|
+
),
|
|
128
|
+
]
|
|
129
|
+
yLabels = [
|
|
130
|
+
...new Set(
|
|
131
|
+
datasets[0].data.map((d) => {
|
|
132
|
+
return d.y
|
|
133
|
+
}),
|
|
134
|
+
),
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
break
|
|
138
|
+
default:
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const grid = {
|
|
143
|
+
display: false,
|
|
144
|
+
drawBorder: false,
|
|
145
|
+
}
|
|
146
|
+
const ticks = {
|
|
147
|
+
padding: 1,
|
|
148
|
+
maxRotation: 0,
|
|
149
|
+
stepSize: 1,
|
|
150
|
+
}
|
|
151
|
+
const offset = true
|
|
152
|
+
const common = {
|
|
153
|
+
offset,
|
|
154
|
+
ticks,
|
|
155
|
+
grid,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
y: {
|
|
160
|
+
left: 'left',
|
|
161
|
+
...(scaleType && { type: scaleType }),
|
|
162
|
+
...(yLabels && { labels: yLabels }),
|
|
163
|
+
...(yTime && { time: yTime }),
|
|
164
|
+
...common,
|
|
165
|
+
},
|
|
166
|
+
x: {
|
|
167
|
+
position: 'top',
|
|
168
|
+
...(scaleType && { type: scaleType }),
|
|
169
|
+
...(xLabels && { labels: xLabels }),
|
|
170
|
+
...(xTime && { time: xTime }),
|
|
171
|
+
...common,
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var G=Object.create;var b=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var j=(a,t)=>{for(var e in t)b(a,e,{get:t[e],enumerable:!0})},w=(a,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of A(t))!H.call(a,o)&&o!==e&&b(a,o,{get:()=>t[o],enumerable:!(s=$(t,o))||s.enumerable});return a};var p=(a,t,e)=>(e=a!=null?G(F(a)):{},w(t||!a||!a.__esModule?b(e,"default",{value:a,enumerable:!0}):e,a)),v=a=>w(b({},"__esModule",{value:!0}),a);var Q={};j(Q,{createChart:()=>M,createMatrixChart:()=>S,createTimeseriesCharts:()=>L,default:()=>P});module.exports=v(Q);var T=p(require("dayjs")),x=p(require("dayjs/plugin/weekOfYear")),D=p(require("../../utils/datasetHelper")),f=p(require("../_dashboards/dashboard-list/utils")),B=require("../_inputs/granular-date-range/types"),k=p(require("./chart/heatmap/Heatmap"));T.default.extend(x.default);const M=(a,t)=>{let e,s,o;const{dataSetRows:r,snapshotData:l}=O(a,t);return r.length&&(s=Y(a,l),e=z(a,r),o=R(a,r)),{details:o,table:e,chart:s}},L=(a,t)=>{let e,s,o;const{latestData:r,dataSetRows:l,timeseriesData:u}=g(a,t);return l.length&&(s=N(a,u),e=V(a,u),o=R(a,r,!0)),{details:o,table:e,chart:s}},S=(a,t,e)=>{let s,o,r,l=B.Granularity.DAILY;Object.keys(e).forEach(h=>{h.includes("granularity")&&(l=e[h])});const{latestData:u,dataSetRows:n,timeseriesData:i}=g(a,t);return n.length&&(o=new k.default(i,l,a).build(),s=V(a,i),r=R(a,u,!0)),{details:r,table:s,chart:o}},O=(a,t)=>{const e=D.default.getLastestDataset(t),s=D.default.getDatasetRows(a,e),o=D.default.filterRowsByDisplayColumns(a,s,!0);return{dataSetRows:s,snapshotData:o}},g=(a,t)=>{const e=D.default.getLastestDataset(t),s=D.default.getDatasetRows(a,t),o=D.default.filterRowsByDisplayColumns(a,s,!0);return{latestData:e,dataSetRows:s,timeseriesData:o}},R=(a,t,e=!1)=>{const s=[],o=W(a,t,e);return t[0]?.ts&&s.push({label:"Values for:",value:t[0]?.ts.raw}),{meta:s,headlines:o}},W=(a,t,e=!1)=>{const s=[],{columns:o}=a,{measures:r}=o,l=!!r.find(d=>d.axis);let u,n,i,h;return e?(n=r.find(d=>d.id!=="ts"),n&&(h=`${t[0].ts.raw}`,i=+t[0][n.id].raw,u={label:h,value:i})):(n=l?r.find(d=>d.axis&&d.axis==="y"):r[0],n&&(h=`Total ${n.display.toLowerCase()}`,i=t.reduce((d,c)=>d+ +c[n.id].raw,0),u={label:h,value:i})),s.push(u),s},Y=(a,t)=>{const{type:e,columns:s}=a,{measures:o}=s,r=!!o.find(i=>i.axis);let l,u,n;return r?{labels:l,unit:u,datasets:n}=U(s,t):{labels:l,unit:u,datasets:n}=E(s,t),{type:e,unit:u,data:{labels:l,datasets:n}}},E=(a,t)=>{const{keys:e,measures:s}=a,o=s.map(n=>n.display),r=e[e.length-1]?.id,l=s[0].unit?s[0].unit:void 0,u=t.map(n=>{const i=n[r]?`${n[r].raw}`:"All",h=s.map(c=>{const m=c.id;return n[m]?+n[m].raw:0}),d=h.reduce((c,m)=>c+m,0);return{label:i,data:h,total:d}});return{labels:o,unit:l,datasets:u}},U=(a,t)=>{const{measures:e,keys:s}=a,o=e.find(d=>d.axis==="x"),r=e.find(d=>d.axis==="y"),l=r?.unit||void 0,u=D.default.getGroupKey(s,t),n=u?D.default.groupRowsByKey(t,u.id):[t],i=n[0]?.map(d=>`${d[o.id].raw}`),h=n.map(d=>{const c=d.map(m=>+m[r.id].raw);return{label:u?`${d[0][u.id].raw}`:r.display,data:c,total:c.reduce((m,C)=>m+C,0)}});return{labels:i,unit:l,datasets:h}},z=(a,t)=>{const{columns:e}=a,{keys:s,measures:o}=e,l=[...s,...o].map(i=>({text:i.display})),u=D.default.filterRowsByDisplayColumns(a,t,!0),n=f.default.createTableRows(u);return{head:l,rows:n}},N=(a,t)=>{const{columns:e}=a,{keys:s,measures:o}=e,r=o[0].unit?o[0].unit:void 0,l=a.type.split("-")[0],n=D.default.getGroupKey(s,t).id,i=D.default.groupRowsByTimestamp(t),h=i.map(m=>m[0].ts.raw),d=i[0].length,c=[];for(let m=0;m<d;m+=1){const C=i.map(y=>+y[m][o[1].id].raw),J=C.reduce((y,K)=>y+K,0),I=i[0][m][n].raw;c.push({data:C,label:I,total:J})}return{type:l,unit:r,timeseries:!0,data:{labels:h,datasets:c}}},V=(a,t)=>{const{columns:e}=a,{keys:s,measures:o}=e;let r=t.flat(),l=[...o];if(t.length>1){const i=l.findIndex(c=>c.id==="ts"),h=l[i];l.splice(i,1),l=[...s.filter(c=>c.id!=="ts"),...l],l.unshift(h)}else r=D.default.filterRowsByDisplayColumns(a,r);const u=l.map(i=>({text:i.display})),n=f.default.createTableRows(r);return{head:u,rows:n}};var P={createChart:M,createTimeseriesCharts:L,createMatrixChart:S};0&&(module.exports={createChart,createMatrixChart,createTimeseriesCharts});
|
|
2
2
|
//# sourceMappingURL=utils.js.map
|