@ministryofjustice/hmpps-digital-prison-reporting-frontend 4.29.4 → 4.30.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.
Files changed (31) hide show
  1. package/dpr/components/_dashboards/dashboard-visualisation/types.js.map +2 -2
  2. package/dpr/components/_dashboards/dashboard-visualisation/types.ts +1 -0
  3. package/dpr/components/_dashboards/dashboard-visualisation/view.njk +12 -7
  4. package/dpr/components/_dashboards/scorecard/utils.js +3 -2
  5. package/dpr/components/_dashboards/scorecard/utils.js.map +2 -2
  6. package/dpr/components/_dashboards/scorecard/utils.test.ts +9 -1
  7. package/dpr/components/_dashboards/scorecard/utils.ts +2 -1
  8. package/dpr/components/user-reports/bookmarks/utils.js +2 -0
  9. package/dpr/components/user-reports/bookmarks/utils.js.map +2 -2
  10. package/dpr/components/user-reports/bookmarks/utils.ts +2 -0
  11. package/dpr/data/types.d.js.map +1 -1
  12. package/dpr/data/types.d.ts +0 -1
  13. package/dpr/routes/journeys/request-report/status/controller.js +2 -0
  14. package/dpr/routes/journeys/request-report/status/controller.js.map +2 -2
  15. package/dpr/routes/journeys/request-report/status/controller.ts +2 -0
  16. package/dpr/routes/journeys/view-report/async/controller.js +2 -0
  17. package/dpr/routes/journeys/view-report/async/controller.js.map +2 -2
  18. package/dpr/routes/journeys/view-report/async/controller.ts +2 -0
  19. package/dpr/routes/journeys/view-report/async/dashboard/tests.cy.js +27 -1
  20. package/dpr/routes/journeys/view-report/async/dashboard/tests.cy.js.map +2 -2
  21. package/dpr/routes/journeys/view-report/async/dashboard/tests.cy.ts +34 -1
  22. package/dpr/routes/journeys/view-report/async/dashboard/utils.js +46 -4
  23. package/dpr/routes/journeys/view-report/async/dashboard/utils.js.map +2 -2
  24. package/dpr/routes/journeys/view-report/async/dashboard/utils.ts +47 -2
  25. package/dpr/routes/journeys/view-report/sync/dashboard/utils.js +9 -1
  26. package/dpr/routes/journeys/view-report/sync/dashboard/utils.js.map +2 -2
  27. package/dpr/routes/journeys/view-report/sync/dashboard/utils.ts +9 -1
  28. package/dpr/services/featureFlagService.js +3 -3
  29. package/dpr/services/featureFlagService.js.map +2 -2
  30. package/dpr/services/featureFlagService.ts +10 -3
  31. package/package.json +1 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../dpr/components/_dashboards/dashboard-visualisation/types.ts"],
4
- "sourcesContent": ["import z from 'zod'\nimport { components } from '../../../types/api'\nimport { Scorecard, ScorecardGroup } from '../scorecard/types'\nimport { MatrixChartData } from '../../_charts/chart/heatmap/types'\nimport { ChartDetails } from '../../../types/Charts'\nimport DashboardVisualisationSchemas from './Validate'\nimport { BarDefinitionMeasure } from '../../_charts/chart/bar/types'\nimport { DoughnutDefinitionMeasure } from '../../_charts/chart/doughnut/types'\nimport { LineDefinitionMeasure } from '../../_charts/chart/line/types'\nimport { LineTimeseriesDefinitionMeasure } from '../../_charts/chart/line-timeseries/types'\nimport { BarTimeseriesDefinitionMeasure } from '../../_charts/chart/bar-timeseries/types'\nimport { ChartOptionsType } from '../../_charts/chart/chart-config'\nimport { PartialDate } from '../../_filters/types'\n\nexport interface DashboardSection {\n id: string\n title?: string\n description?: string\n visualisations?: DashboardVisualisation[]\n}\n\nexport interface DashboardVisualisation {\n id: string\n type: components['schemas']['DashboardVisualisationDefinition']['type']\n title?: string | undefined\n description?: string | undefined\n data:\n | Scorecard\n | Scorecard[]\n | ScorecardGroup[]\n | DashboardVisualisatonCardData\n | DashboardVisualisationTable\n | undefined\n}\n\nexport interface DashboardVisualisatonCardData {\n chart?: DashboardVisualisationData | undefined\n table?: MoJTable | undefined\n details?: ChartDetails | undefined\n}\n\nexport interface DashboardVisualisationData {\n type: DashboardVisualisationType\n options?: DashboardVisualisationDataOptions\n data: DashboardVisualisationDataValues\n}\n\ninterface DashboardVisualisationDataOptions {\n height?: number\n unit?: components['schemas']['DashboardVisualisationColumnDefinition']['unit']\n timeseries?: boolean\n}\n\nexport interface DashboardVisualisationDataValues {\n labels?: string[]\n datasets: DashboardVisualisationDataSet[]\n axis?: 'x' | 'y'\n config: ChartOptionsType\n partialDate?: PartialDate | undefined\n}\n\nexport interface DashboardVisualisationDataSet {\n label: string\n data: number[] | MatrixChartData[]\n total?: number\n}\n\nexport interface DashboardVisualisationTable {\n table: MoJTable\n ts?: string\n}\n\nexport interface MoJTable {\n head: MoJTableHead[]\n rows: MoJTableRow[][]\n}\n\nexport interface MoJTableRow {\n text?: string\n html?: string\n}\n\nexport interface MoJTableHead {\n text?: string\n html?: string\n}\n\nexport enum DashboardVisualisationType {\n LIST = 'list',\n DONUT = 'doughnut',\n BAR = 'bar',\n LINE = 'line',\n MATRIX = 'matrix',\n MATRIX_TIMESERIES = 'matrix-timeseries',\n BAR_TIMESERIES = 'bar-timeseries',\n LINE_TIMESERIES = 'line-timeseries',\n SCORECARD = 'scorecard',\n SCORECARD_GROUP = 'scorecard-group',\n}\n\nexport type DashboardVisualisationOptions = ListDashboardVisualisationOptions | BucketDashboardVisualisationOptions\n\nexport interface ListDashboardVisualisationOptions {\n showLatest?: boolean\n columnsAsList?: boolean\n}\n\nexport interface BucketDashboardVisualisationOptions {\n useRagColour?: boolean\n buckets?: DashboardVisualisationBucket[]\n baseColour?: string\n}\n\nexport interface DashboardVisualisationBucket {\n min?: number | undefined\n max?: number | undefined\n hexColour?: string | undefined\n}\n\nexport type VisualisationDefinitionType = z.infer<typeof DashboardVisualisationSchemas.DashboardVisualisationSchema>\nexport type VisualisationDefinitionKey = z.infer<typeof DashboardVisualisationSchemas.DashboardVisualisationKeySchema>\nexport type VisualisationDefinitionMeasure = z.infer<\n typeof DashboardVisualisationSchemas.DashboardVisualisationMeasureSchema\n>\n\nexport type ChartMeasure =\n | BarDefinitionMeasure[]\n | DoughnutDefinitionMeasure[]\n | LineDefinitionMeasure[]\n | VisualisationDefinitionMeasure[]\n\nexport type TimeseriesChartMeasure = LineTimeseriesDefinitionMeasure[] | BarTimeseriesDefinitionMeasure[]\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuFO,IAAK,6BAAL,kBAAKA,gCAAL;AACL,EAAAA,4BAAA,UAAO;AACP,EAAAA,4BAAA,WAAQ;AACR,EAAAA,4BAAA,SAAM;AACN,EAAAA,4BAAA,UAAO;AACP,EAAAA,4BAAA,YAAS;AACT,EAAAA,4BAAA,uBAAoB;AACpB,EAAAA,4BAAA,oBAAiB;AACjB,EAAAA,4BAAA,qBAAkB;AAClB,EAAAA,4BAAA,eAAY;AACZ,EAAAA,4BAAA,qBAAkB;AAVR,SAAAA;AAAA,GAAA;",
4
+ "sourcesContent": ["import z from 'zod'\nimport { components } from '../../../types/api'\nimport { Scorecard, ScorecardGroup } from '../scorecard/types'\nimport { MatrixChartData } from '../../_charts/chart/heatmap/types'\nimport { ChartDetails } from '../../../types/Charts'\nimport DashboardVisualisationSchemas from './Validate'\nimport { BarDefinitionMeasure } from '../../_charts/chart/bar/types'\nimport { DoughnutDefinitionMeasure } from '../../_charts/chart/doughnut/types'\nimport { LineDefinitionMeasure } from '../../_charts/chart/line/types'\nimport { LineTimeseriesDefinitionMeasure } from '../../_charts/chart/line-timeseries/types'\nimport { BarTimeseriesDefinitionMeasure } from '../../_charts/chart/bar-timeseries/types'\nimport { ChartOptionsType } from '../../_charts/chart/chart-config'\nimport { PartialDate } from '../../_filters/types'\n\nexport interface DashboardSection {\n id: string\n title?: string\n description?: string\n visualisations?: DashboardVisualisation[]\n}\n\nexport interface DashboardVisualisation {\n id: string\n type: components['schemas']['DashboardVisualisationDefinition']['type']\n title?: string | undefined\n description?: string | undefined\n isEnabled: boolean\n data:\n | Scorecard\n | Scorecard[]\n | ScorecardGroup[]\n | DashboardVisualisatonCardData\n | DashboardVisualisationTable\n | undefined\n}\n\nexport interface DashboardVisualisatonCardData {\n chart?: DashboardVisualisationData | undefined\n table?: MoJTable | undefined\n details?: ChartDetails | undefined\n}\n\nexport interface DashboardVisualisationData {\n type: DashboardVisualisationType\n options?: DashboardVisualisationDataOptions\n data: DashboardVisualisationDataValues\n}\n\ninterface DashboardVisualisationDataOptions {\n height?: number\n unit?: components['schemas']['DashboardVisualisationColumnDefinition']['unit']\n timeseries?: boolean\n}\n\nexport interface DashboardVisualisationDataValues {\n labels?: string[]\n datasets: DashboardVisualisationDataSet[]\n axis?: 'x' | 'y'\n config: ChartOptionsType\n partialDate?: PartialDate | undefined\n}\n\nexport interface DashboardVisualisationDataSet {\n label: string\n data: number[] | MatrixChartData[]\n total?: number\n}\n\nexport interface DashboardVisualisationTable {\n table: MoJTable\n ts?: string\n}\n\nexport interface MoJTable {\n head: MoJTableHead[]\n rows: MoJTableRow[][]\n}\n\nexport interface MoJTableRow {\n text?: string\n html?: string\n}\n\nexport interface MoJTableHead {\n text?: string\n html?: string\n}\n\nexport enum DashboardVisualisationType {\n LIST = 'list',\n DONUT = 'doughnut',\n BAR = 'bar',\n LINE = 'line',\n MATRIX = 'matrix',\n MATRIX_TIMESERIES = 'matrix-timeseries',\n BAR_TIMESERIES = 'bar-timeseries',\n LINE_TIMESERIES = 'line-timeseries',\n SCORECARD = 'scorecard',\n SCORECARD_GROUP = 'scorecard-group',\n}\n\nexport type DashboardVisualisationOptions = ListDashboardVisualisationOptions | BucketDashboardVisualisationOptions\n\nexport interface ListDashboardVisualisationOptions {\n showLatest?: boolean\n columnsAsList?: boolean\n}\n\nexport interface BucketDashboardVisualisationOptions {\n useRagColour?: boolean\n buckets?: DashboardVisualisationBucket[]\n baseColour?: string\n}\n\nexport interface DashboardVisualisationBucket {\n min?: number | undefined\n max?: number | undefined\n hexColour?: string | undefined\n}\n\nexport type VisualisationDefinitionType = z.infer<typeof DashboardVisualisationSchemas.DashboardVisualisationSchema>\nexport type VisualisationDefinitionKey = z.infer<typeof DashboardVisualisationSchemas.DashboardVisualisationKeySchema>\nexport type VisualisationDefinitionMeasure = z.infer<\n typeof DashboardVisualisationSchemas.DashboardVisualisationMeasureSchema\n>\n\nexport type ChartMeasure =\n | BarDefinitionMeasure[]\n | DoughnutDefinitionMeasure[]\n | LineDefinitionMeasure[]\n | VisualisationDefinitionMeasure[]\n\nexport type TimeseriesChartMeasure = LineTimeseriesDefinitionMeasure[] | BarTimeseriesDefinitionMeasure[]\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwFO,IAAK,6BAAL,kBAAKA,gCAAL;AACL,EAAAA,4BAAA,UAAO;AACP,EAAAA,4BAAA,WAAQ;AACR,EAAAA,4BAAA,SAAM;AACN,EAAAA,4BAAA,UAAO;AACP,EAAAA,4BAAA,YAAS;AACT,EAAAA,4BAAA,uBAAoB;AACpB,EAAAA,4BAAA,oBAAiB;AACjB,EAAAA,4BAAA,qBAAkB;AAClB,EAAAA,4BAAA,eAAY;AACZ,EAAAA,4BAAA,qBAAkB;AAVR,SAAAA;AAAA,GAAA;",
6
6
  "names": ["DashboardVisualisationType"]
7
7
  }
@@ -24,6 +24,7 @@ export interface DashboardVisualisation {
24
24
  type: components['schemas']['DashboardVisualisationDefinition']['type']
25
25
  title?: string | undefined
26
26
  description?: string | undefined
27
+ isEnabled: boolean
27
28
  data:
28
29
  | Scorecard
29
30
  | Scorecard[]
@@ -8,6 +8,7 @@
8
8
  {% set title = visualisation.title %}
9
9
  {% set description = visualisation.description %}
10
10
  {% set data = visualisation.data %}
11
+ {% set isEnabled = visualisation.isEnabled %}
11
12
 
12
13
  <div class="dashboard-visualisation-container" id="{{ id }}-dash-section-visualisation" tabindex="0">
13
14
  {% if title %}
@@ -18,18 +19,22 @@
18
19
  <p class="govuk-body">{{ description }}</p>
19
20
  {% endif %}
20
21
 
21
- {% if type === 'scorecard-group' %}
22
+ {% if not isEnabled %}
23
+ <p class="govuk-body">This visualisation type is not supported yet.</p>
24
+ {% else %}
25
+ {% if type === 'scorecard-group' %}
22
26
 
23
- {{ dprScoreCardGroup(id, data) }}
27
+ {{ dprScoreCardGroup(id, data) }}
24
28
 
25
- {% elif type === 'list' %}
29
+ {% elif type === 'list' %}
26
30
 
27
- {{ dprDashboardList(id, data) }}
31
+ {{ dprDashboardList(id, data) }}
28
32
 
29
- {% else %}
33
+ {% else %}
30
34
 
31
- {{ dprChartCard(id, data) }}
32
-
35
+ {{ dprChartCard(id, data) }}
36
+
37
+ {% endif %}
33
38
  {% endif %}
34
39
 
35
40
  </div>
@@ -23,7 +23,7 @@ __export(utils_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(utils_exports);
25
25
  var import_types = require("../dashboard-visualisation/types");
26
- const mergeScorecardsIntoGroup = (visualisations) => {
26
+ const mergeScorecardsIntoGroup = (visualisations, isEnabled) => {
27
27
  const groupedScorecardIndexes = visualisations.reduce((acc, vis, i) => {
28
28
  if (vis.type === import_types.DashboardVisualisationType.SCORECARD) acc.push(i);
29
29
  return acc;
@@ -46,7 +46,8 @@ const mergeScorecardsIntoGroup = (visualisations) => {
46
46
  visualisations.splice(spliceAtIndex, 0, {
47
47
  id: `${spliceAtIndex}`,
48
48
  type: import_types.DashboardVisualisationType.SCORECARD_GROUP,
49
- data: [{ scorecards: scorecardGroup }]
49
+ data: [{ scorecards: scorecardGroup }],
50
+ isEnabled
50
51
  });
51
52
  }
52
53
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../dpr/components/_dashboards/scorecard/utils.ts"],
4
- "sourcesContent": ["import { DashboardVisualisation, DashboardVisualisationType } from '../dashboard-visualisation/types'\nimport { Scorecard } from './types'\n\nexport const mergeScorecardsIntoGroup = (visualisations: DashboardVisualisation[]) => {\n const groupedScorecardIndexes: number[][] = visualisations\n // get scorecard indexes\n .reduce((acc: number[], vis: DashboardVisualisation, i: number) => {\n if (vis.type === DashboardVisualisationType.SCORECARD) acc.push(i)\n return acc\n }, [])\n // group adjacent indexes\n .reduce((r: number[][], n) => {\n const lastSubArray = r[r.length - 1]\n if (!lastSubArray || lastSubArray[lastSubArray.length - 1] !== n - 1) r.push([])\n r[r.length - 1].push(n)\n return r\n }, [])\n\n groupedScorecardIndexes.reverse().forEach((group: number[]) => {\n const spliceAtIndex = group[0]\n const scorecardGroup: Scorecard[] = group\n .map((scIndex: number) => {\n return visualisations[scIndex].data as Scorecard\n })\n .filter((scorecard: Scorecard) => !!scorecard)\n\n while (group.length) {\n const i = group.pop()\n if (i !== undefined) visualisations.splice(i, 1)\n }\n\n if (scorecardGroup.length) {\n visualisations.splice(spliceAtIndex, 0, {\n id: `${spliceAtIndex}`,\n type: DashboardVisualisationType.SCORECARD_GROUP,\n data: [{ scorecards: scorecardGroup }],\n })\n }\n })\n\n return visualisations\n}\n\nexport default {\n mergeScorecardsIntoGroup,\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAmE;AAG5D,MAAM,2BAA2B,CAAC,mBAA6C;AACpF,QAAM,0BAAsC,eAEzC,OAAO,CAAC,KAAe,KAA6B,MAAc;AACjE,QAAI,IAAI,SAAS,wCAA2B,UAAW,KAAI,KAAK,CAAC;AACjE,WAAO;AAAA,EACT,GAAG,CAAC,CAAC,EAEJ,OAAO,CAAC,GAAe,MAAM;AAC5B,UAAM,eAAe,EAAE,EAAE,SAAS,CAAC;AACnC,QAAI,CAAC,gBAAgB,aAAa,aAAa,SAAS,CAAC,MAAM,IAAI,EAAG,GAAE,KAAK,CAAC,CAAC;AAC/E,MAAE,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC;AACtB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEP,0BAAwB,QAAQ,EAAE,QAAQ,CAAC,UAAoB;AAC7D,UAAM,gBAAgB,MAAM,CAAC;AAC7B,UAAM,iBAA8B,MACjC,IAAI,CAAC,YAAoB;AACxB,aAAO,eAAe,OAAO,EAAE;AAAA,IACjC,CAAC,EACA,OAAO,CAAC,cAAyB,CAAC,CAAC,SAAS;AAE/C,WAAO,MAAM,QAAQ;AACnB,YAAM,IAAI,MAAM,IAAI;AACpB,UAAI,MAAM,OAAW,gBAAe,OAAO,GAAG,CAAC;AAAA,IACjD;AAEA,QAAI,eAAe,QAAQ;AACzB,qBAAe,OAAO,eAAe,GAAG;AAAA,QACtC,IAAI,GAAG,aAAa;AAAA,QACpB,MAAM,wCAA2B;AAAA,QACjC,MAAM,CAAC,EAAE,YAAY,eAAe,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,IAAO,gBAAQ;AAAA,EACb;AACF;",
4
+ "sourcesContent": ["import { DashboardVisualisation, DashboardVisualisationType } from '../dashboard-visualisation/types'\nimport { Scorecard } from './types'\n\nexport const mergeScorecardsIntoGroup = (visualisations: DashboardVisualisation[], isEnabled: boolean) => {\n const groupedScorecardIndexes: number[][] = visualisations\n // get scorecard indexes\n .reduce((acc: number[], vis: DashboardVisualisation, i: number) => {\n if (vis.type === DashboardVisualisationType.SCORECARD) acc.push(i)\n return acc\n }, [])\n // group adjacent indexes\n .reduce((r: number[][], n) => {\n const lastSubArray = r[r.length - 1]\n if (!lastSubArray || lastSubArray[lastSubArray.length - 1] !== n - 1) r.push([])\n r[r.length - 1].push(n)\n return r\n }, [])\n\n groupedScorecardIndexes.reverse().forEach((group: number[]) => {\n const spliceAtIndex = group[0]\n const scorecardGroup: Scorecard[] = group\n .map((scIndex: number) => {\n return visualisations[scIndex].data as Scorecard\n })\n .filter((scorecard: Scorecard) => !!scorecard)\n\n while (group.length) {\n const i = group.pop()\n if (i !== undefined) visualisations.splice(i, 1)\n }\n\n if (scorecardGroup.length) {\n visualisations.splice(spliceAtIndex, 0, {\n id: `${spliceAtIndex}`,\n type: DashboardVisualisationType.SCORECARD_GROUP,\n data: [{ scorecards: scorecardGroup }],\n isEnabled,\n })\n }\n })\n\n return visualisations\n}\n\nexport default {\n mergeScorecardsIntoGroup,\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAmE;AAG5D,MAAM,2BAA2B,CAAC,gBAA0C,cAAuB;AACxG,QAAM,0BAAsC,eAEzC,OAAO,CAAC,KAAe,KAA6B,MAAc;AACjE,QAAI,IAAI,SAAS,wCAA2B,UAAW,KAAI,KAAK,CAAC;AACjE,WAAO;AAAA,EACT,GAAG,CAAC,CAAC,EAEJ,OAAO,CAAC,GAAe,MAAM;AAC5B,UAAM,eAAe,EAAE,EAAE,SAAS,CAAC;AACnC,QAAI,CAAC,gBAAgB,aAAa,aAAa,SAAS,CAAC,MAAM,IAAI,EAAG,GAAE,KAAK,CAAC,CAAC;AAC/E,MAAE,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC;AACtB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEP,0BAAwB,QAAQ,EAAE,QAAQ,CAAC,UAAoB;AAC7D,UAAM,gBAAgB,MAAM,CAAC;AAC7B,UAAM,iBAA8B,MACjC,IAAI,CAAC,YAAoB;AACxB,aAAO,eAAe,OAAO,EAAE;AAAA,IACjC,CAAC,EACA,OAAO,CAAC,cAAyB,CAAC,CAAC,SAAS;AAE/C,WAAO,MAAM,QAAQ;AACnB,YAAM,IAAI,MAAM,IAAI;AACpB,UAAI,MAAM,OAAW,gBAAe,OAAO,GAAG,CAAC;AAAA,IACjD;AAEA,QAAI,eAAe,QAAQ;AACzB,qBAAe,OAAO,eAAe,GAAG;AAAA,QACtC,IAAI,GAAG,aAAa;AAAA,QACpB,MAAM,wCAA2B;AAAA,QACjC,MAAM,CAAC,EAAE,YAAY,eAAe,CAAC;AAAA,QACrC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,IAAO,gBAAQ;AAAA,EACb;AACF;",
6
6
  "names": []
7
7
  }
@@ -53,33 +53,39 @@ describe('ScorecardUtils', () => {
53
53
  id: '1',
54
54
  type: DashboardVisualisationType.SCORECARD,
55
55
  data: scorecardData1,
56
+ isEnabled: true,
56
57
  },
57
58
  {
58
59
  id: '2',
59
60
  type: DashboardVisualisationType.SCORECARD,
60
61
  data: scorecardData2,
62
+ isEnabled: true,
61
63
  },
62
64
  {
63
65
  id: '3',
64
66
  type: DashboardVisualisationType.BAR,
65
67
  data: {} as unknown as DashboardVisualisatonCardData,
68
+ isEnabled: true,
66
69
  },
67
70
  {
68
71
  id: '4',
69
72
  type: DashboardVisualisationType.SCORECARD,
70
73
  data: scorecardData1,
74
+ isEnabled: true,
71
75
  },
72
76
  {
73
77
  id: '5',
74
78
  type: DashboardVisualisationType.SCORECARD,
75
79
  data: scorecardData2,
80
+ isEnabled: true,
76
81
  },
77
82
  ]
78
83
 
79
- const dashboardVis = ScorecardUtils.mergeScorecardsIntoGroup(visualistationData)
84
+ const dashboardVis = ScorecardUtils.mergeScorecardsIntoGroup(visualistationData, true)
80
85
  expect(dashboardVis).toEqual([
81
86
  {
82
87
  id: '0',
88
+ isEnabled: true,
83
89
  type: 'scorecard-group',
84
90
  data: [
85
91
  {
@@ -120,11 +126,13 @@ describe('ScorecardUtils', () => {
120
126
  },
121
127
  {
122
128
  id: '3',
129
+ isEnabled: true,
123
130
  type: 'bar',
124
131
  data: {},
125
132
  },
126
133
  {
127
134
  id: '3',
135
+ isEnabled: true,
128
136
  type: 'scorecard-group',
129
137
  data: [
130
138
  {
@@ -1,7 +1,7 @@
1
1
  import { DashboardVisualisation, DashboardVisualisationType } from '../dashboard-visualisation/types'
2
2
  import { Scorecard } from './types'
3
3
 
4
- export const mergeScorecardsIntoGroup = (visualisations: DashboardVisualisation[]) => {
4
+ export const mergeScorecardsIntoGroup = (visualisations: DashboardVisualisation[], isEnabled: boolean) => {
5
5
  const groupedScorecardIndexes: number[][] = visualisations
6
6
  // get scorecard indexes
7
7
  .reduce((acc: number[], vis: DashboardVisualisation, i: number) => {
@@ -34,6 +34,7 @@ export const mergeScorecardsIntoGroup = (visualisations: DashboardVisualisation[
34
34
  id: `${spliceAtIndex}`,
35
35
  type: DashboardVisualisationType.SCORECARD_GROUP,
36
36
  data: [{ scorecards: scorecardGroup }],
37
+ isEnabled,
37
38
  })
38
39
  }
39
40
  })
@@ -34,6 +34,7 @@ __export(utils_exports, {
34
34
  renderBookmarkList: () => renderBookmarkList
35
35
  });
36
36
  module.exports = __toCommonJS(utils_exports);
37
+ var import_node = require("@sentry/node");
37
38
  var import_UserReports = require("../../../types/UserReports");
38
39
  var import_utils = __toESM(require("../../show-more/utils"));
39
40
  var import_logger = __toESM(require("../../../utils/logger"));
@@ -143,6 +144,7 @@ const mapBookmarkIdsToDefinition = async (bookmarks, res, token, services) => {
143
144
  });
144
145
  }
145
146
  } catch (error) {
147
+ (0, import_node.captureException)(error);
146
148
  import_logger.default.warn(`Failed to map bookmark for: Report ${reportId}, variant ${id}`);
147
149
  const { dprUser } = import_localsHelper.default.getValues(res);
148
150
  await services.bookmarkService.removeBookmark(dprUser.id, id, reportId);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../dpr/components/user-reports/bookmarks/utils.ts"],
4
- "sourcesContent": ["import { Response } from 'express'\nimport { BookmarkService } from '../../../services'\nimport { BookmarkedReportData, BookmarkStoreData } from '../../../types/Bookmark'\nimport { FormattedBookmarkData, LoadType, ReportType } from '../../../types/UserReports'\nimport { Services } from '../../../types/Services'\nimport ShowMoreUtils from '../../show-more/utils'\nimport logger from '../../../utils/logger'\nimport DefinitionUtils from '../../../utils/definitionUtils'\nimport { createListItemProduct, createListActions, setInitialHref } from '../../../utils/reportListsHelper'\nimport LocalsHelper from '../../../utils/localsHelper'\nimport { ReportStoreConfig } from '../../../types/ReportStore'\n\nexport const formatBookmarks = async (bookmarksData: BookmarkedReportData[]): Promise<FormattedBookmarkData[]> => {\n return bookmarksData\n .map((report: BookmarkedReportData) => {\n return formatBookmark(report)\n })\n .sort((a, b) => a.text.localeCompare(b.text))\n}\n\nexport const formatBookmark = (bookmarkData: BookmarkedReportData): FormattedBookmarkData => {\n const reportData: BookmarkedReportData = JSON.parse(JSON.stringify(bookmarkData))\n const { id, name, description, href, reportName, type } = reportData\n\n return {\n id,\n reportName,\n text: name,\n description,\n href,\n type: type as ReportType,\n }\n}\n\nconst formatTable = async (\n bookmarksData: BookmarkedReportData[],\n bookmarkService: BookmarkService,\n csrfToken: string,\n userId: string,\n maxRows?: number,\n nestedBaseUrl?: string,\n) => {\n const userConfig = await bookmarkService.getState(userId)\n const rows = await Promise.all(\n bookmarksData\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(async (bookmark: BookmarkedReportData) => {\n return formatTableData(bookmark, bookmarkService, csrfToken, userConfig, nestedBaseUrl)\n }),\n )\n\n return {\n rows: maxRows ? rows.slice(0, maxRows) : rows,\n head: [\n { text: 'Product', classes: 'dpr-req-product-head' },\n { text: 'Description', classes: 'dpr-bm-description-head' },\n { text: 'Actions', classes: 'dpr-bm-actions-head' },\n ],\n }\n}\n\nconst formatTableData = async (\n bookmarksData: BookmarkedReportData,\n bookmarkService: BookmarkService,\n csrfToken: string,\n userConfig: ReportStoreConfig,\n nestedBaseUrl?: string,\n) => {\n const { description, reportName, reportId, id, href, name, type, loadType } = bookmarksData\n const bookmarkHtml = await bookmarkService.createBookMarkToggleHtml({\n userConfig,\n reportId,\n id,\n csrfToken,\n ctxId: 'bookmark-list',\n reportType: type,\n // We don't have the data here, and missing reports should never get into bookmarked, viewed or requested\n isMissing: false,\n nestedBaseUrl,\n })\n return [\n {\n html: createListItemProduct(reportName, name, type),\n },\n { html: ShowMoreUtils.createShowMoreHtml(description), classes: 'dpr-req-cell' },\n {\n html: createListActions(href, type, loadType, bookmarkHtml),\n classes: 'dpr-req-cell dpr-req-cell__status',\n },\n ]\n}\n\nconst mapBookmarkIdsToDefinition = async (\n bookmarks: BookmarkStoreData[],\n res: Response,\n token: string,\n services: Services,\n): Promise<BookmarkedReportData[]> => {\n const bookmarkData: BookmarkedReportData[] = []\n const { definitionsPath } = LocalsHelper.getValues(res)\n\n await Promise.all(\n bookmarks.map(async (bookmark) => {\n let definition\n const { reportId, id, automatic, type } = bookmark\n const reportType: ReportType = type ? (type as ReportType) : ReportType.REPORT\n\n try {\n let name = ''\n let description = ''\n let loadType = LoadType.ASYNC\n const href = setInitialHref(loadType, reportType, reportId, id, res)\n\n const procuctSummary = await DefinitionUtils.getReportSummary(\n reportId,\n services.reportingService,\n token,\n definitionsPath,\n )\n const reportName = procuctSummary.name\n\n if (reportType === ReportType.REPORT) {\n const variantSummary = procuctSummary.variants.find((v) => v.id === id)\n definition = await services.reportingService.getDefinition(token, reportId, id, definitionsPath)\n name = definition.variant.name\n description = definition.variant.description || definition.description || ''\n loadType = (variantSummary?.loadType as LoadType) || loadType\n }\n\n if (reportType === ReportType.DASHBOARD) {\n definition = await services.dashboardService.getDefinition(token, reportId, id, definitionsPath)\n name = definition.name\n description = definition.description || ''\n }\n\n if (definition) {\n bookmarkData.push({\n reportId,\n id,\n reportName,\n name,\n description,\n type: reportType,\n href,\n loadType,\n automatic,\n })\n }\n } catch (error) {\n // DPD has been deleted so API throws error\n logger.warn(`Failed to map bookmark for: Report ${reportId}, variant ${id}`)\n const { dprUser } = LocalsHelper.getValues(res)\n await services.bookmarkService.removeBookmark(dprUser.id, id, reportId)\n }\n }),\n )\n return bookmarkData\n}\n\nexport const renderBookmarkList = async ({\n services,\n maxRows = 20,\n res,\n}: {\n services: Services\n maxRows?: number\n res: Response\n}) => {\n const { token, csrfToken, dprUser, bookmarks, nestedBaseUrl } = LocalsHelper.getValues(res)\n const bookmarksData: BookmarkedReportData[] = await mapBookmarkIdsToDefinition(bookmarks, res, token, services)\n\n let formatted = await formatBookmarks(bookmarksData)\n const formattedCount = formatted.length\n\n if (maxRows) formatted = formatted.slice(0, maxRows)\n const tableData = await formatTable(\n bookmarksData,\n services.bookmarkService,\n csrfToken,\n dprUser.id,\n maxRows,\n nestedBaseUrl,\n )\n\n const head = {\n ...(formatted.length && { href: '/dpr/my-reports/bookmarks/list' }),\n ...(!formatted.length && { emptyMessage: 'You have 0 bookmarked reports' }),\n }\n\n const total = {\n amount: formattedCount,\n shown: formattedCount > maxRows ? maxRows : formattedCount,\n max: maxRows,\n }\n\n const result = {\n head,\n tableData,\n total,\n csrfToken,\n type: 'bookmark',\n }\n\n return result\n}\n\nexport default {\n renderBookmarkList,\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Response } from 'express'\nimport { captureException } from '@sentry/node'\nimport { BookmarkService } from '../../../services'\nimport { BookmarkedReportData, BookmarkStoreData } from '../../../types/Bookmark'\nimport { FormattedBookmarkData, LoadType, ReportType } from '../../../types/UserReports'\nimport { Services } from '../../../types/Services'\nimport ShowMoreUtils from '../../show-more/utils'\nimport logger from '../../../utils/logger'\nimport DefinitionUtils from '../../../utils/definitionUtils'\nimport { createListItemProduct, createListActions, setInitialHref } from '../../../utils/reportListsHelper'\nimport LocalsHelper from '../../../utils/localsHelper'\nimport { ReportStoreConfig } from '../../../types/ReportStore'\n\nexport const formatBookmarks = async (bookmarksData: BookmarkedReportData[]): Promise<FormattedBookmarkData[]> => {\n return bookmarksData\n .map((report: BookmarkedReportData) => {\n return formatBookmark(report)\n })\n .sort((a, b) => a.text.localeCompare(b.text))\n}\n\nexport const formatBookmark = (bookmarkData: BookmarkedReportData): FormattedBookmarkData => {\n const reportData: BookmarkedReportData = JSON.parse(JSON.stringify(bookmarkData))\n const { id, name, description, href, reportName, type } = reportData\n\n return {\n id,\n reportName,\n text: name,\n description,\n href,\n type: type as ReportType,\n }\n}\n\nconst formatTable = async (\n bookmarksData: BookmarkedReportData[],\n bookmarkService: BookmarkService,\n csrfToken: string,\n userId: string,\n maxRows?: number,\n nestedBaseUrl?: string,\n) => {\n const userConfig = await bookmarkService.getState(userId)\n const rows = await Promise.all(\n bookmarksData\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(async (bookmark: BookmarkedReportData) => {\n return formatTableData(bookmark, bookmarkService, csrfToken, userConfig, nestedBaseUrl)\n }),\n )\n\n return {\n rows: maxRows ? rows.slice(0, maxRows) : rows,\n head: [\n { text: 'Product', classes: 'dpr-req-product-head' },\n { text: 'Description', classes: 'dpr-bm-description-head' },\n { text: 'Actions', classes: 'dpr-bm-actions-head' },\n ],\n }\n}\n\nconst formatTableData = async (\n bookmarksData: BookmarkedReportData,\n bookmarkService: BookmarkService,\n csrfToken: string,\n userConfig: ReportStoreConfig,\n nestedBaseUrl?: string,\n) => {\n const { description, reportName, reportId, id, href, name, type, loadType } = bookmarksData\n const bookmarkHtml = await bookmarkService.createBookMarkToggleHtml({\n userConfig,\n reportId,\n id,\n csrfToken,\n ctxId: 'bookmark-list',\n reportType: type,\n // We don't have the data here, and missing reports should never get into bookmarked, viewed or requested\n isMissing: false,\n nestedBaseUrl,\n })\n return [\n {\n html: createListItemProduct(reportName, name, type),\n },\n { html: ShowMoreUtils.createShowMoreHtml(description), classes: 'dpr-req-cell' },\n {\n html: createListActions(href, type, loadType, bookmarkHtml),\n classes: 'dpr-req-cell dpr-req-cell__status',\n },\n ]\n}\n\nconst mapBookmarkIdsToDefinition = async (\n bookmarks: BookmarkStoreData[],\n res: Response,\n token: string,\n services: Services,\n): Promise<BookmarkedReportData[]> => {\n const bookmarkData: BookmarkedReportData[] = []\n const { definitionsPath } = LocalsHelper.getValues(res)\n\n await Promise.all(\n bookmarks.map(async (bookmark) => {\n let definition\n const { reportId, id, automatic, type } = bookmark\n const reportType: ReportType = type ? (type as ReportType) : ReportType.REPORT\n\n try {\n let name = ''\n let description = ''\n let loadType = LoadType.ASYNC\n const href = setInitialHref(loadType, reportType, reportId, id, res)\n\n const procuctSummary = await DefinitionUtils.getReportSummary(\n reportId,\n services.reportingService,\n token,\n definitionsPath,\n )\n const reportName = procuctSummary.name\n\n if (reportType === ReportType.REPORT) {\n const variantSummary = procuctSummary.variants.find((v) => v.id === id)\n definition = await services.reportingService.getDefinition(token, reportId, id, definitionsPath)\n name = definition.variant.name\n description = definition.variant.description || definition.description || ''\n loadType = (variantSummary?.loadType as LoadType) || loadType\n }\n\n if (reportType === ReportType.DASHBOARD) {\n definition = await services.dashboardService.getDefinition(token, reportId, id, definitionsPath)\n name = definition.name\n description = definition.description || ''\n }\n\n if (definition) {\n bookmarkData.push({\n reportId,\n id,\n reportName,\n name,\n description,\n type: reportType,\n href,\n loadType,\n automatic,\n })\n }\n } catch (error) {\n captureException(error)\n // DPD has been deleted so API throws error\n logger.warn(`Failed to map bookmark for: Report ${reportId}, variant ${id}`)\n const { dprUser } = LocalsHelper.getValues(res)\n await services.bookmarkService.removeBookmark(dprUser.id, id, reportId)\n }\n }),\n )\n return bookmarkData\n}\n\nexport const renderBookmarkList = async ({\n services,\n maxRows = 20,\n res,\n}: {\n services: Services\n maxRows?: number\n res: Response\n}) => {\n const { token, csrfToken, dprUser, bookmarks, nestedBaseUrl } = LocalsHelper.getValues(res)\n const bookmarksData: BookmarkedReportData[] = await mapBookmarkIdsToDefinition(bookmarks, res, token, services)\n\n let formatted = await formatBookmarks(bookmarksData)\n const formattedCount = formatted.length\n\n if (maxRows) formatted = formatted.slice(0, maxRows)\n const tableData = await formatTable(\n bookmarksData,\n services.bookmarkService,\n csrfToken,\n dprUser.id,\n maxRows,\n nestedBaseUrl,\n )\n\n const head = {\n ...(formatted.length && { href: '/dpr/my-reports/bookmarks/list' }),\n ...(!formatted.length && { emptyMessage: 'You have 0 bookmarked reports' }),\n }\n\n const total = {\n amount: formattedCount,\n shown: formattedCount > maxRows ? maxRows : formattedCount,\n max: maxRows,\n }\n\n const result = {\n head,\n tableData,\n total,\n csrfToken,\n type: 'bookmark',\n }\n\n return result\n}\n\nexport default {\n renderBookmarkList,\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["ShowMoreUtils", "LocalsHelper", "DefinitionUtils", "logger"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { Response } from 'express'
2
+ import { captureException } from '@sentry/node'
2
3
  import { BookmarkService } from '../../../services'
3
4
  import { BookmarkedReportData, BookmarkStoreData } from '../../../types/Bookmark'
4
5
  import { FormattedBookmarkData, LoadType, ReportType } from '../../../types/UserReports'
@@ -147,6 +148,7 @@ const mapBookmarkIdsToDefinition = async (
147
148
  })
148
149
  }
149
150
  } catch (error) {
151
+ captureException(error)
150
152
  // DPD has been deleted so API throws error
151
153
  logger.warn(`Failed to map bookmark for: Report ${reportId}, variant ${id}`)
152
154
  const { dprUser } = LocalsHelper.getValues(res)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../dpr/data/types.d.ts"],
4
- "sourcesContent": ["import AgentConfig from './agentConfig'\nimport Dict = NodeJS.Dict\n\nexport interface GetRequest {\n path?: string\n query?: object\n headers?: Record<string, string>\n responseType?: string\n raw?: boolean\n token: string\n}\n\nexport interface FeatureFlagConfig {\n namespace: string\n token: string\n url: string\n}\n\nexport interface ApiConfig {\n url: string\n agent: AgentConfig\n}\n\nexport interface Count {\n count: number\n}\n\nexport interface ListWithWarnings {\n data: Array<Dict<string>>\n warnings: Warnings\n}\n\nexport interface Warnings {\n noDataAvailable?: string | undefined\n}\n\nexport interface FieldValuesRequest {\n token: string\n definitionName: string\n variantName: string\n fieldName: string\n prefix: string\n definitionsPath?: string\n}\n\nexport interface AsyncRequestQuery {\n sortColumn: string\n sortedAsc: boolean\n dataProductDefinitionsPath: string\n [key: string]: string | boolean\n}\n\ninterface filter {\n [filterId: string]: string\n}\n"],
4
+ "sourcesContent": ["import AgentConfig from './agentConfig'\nimport Dict = NodeJS.Dict\n\nexport interface GetRequest {\n path?: string\n query?: object\n headers?: Record<string, string>\n responseType?: string\n raw?: boolean\n token: string\n}\n\nexport interface FeatureFlagConfig {\n token: string\n url: string\n}\n\nexport interface ApiConfig {\n url: string\n agent: AgentConfig\n}\n\nexport interface Count {\n count: number\n}\n\nexport interface ListWithWarnings {\n data: Array<Dict<string>>\n warnings: Warnings\n}\n\nexport interface Warnings {\n noDataAvailable?: string | undefined\n}\n\nexport interface FieldValuesRequest {\n token: string\n definitionName: string\n variantName: string\n fieldName: string\n prefix: string\n definitionsPath?: string\n}\n\nexport interface AsyncRequestQuery {\n sortColumn: string\n sortedAsc: boolean\n dataProductDefinitionsPath: string\n [key: string]: string | boolean\n}\n\ninterface filter {\n [filterId: string]: string\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -11,7 +11,6 @@ export interface GetRequest {
11
11
  }
12
12
 
13
13
  export interface FeatureFlagConfig {
14
- namespace: string
15
14
  token: string
16
15
  url: string
17
16
  }
@@ -32,6 +32,7 @@ __export(controller_exports, {
32
32
  default: () => controller_default
33
33
  });
34
34
  module.exports = __toCommonJS(controller_exports);
35
+ var import_node = require("@sentry/node");
35
36
  var import_utils = __toESM(require("./utils"));
36
37
  var import_utils2 = __toESM(require("../../../../components/user-reports/requested/utils"));
37
38
  var import_ErrorHandler = __toESM(require("../../../../utils/ErrorHandler"));
@@ -69,6 +70,7 @@ class RequestStatusController {
69
70
  const response = await import_utils2.default.getRequestStatus({ req, res, services: this.services });
70
71
  res.send({ status: response.status });
71
72
  } catch (error) {
73
+ (0, import_node.captureException)(error);
72
74
  res.send({ status: "FAILED" });
73
75
  }
74
76
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../dpr/routes/journeys/request-report/status/controller.ts"],
4
- "sourcesContent": ["import { RequestHandler } from 'express'\nimport { Services } from '../../../../types/Services'\nimport AsyncPollingUtils from './utils'\nimport AsyncRequestListUtils from '../../../../components/user-reports/requested/utils'\nimport ErrorHandler from '../../../../utils/ErrorHandler'\n\nclass RequestStatusController {\n layoutPath: string\n\n services: Services\n\n constructor(layoutPath: string, services: Services) {\n this.layoutPath = layoutPath\n this.services = services\n }\n\n // Render status page\n GET: RequestHandler = async (req, res, next) => {\n try {\n const pollingRenderData = await AsyncPollingUtils.renderPolling({\n req,\n res,\n services: this.services,\n next,\n })\n res.render(`dpr/routes/journeys/request-report/status/view`, {\n layoutPath: this.layoutPath,\n ...pollingRenderData,\n })\n } catch (error) {\n req.body ??= {}\n req.body.title = 'Failed to retrieve report status'\n req.body.errorDescription = 'We were unable to retrieve the report status:'\n req.body.error = new ErrorHandler(error).formatError()\n next(error)\n }\n }\n\n // Poll request status\n POST: RequestHandler = async (req, res, _next) => {\n try {\n const response = await AsyncRequestListUtils.getRequestStatus({ req, res, services: this.services })\n res.send({ status: response.status })\n } catch (error) {\n res.send({ status: 'FAILED' })\n }\n }\n}\n\nexport { RequestStatusController }\nexport default RequestStatusController\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAA8B;AAC9B,IAAAA,gBAAkC;AAClC,0BAAyB;AAEzB,MAAM,wBAAwB;AAAA,EAC5B;AAAA,EAEA;AAAA,EAEA,YAAY,YAAoB,UAAoB;AAClD,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,MAAsB,OAAO,KAAK,KAAK,SAAS;AAC9C,QAAI;AACF,YAAM,oBAAoB,MAAM,aAAAC,QAAkB,cAAc;AAAA,QAC9D;AAAA,QACA;AAAA,QACA,UAAU,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AACD,UAAI,OAAO,kDAAkD;AAAA,QAC3D,YAAY,KAAK;AAAA,QACjB,GAAG;AAAA,MACL,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,SAAS,CAAC;AACd,UAAI,KAAK,QAAQ;AACjB,UAAI,KAAK,mBAAmB;AAC5B,UAAI,KAAK,QAAQ,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AACrD,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA;AAAA,EAGA,OAAuB,OAAO,KAAK,KAAK,UAAU;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,cAAAC,QAAsB,iBAAiB,EAAE,KAAK,KAAK,UAAU,KAAK,SAAS,CAAC;AACnG,UAAI,KAAK,EAAE,QAAQ,SAAS,OAAO,CAAC;AAAA,IACtC,SAAS,OAAO;AACd,UAAI,KAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;AAGA,IAAO,qBAAQ;",
4
+ "sourcesContent": ["import { RequestHandler } from 'express'\nimport { captureException } from '@sentry/node'\nimport { Services } from '../../../../types/Services'\nimport AsyncPollingUtils from './utils'\nimport AsyncRequestListUtils from '../../../../components/user-reports/requested/utils'\nimport ErrorHandler from '../../../../utils/ErrorHandler'\n\nclass RequestStatusController {\n layoutPath: string\n\n services: Services\n\n constructor(layoutPath: string, services: Services) {\n this.layoutPath = layoutPath\n this.services = services\n }\n\n // Render status page\n GET: RequestHandler = async (req, res, next) => {\n try {\n const pollingRenderData = await AsyncPollingUtils.renderPolling({\n req,\n res,\n services: this.services,\n next,\n })\n res.render(`dpr/routes/journeys/request-report/status/view`, {\n layoutPath: this.layoutPath,\n ...pollingRenderData,\n })\n } catch (error) {\n req.body ??= {}\n req.body.title = 'Failed to retrieve report status'\n req.body.errorDescription = 'We were unable to retrieve the report status:'\n req.body.error = new ErrorHandler(error).formatError()\n next(error)\n }\n }\n\n // Poll request status\n POST: RequestHandler = async (req, res, _next) => {\n try {\n const response = await AsyncRequestListUtils.getRequestStatus({ req, res, services: this.services })\n res.send({ status: response.status })\n } catch (error) {\n captureException(error)\n res.send({ status: 'FAILED' })\n }\n }\n}\n\nexport { RequestStatusController }\nexport default RequestStatusController\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiC;AAEjC,mBAA8B;AAC9B,IAAAA,gBAAkC;AAClC,0BAAyB;AAEzB,MAAM,wBAAwB;AAAA,EAC5B;AAAA,EAEA;AAAA,EAEA,YAAY,YAAoB,UAAoB;AAClD,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,MAAsB,OAAO,KAAK,KAAK,SAAS;AAC9C,QAAI;AACF,YAAM,oBAAoB,MAAM,aAAAC,QAAkB,cAAc;AAAA,QAC9D;AAAA,QACA;AAAA,QACA,UAAU,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AACD,UAAI,OAAO,kDAAkD;AAAA,QAC3D,YAAY,KAAK;AAAA,QACjB,GAAG;AAAA,MACL,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,SAAS,CAAC;AACd,UAAI,KAAK,QAAQ;AACjB,UAAI,KAAK,mBAAmB;AAC5B,UAAI,KAAK,QAAQ,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AACrD,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA;AAAA,EAGA,OAAuB,OAAO,KAAK,KAAK,UAAU;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,cAAAC,QAAsB,iBAAiB,EAAE,KAAK,KAAK,UAAU,KAAK,SAAS,CAAC;AACnG,UAAI,KAAK,EAAE,QAAQ,SAAS,OAAO,CAAC;AAAA,IACtC,SAAS,OAAO;AACd,wCAAiB,KAAK;AACtB,UAAI,KAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;AAGA,IAAO,qBAAQ;",
6
6
  "names": ["import_utils", "AsyncPollingUtils", "ErrorHandler", "AsyncRequestListUtils"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { RequestHandler } from 'express'
2
+ import { captureException } from '@sentry/node'
2
3
  import { Services } from '../../../../types/Services'
3
4
  import AsyncPollingUtils from './utils'
4
5
  import AsyncRequestListUtils from '../../../../components/user-reports/requested/utils'
@@ -42,6 +43,7 @@ class RequestStatusController {
42
43
  const response = await AsyncRequestListUtils.getRequestStatus({ req, res, services: this.services })
43
44
  res.send({ status: response.status })
44
45
  } catch (error) {
46
+ captureException(error)
45
47
  res.send({ status: 'FAILED' })
46
48
  }
47
49
  }
@@ -32,6 +32,7 @@ __export(controller_exports, {
32
32
  default: () => controller_default
33
33
  });
34
34
  module.exports = __toCommonJS(controller_exports);
35
+ var import_node = require("@sentry/node");
35
36
  var import_ErrorHandler = __toESM(require("../../../../utils/ErrorHandler"));
36
37
  var import_utils = __toESM(require("../../../../components/user-reports/utils"));
37
38
  var import_filtersTypeEnum = require("../../../../components/_filters/filtersTypeEnum");
@@ -52,6 +53,7 @@ class AsyncController {
52
53
  });
53
54
  res.send({ isExpired: response });
54
55
  } catch (error) {
56
+ (0, import_node.captureException)(error);
55
57
  res.send({ status: "FAILED" });
56
58
  }
57
59
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../dpr/routes/journeys/view-report/async/controller.ts"],
4
- "sourcesContent": ["import { RequestHandler } from 'express'\nimport ErrorHandler from '../../../../utils/ErrorHandler'\nimport { Services } from '../../../../types/Services'\nimport UserReportsListUtils from '../../../../components/user-reports/utils'\nimport { FiltersType } from '../../../../components/_filters/filtersTypeEnum'\nimport PersonalisationUtils from '../../../../utils/Personalisation/personalisationUtils'\n\nclass AsyncController {\n layoutPath: string\n\n services: Services\n\n constructor(layoutPath: string, services: Services) {\n this.layoutPath = layoutPath\n this.services = services\n }\n\n POST: RequestHandler = async (req, res, _next) => {\n try {\n const response = await UserReportsListUtils.updateExpiredStatus({\n req,\n res,\n services: this.services,\n })\n res.send({ isExpired: response })\n } catch (error) {\n res.send({ status: 'FAILED' })\n }\n }\n\n saveDefaultFilterValues: RequestHandler = async (req, res, next) => {\n try {\n PersonalisationUtils.saveDefaults(FiltersType.INTERACTIVE, res, req, this.services)\n res.redirect(`${req.baseUrl}?defaultsSaved=true`)\n } catch (error) {\n req.body = {\n title: 'Failed to save defaults',\n error: new ErrorHandler(error).formatError(),\n ...(req.body && { ...req.body }),\n }\n next(error)\n }\n }\n\n removeDefaultFilterValues: RequestHandler = async (req, res, next) => {\n try {\n PersonalisationUtils.removeDefaults(FiltersType.INTERACTIVE, res, req, this.services)\n res.redirect(req.baseUrl)\n } catch (error) {\n req.body = {\n title: 'Failed to remove defaults',\n error: new ErrorHandler(error).formatError(),\n ...(req.body && { ...req.body }),\n }\n next(error)\n }\n }\n}\n\nexport { AsyncController }\nexport default AsyncController\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAyB;AAEzB,mBAAiC;AACjC,6BAA4B;AAC5B,kCAAiC;AAEjC,MAAM,gBAAgB;AAAA,EACpB;AAAA,EAEA;AAAA,EAEA,YAAY,YAAoB,UAAoB;AAClD,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,OAAuB,OAAO,KAAK,KAAK,UAAU;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,aAAAA,QAAqB,oBAAoB;AAAA,QAC9D;AAAA,QACA;AAAA,QACA,UAAU,KAAK;AAAA,MACjB,CAAC;AACD,UAAI,KAAK,EAAE,WAAW,SAAS,CAAC;AAAA,IAClC,SAAS,OAAO;AACd,UAAI,KAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,0BAA0C,OAAO,KAAK,KAAK,SAAS;AAClE,QAAI;AACF,kCAAAC,QAAqB,aAAa,mCAAY,aAAa,KAAK,KAAK,KAAK,QAAQ;AAClF,UAAI,SAAS,GAAG,IAAI,OAAO,qBAAqB;AAAA,IAClD,SAAS,OAAO;AACd,UAAI,OAAO;AAAA,QACT,OAAO;AAAA,QACP,OAAO,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AAAA,QAC3C,GAAI,IAAI,QAAQ,EAAE,GAAG,IAAI,KAAK;AAAA,MAChC;AACA,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,4BAA4C,OAAO,KAAK,KAAK,SAAS;AACpE,QAAI;AACF,kCAAAD,QAAqB,eAAe,mCAAY,aAAa,KAAK,KAAK,KAAK,QAAQ;AACpF,UAAI,SAAS,IAAI,OAAO;AAAA,IAC1B,SAAS,OAAO;AACd,UAAI,OAAO;AAAA,QACT,OAAO;AAAA,QACP,OAAO,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AAAA,QAC3C,GAAI,IAAI,QAAQ,EAAE,GAAG,IAAI,KAAK;AAAA,MAChC;AACA,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;AAGA,IAAO,qBAAQ;",
4
+ "sourcesContent": ["import { RequestHandler } from 'express'\nimport { captureException } from '@sentry/node'\nimport ErrorHandler from '../../../../utils/ErrorHandler'\nimport { Services } from '../../../../types/Services'\nimport UserReportsListUtils from '../../../../components/user-reports/utils'\nimport { FiltersType } from '../../../../components/_filters/filtersTypeEnum'\nimport PersonalisationUtils from '../../../../utils/Personalisation/personalisationUtils'\n\nclass AsyncController {\n layoutPath: string\n\n services: Services\n\n constructor(layoutPath: string, services: Services) {\n this.layoutPath = layoutPath\n this.services = services\n }\n\n POST: RequestHandler = async (req, res, _next) => {\n try {\n const response = await UserReportsListUtils.updateExpiredStatus({\n req,\n res,\n services: this.services,\n })\n res.send({ isExpired: response })\n } catch (error) {\n captureException(error)\n res.send({ status: 'FAILED' })\n }\n }\n\n saveDefaultFilterValues: RequestHandler = async (req, res, next) => {\n try {\n PersonalisationUtils.saveDefaults(FiltersType.INTERACTIVE, res, req, this.services)\n res.redirect(`${req.baseUrl}?defaultsSaved=true`)\n } catch (error) {\n req.body = {\n title: 'Failed to save defaults',\n error: new ErrorHandler(error).formatError(),\n ...(req.body && { ...req.body }),\n }\n next(error)\n }\n }\n\n removeDefaultFilterValues: RequestHandler = async (req, res, next) => {\n try {\n PersonalisationUtils.removeDefaults(FiltersType.INTERACTIVE, res, req, this.services)\n res.redirect(req.baseUrl)\n } catch (error) {\n req.body = {\n title: 'Failed to remove defaults',\n error: new ErrorHandler(error).formatError(),\n ...(req.body && { ...req.body }),\n }\n next(error)\n }\n }\n}\n\nexport { AsyncController }\nexport default AsyncController\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiC;AACjC,0BAAyB;AAEzB,mBAAiC;AACjC,6BAA4B;AAC5B,kCAAiC;AAEjC,MAAM,gBAAgB;AAAA,EACpB;AAAA,EAEA;AAAA,EAEA,YAAY,YAAoB,UAAoB;AAClD,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,OAAuB,OAAO,KAAK,KAAK,UAAU;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,aAAAA,QAAqB,oBAAoB;AAAA,QAC9D;AAAA,QACA;AAAA,QACA,UAAU,KAAK;AAAA,MACjB,CAAC;AACD,UAAI,KAAK,EAAE,WAAW,SAAS,CAAC;AAAA,IAClC,SAAS,OAAO;AACd,wCAAiB,KAAK;AACtB,UAAI,KAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,0BAA0C,OAAO,KAAK,KAAK,SAAS;AAClE,QAAI;AACF,kCAAAC,QAAqB,aAAa,mCAAY,aAAa,KAAK,KAAK,KAAK,QAAQ;AAClF,UAAI,SAAS,GAAG,IAAI,OAAO,qBAAqB;AAAA,IAClD,SAAS,OAAO;AACd,UAAI,OAAO;AAAA,QACT,OAAO;AAAA,QACP,OAAO,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AAAA,QAC3C,GAAI,IAAI,QAAQ,EAAE,GAAG,IAAI,KAAK;AAAA,MAChC;AACA,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,4BAA4C,OAAO,KAAK,KAAK,SAAS;AACpE,QAAI;AACF,kCAAAD,QAAqB,eAAe,mCAAY,aAAa,KAAK,KAAK,KAAK,QAAQ;AACpF,UAAI,SAAS,IAAI,OAAO;AAAA,IAC1B,SAAS,OAAO;AACd,UAAI,OAAO;AAAA,QACT,OAAO;AAAA,QACP,OAAO,IAAI,oBAAAC,QAAa,KAAK,EAAE,YAAY;AAAA,QAC3C,GAAI,IAAI,QAAQ,EAAE,GAAG,IAAI,KAAK;AAAA,MAChC;AACA,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AACF;AAGA,IAAO,qBAAQ;",
6
6
  "names": ["UserReportsListUtils", "PersonalisationUtils", "ErrorHandler"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { RequestHandler } from 'express'
2
+ import { captureException } from '@sentry/node'
2
3
  import ErrorHandler from '../../../../utils/ErrorHandler'
3
4
  import { Services } from '../../../../types/Services'
4
5
  import UserReportsListUtils from '../../../../components/user-reports/utils'
@@ -24,6 +25,7 @@ class AsyncController {
24
25
  })
25
26
  res.send({ isExpired: response })
26
27
  } catch (error) {
28
+ captureException(error)
27
29
  res.send({ status: 'FAILED' })
28
30
  }
29
31
  }
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ var import_appStateUtils = require("test-app/routes/integrationTests/appStateUtils");
2
3
  var import_cypressUtils = require("../../../../../../../cypress-tests/cypressUtils");
3
4
  context("Viewing a report", () => {
4
5
  const path = "/embedded/platform/";
@@ -8,7 +9,9 @@ context("Viewing a report", () => {
8
9
  cy.task("stubTestDashboard8");
9
10
  cy.task("stubDashboardSuccessResult20");
10
11
  });
11
- it("should mark the dashboard as recently viewed", () => {
12
+ it("should mark the dashboard as recently viewed and not show viz", () => {
13
+ cy.task("stubFeatureFlagsDisabled");
14
+ (0, import_appStateUtils.resetFeatureFlags)();
12
15
  cy.visit(path);
13
16
  cy.findByRole("tab", { name: /Viewed \(0\)/ }).should("be.visible");
14
17
  (0, import_cypressUtils.checkA11y)();
@@ -26,9 +29,32 @@ context("Viewing a report", () => {
26
29
  (0, import_cypressUtils.checkA11y)();
27
30
  cy.findByRole("heading", { level: 1, name: /Test Dashboard/ }).should("be.visible");
28
31
  (0, import_cypressUtils.checkA11y)();
32
+ cy.findAllByText(/This visualisation type is not supported yet./).each((el) => cy.wrap(el).should("be.visible")).should("have.length.at.least", 1);
33
+ cy.get("canvas").should("not.exist");
29
34
  cy.visit(path);
30
35
  cy.findByRole("tab", { name: /Viewed \(1\)/ }).should("be.visible");
31
36
  });
37
+ it("should show viz", () => {
38
+ cy.task("stubFeatureFlags");
39
+ (0, import_appStateUtils.resetFeatureFlags)();
40
+ cy.visit(path);
41
+ cy.findByLabelText(/Reports catalogue.*/i).within(() => {
42
+ cy.findByRole("row", {
43
+ name: (_, element) => {
44
+ return Boolean(element.textContent?.includes("Test Dashboard")) && Boolean(element.textContent?.includes("Dashboard used for testing testing"));
45
+ }
46
+ }).within(() => {
47
+ cy.findByRole("link", { name: "Request dashboard" }).click();
48
+ });
49
+ });
50
+ (0, import_cypressUtils.checkA11y)();
51
+ cy.findByRole("button", { name: /Request/ }).click();
52
+ (0, import_cypressUtils.checkA11y)();
53
+ cy.findByRole("heading", { level: 1, name: /Test Dashboard/ }).should("be.visible");
54
+ (0, import_cypressUtils.checkA11y)();
55
+ cy.findAllByText(/This visualisation type is not supported yet./).should("have.length", 0);
56
+ cy.get("canvas").should("have.length.at.least", 1);
57
+ });
32
58
  });
33
59
  });
34
60
  //# sourceMappingURL=tests.cy.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../dpr/routes/journeys/view-report/async/dashboard/tests.cy.ts"],
4
- "sourcesContent": ["import { checkA11y, executeDashboardStubs } from '../../../../../../../cypress-tests/cypressUtils'\n\ncontext('Viewing a report', () => {\n const path = '/embedded/platform/'\n\n describe('dashboard tests', () => {\n before(() => {\n executeDashboardStubs()\n cy.task('stubTestDashboard8')\n cy.task('stubDashboardSuccessResult20')\n })\n\n it('should mark the dashboard as recently viewed', () => {\n // Request and run a report so we can go back to it for each test\n cy.visit(path)\n cy.findByRole('tab', { name: /Viewed \\(0\\)/ }).should('be.visible')\n checkA11y()\n cy.findByLabelText(/Reports catalogue.*/i).within(() => {\n cy.findByRole('row', {\n name: (_, element) => {\n return (\n Boolean(element.textContent?.includes('Test Dashboard')) &&\n Boolean(element.textContent?.includes('Dashboard used for testing testing'))\n )\n },\n }).within(() => {\n cy.findByRole('link', { name: 'Request dashboard' }).click()\n })\n })\n checkA11y()\n cy.findByRole('button', { name: /Request/ }).click()\n checkA11y()\n cy.findByRole('heading', { level: 1, name: /Test Dashboard/ }).should('be.visible')\n checkA11y()\n cy.visit(path)\n cy.findByRole('tab', { name: /Viewed \\(1\\)/ }).should('be.visible')\n })\n })\n})\n"],
5
- "mappings": ";AAAA,0BAAiD;AAEjD,QAAQ,oBAAoB,MAAM;AAChC,QAAM,OAAO;AAEb,WAAS,mBAAmB,MAAM;AAChC,WAAO,MAAM;AACX,qDAAsB;AACtB,SAAG,KAAK,oBAAoB;AAC5B,SAAG,KAAK,8BAA8B;AAAA,IACxC,CAAC;AAED,OAAG,gDAAgD,MAAM;AAEvD,SAAG,MAAM,IAAI;AACb,SAAG,WAAW,OAAO,EAAE,MAAM,eAAe,CAAC,EAAE,OAAO,YAAY;AAClE,yCAAU;AACV,SAAG,gBAAgB,sBAAsB,EAAE,OAAO,MAAM;AACtD,WAAG,WAAW,OAAO;AAAA,UACnB,MAAM,CAAC,GAAG,YAAY;AACpB,mBACE,QAAQ,QAAQ,aAAa,SAAS,gBAAgB,CAAC,KACvD,QAAQ,QAAQ,aAAa,SAAS,oCAAoC,CAAC;AAAA,UAE/E;AAAA,QACF,CAAC,EAAE,OAAO,MAAM;AACd,aAAG,WAAW,QAAQ,EAAE,MAAM,oBAAoB,CAAC,EAAE,MAAM;AAAA,QAC7D,CAAC;AAAA,MACH,CAAC;AACD,yCAAU;AACV,SAAG,WAAW,UAAU,EAAE,MAAM,UAAU,CAAC,EAAE,MAAM;AACnD,yCAAU;AACV,SAAG,WAAW,WAAW,EAAE,OAAO,GAAG,MAAM,iBAAiB,CAAC,EAAE,OAAO,YAAY;AAClF,yCAAU;AACV,SAAG,MAAM,IAAI;AACb,SAAG,WAAW,OAAO,EAAE,MAAM,eAAe,CAAC,EAAE,OAAO,YAAY;AAAA,IACpE,CAAC;AAAA,EACH,CAAC;AACH,CAAC;",
4
+ "sourcesContent": ["import { resetFeatureFlags } from 'test-app/routes/integrationTests/appStateUtils'\nimport { checkA11y, executeDashboardStubs } from '../../../../../../../cypress-tests/cypressUtils'\n\ncontext('Viewing a report', () => {\n const path = '/embedded/platform/'\n\n describe('dashboard tests', () => {\n before(() => {\n executeDashboardStubs()\n cy.task('stubTestDashboard8')\n cy.task('stubDashboardSuccessResult20')\n })\n\n it('should mark the dashboard as recently viewed and not show viz', () => {\n cy.task('stubFeatureFlagsDisabled')\n resetFeatureFlags()\n // Request and run a report so we can go back to it for each test\n cy.visit(path)\n cy.findByRole('tab', { name: /Viewed \\(0\\)/ }).should('be.visible')\n checkA11y()\n cy.findByLabelText(/Reports catalogue.*/i).within(() => {\n cy.findByRole('row', {\n name: (_, element) => {\n return (\n Boolean(element.textContent?.includes('Test Dashboard')) &&\n Boolean(element.textContent?.includes('Dashboard used for testing testing'))\n )\n },\n }).within(() => {\n cy.findByRole('link', { name: 'Request dashboard' }).click()\n })\n })\n checkA11y()\n cy.findByRole('button', { name: /Request/ }).click()\n checkA11y()\n cy.findByRole('heading', { level: 1, name: /Test Dashboard/ }).should('be.visible')\n checkA11y()\n cy.findAllByText(/This visualisation type is not supported yet./)\n .each((el) => cy.wrap(el).should('be.visible'))\n .should('have.length.at.least', 1)\n cy.get('canvas').should('not.exist')\n cy.visit(path)\n cy.findByRole('tab', { name: /Viewed \\(1\\)/ }).should('be.visible')\n })\n\n it('should show viz', () => {\n cy.task('stubFeatureFlags')\n resetFeatureFlags()\n // Request and run a report so we can go back to it for each test\n cy.visit(path)\n cy.findByLabelText(/Reports catalogue.*/i).within(() => {\n cy.findByRole('row', {\n name: (_, element) => {\n return (\n Boolean(element.textContent?.includes('Test Dashboard')) &&\n Boolean(element.textContent?.includes('Dashboard used for testing testing'))\n )\n },\n }).within(() => {\n cy.findByRole('link', { name: 'Request dashboard' }).click()\n })\n })\n checkA11y()\n cy.findByRole('button', { name: /Request/ }).click()\n checkA11y()\n cy.findByRole('heading', { level: 1, name: /Test Dashboard/ }).should('be.visible')\n checkA11y()\n cy.findAllByText(/This visualisation type is not supported yet./).should('have.length', 0)\n cy.get('canvas').should('have.length.at.least', 1)\n })\n })\n})\n"],
5
+ "mappings": ";AAAA,2BAAkC;AAClC,0BAAiD;AAEjD,QAAQ,oBAAoB,MAAM;AAChC,QAAM,OAAO;AAEb,WAAS,mBAAmB,MAAM;AAChC,WAAO,MAAM;AACX,qDAAsB;AACtB,SAAG,KAAK,oBAAoB;AAC5B,SAAG,KAAK,8BAA8B;AAAA,IACxC,CAAC;AAED,OAAG,iEAAiE,MAAM;AACxE,SAAG,KAAK,0BAA0B;AAClC,kDAAkB;AAElB,SAAG,MAAM,IAAI;AACb,SAAG,WAAW,OAAO,EAAE,MAAM,eAAe,CAAC,EAAE,OAAO,YAAY;AAClE,yCAAU;AACV,SAAG,gBAAgB,sBAAsB,EAAE,OAAO,MAAM;AACtD,WAAG,WAAW,OAAO;AAAA,UACnB,MAAM,CAAC,GAAG,YAAY;AACpB,mBACE,QAAQ,QAAQ,aAAa,SAAS,gBAAgB,CAAC,KACvD,QAAQ,QAAQ,aAAa,SAAS,oCAAoC,CAAC;AAAA,UAE/E;AAAA,QACF,CAAC,EAAE,OAAO,MAAM;AACd,aAAG,WAAW,QAAQ,EAAE,MAAM,oBAAoB,CAAC,EAAE,MAAM;AAAA,QAC7D,CAAC;AAAA,MACH,CAAC;AACD,yCAAU;AACV,SAAG,WAAW,UAAU,EAAE,MAAM,UAAU,CAAC,EAAE,MAAM;AACnD,yCAAU;AACV,SAAG,WAAW,WAAW,EAAE,OAAO,GAAG,MAAM,iBAAiB,CAAC,EAAE,OAAO,YAAY;AAClF,yCAAU;AACV,SAAG,cAAc,+CAA+C,EAC7D,KAAK,CAAC,OAAO,GAAG,KAAK,EAAE,EAAE,OAAO,YAAY,CAAC,EAC7C,OAAO,wBAAwB,CAAC;AACnC,SAAG,IAAI,QAAQ,EAAE,OAAO,WAAW;AACnC,SAAG,MAAM,IAAI;AACb,SAAG,WAAW,OAAO,EAAE,MAAM,eAAe,CAAC,EAAE,OAAO,YAAY;AAAA,IACpE,CAAC;AAED,OAAG,mBAAmB,MAAM;AAC1B,SAAG,KAAK,kBAAkB;AAC1B,kDAAkB;AAElB,SAAG,MAAM,IAAI;AACb,SAAG,gBAAgB,sBAAsB,EAAE,OAAO,MAAM;AACtD,WAAG,WAAW,OAAO;AAAA,UACnB,MAAM,CAAC,GAAG,YAAY;AACpB,mBACE,QAAQ,QAAQ,aAAa,SAAS,gBAAgB,CAAC,KACvD,QAAQ,QAAQ,aAAa,SAAS,oCAAoC,CAAC;AAAA,UAE/E;AAAA,QACF,CAAC,EAAE,OAAO,MAAM;AACd,aAAG,WAAW,QAAQ,EAAE,MAAM,oBAAoB,CAAC,EAAE,MAAM;AAAA,QAC7D,CAAC;AAAA,MACH,CAAC;AACD,yCAAU;AACV,SAAG,WAAW,UAAU,EAAE,MAAM,UAAU,CAAC,EAAE,MAAM;AACnD,yCAAU;AACV,SAAG,WAAW,WAAW,EAAE,OAAO,GAAG,MAAM,iBAAiB,CAAC,EAAE,OAAO,YAAY;AAClF,yCAAU;AACV,SAAG,cAAc,+CAA+C,EAAE,OAAO,eAAe,CAAC;AACzF,SAAG,IAAI,QAAQ,EAAE,OAAO,wBAAwB,CAAC;AAAA,IACnD,CAAC;AAAA,EACH,CAAC;AACH,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,3 +1,4 @@
1
+ import { resetFeatureFlags } from 'test-app/routes/integrationTests/appStateUtils'
1
2
  import { checkA11y, executeDashboardStubs } from '../../../../../../../cypress-tests/cypressUtils'
2
3
 
3
4
  context('Viewing a report', () => {
@@ -10,7 +11,9 @@ context('Viewing a report', () => {
10
11
  cy.task('stubDashboardSuccessResult20')
11
12
  })
12
13
 
13
- it('should mark the dashboard as recently viewed', () => {
14
+ it('should mark the dashboard as recently viewed and not show viz', () => {
15
+ cy.task('stubFeatureFlagsDisabled')
16
+ resetFeatureFlags()
14
17
  // Request and run a report so we can go back to it for each test
15
18
  cy.visit(path)
16
19
  cy.findByRole('tab', { name: /Viewed \(0\)/ }).should('be.visible')
@@ -32,8 +35,38 @@ context('Viewing a report', () => {
32
35
  checkA11y()
33
36
  cy.findByRole('heading', { level: 1, name: /Test Dashboard/ }).should('be.visible')
34
37
  checkA11y()
38
+ cy.findAllByText(/This visualisation type is not supported yet./)
39
+ .each((el) => cy.wrap(el).should('be.visible'))
40
+ .should('have.length.at.least', 1)
41
+ cy.get('canvas').should('not.exist')
35
42
  cy.visit(path)
36
43
  cy.findByRole('tab', { name: /Viewed \(1\)/ }).should('be.visible')
37
44
  })
45
+
46
+ it('should show viz', () => {
47
+ cy.task('stubFeatureFlags')
48
+ resetFeatureFlags()
49
+ // Request and run a report so we can go back to it for each test
50
+ cy.visit(path)
51
+ cy.findByLabelText(/Reports catalogue.*/i).within(() => {
52
+ cy.findByRole('row', {
53
+ name: (_, element) => {
54
+ return (
55
+ Boolean(element.textContent?.includes('Test Dashboard')) &&
56
+ Boolean(element.textContent?.includes('Dashboard used for testing testing'))
57
+ )
58
+ },
59
+ }).within(() => {
60
+ cy.findByRole('link', { name: 'Request dashboard' }).click()
61
+ })
62
+ })
63
+ checkA11y()
64
+ cy.findByRole('button', { name: /Request/ }).click()
65
+ checkA11y()
66
+ cy.findByRole('heading', { level: 1, name: /Test Dashboard/ }).should('be.visible')
67
+ checkA11y()
68
+ cy.findAllByText(/This visualisation type is not supported yet./).should('have.length', 0)
69
+ cy.get('canvas').should('have.length.at.least', 1)
70
+ })
38
71
  })
39
72
  })
@@ -117,13 +117,41 @@ const getDefinitionData = async ({
117
117
  reportDefinition
118
118
  };
119
119
  };
120
- const getSections = (dashboardDefinition, dashboardData, query, partialDate) => {
120
+ const getSections = (dashboardDefinition, dashboardData, query, dashboardFeatureFlags, partialDate) => {
121
121
  return dashboardDefinition.sections.map((section) => {
122
122
  const { id, display: title, description } = section;
123
+ const featureFlagVisTypeMap = {
124
+ [import_types.DashboardVisualisationType.LIST]: true,
125
+ [import_types.DashboardVisualisationType.BAR]: Boolean(
126
+ dashboardFeatureFlags.find((flag) => flag.key === "barChartsEnabled" && flag.enabled)
127
+ ),
128
+ [import_types.DashboardVisualisationType.LINE]: Boolean(
129
+ dashboardFeatureFlags.find((flag) => flag.key === "lineChartsEnabled" && flag.enabled)
130
+ ),
131
+ [import_types.DashboardVisualisationType.DONUT]: Boolean(
132
+ dashboardFeatureFlags.find((flag) => flag.key === "donutChartsEnabled" && flag.enabled)
133
+ ),
134
+ [import_types.DashboardVisualisationType.SCORECARD]: Boolean(
135
+ dashboardFeatureFlags.find((flag) => flag.key === "scorecardChartsEnabled" && flag.enabled)
136
+ ),
137
+ [import_types.DashboardVisualisationType.SCORECARD_GROUP]: Boolean(
138
+ dashboardFeatureFlags.find((flag) => flag.key === "scorecardgroupChartsEnabled" && flag.enabled)
139
+ ),
140
+ [import_types.DashboardVisualisationType.MATRIX_TIMESERIES]: Boolean(
141
+ dashboardFeatureFlags.find((flag) => flag.key === "matrixtimeseriesChartsEnabled" && flag.enabled)
142
+ ),
143
+ [import_types.DashboardVisualisationType.BAR_TIMESERIES]: Boolean(
144
+ dashboardFeatureFlags.find((flag) => flag.key === "bartimeseriesChartsEnabled" && flag.enabled)
145
+ ),
146
+ [import_types.DashboardVisualisationType.LINE_TIMESERIES]: Boolean(
147
+ dashboardFeatureFlags.find((flag) => flag.key === "linetimeseriesChartsEnabled" && flag.enabled)
148
+ )
149
+ };
123
150
  let hasScorecard = false;
124
151
  const visualisations = section.visualisations.map(
125
152
  (visDefinition) => {
126
153
  const { type, display, description: visDescription, id: visId } = visDefinition;
154
+ const isEnabled = featureFlagVisTypeMap[type];
127
155
  let data;
128
156
  switch (type) {
129
157
  case import_types.DashboardVisualisationType.LIST:
@@ -156,11 +184,16 @@ const getSections = (dashboardDefinition, dashboardData, query, partialDate) =>
156
184
  title: display || "",
157
185
  description: visDescription || "",
158
186
  type,
159
- data
187
+ data,
188
+ isEnabled: isEnabled ?? true
160
189
  };
161
190
  }
162
191
  );
163
- if (hasScorecard) import_utils5.default.mergeScorecardsIntoGroup(visualisations);
192
+ if (hasScorecard)
193
+ import_utils5.default.mergeScorecardsIntoGroup(
194
+ visualisations,
195
+ featureFlagVisTypeMap[import_types.DashboardVisualisationType.SCORECARD_GROUP]
196
+ );
164
197
  return { id, title: title || "", description: description || "", visualisations };
165
198
  });
166
199
  };
@@ -208,7 +241,16 @@ const renderAsyncDashboard = async ({ req, res, services }) => {
208
241
  );
209
242
  const flattenedData = dashboardData.flat();
210
243
  const partialDate = getPartialDate(filters.filters);
211
- const sections = getSections(dashboardDefinition, flattenedData, query, partialDate);
244
+ const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(
245
+ (flag) => flag.metadata["dashboardFeature"] === true
246
+ );
247
+ const sections = getSections(
248
+ dashboardDefinition,
249
+ flattenedData,
250
+ query,
251
+ dashboardFeatureFlags,
252
+ partialDate
253
+ );
212
254
  if (requestedReportService) {
213
255
  requestData = await updateStore(services, tableId, dprUser.id, sections, req, filters.filters);
214
256
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../dpr/routes/journeys/view-report/async/dashboard/utils.ts"],
4
- "sourcesContent": ["import { Request, Response } from 'express'\nimport { Services } from '../../../../../types/Services'\nimport Dict = NodeJS.Dict\nimport {\n DashboardSection,\n DashboardVisualisation,\n DashboardVisualisationType,\n} from '../../../../../components/_dashboards/dashboard-visualisation/types'\nimport type { AsyncReportUtilsParams } from '../../../../../types/AsyncReportUtils'\n\nimport type { DashboardDataResponse } from '../../../../../types/Metrics'\nimport type { RequestedReport } from '../../../../../types/UserReports'\nimport { ReportType } from '../../../../../types/UserReports'\nimport type { components } from '../../../../../types/api'\n\nimport ChartUtils from '../../../../../components/_charts/utils'\nimport DefinitionUtils from '../../../../../utils/definitionUtils'\nimport UserReportsUtils from '../../../../../components/user-reports/utils'\nimport DashboardListUtils from '../../../../../components/_dashboards/dashboard-list/utils'\nimport FilterUtils from '../../../../../components/_filters/utils'\nimport ScorecardsUtils from '../../../../../components/_dashboards/scorecard/utils'\nimport ScorecardVisualisation from '../../../../../components/_dashboards/scorecard/Scorecard'\nimport ScorecardGroupVisualisation from '../../../../../components/_dashboards/scorecard-group/ScorecardGroup'\nimport ReportActionsUtils from '../../../../../components/_reports/report-heading/report-actions/utils'\nimport ReportQuery from '../../../../../types/ReportQuery'\nimport LocalsHelper from '../../../../../utils/localsHelper'\nimport { FilterValue, GranularDateRangeFilterValue, PartialDate } from '../../../../../components/_filters/types'\nimport { FiltersType } from '../../../../../components/_filters/filtersTypeEnum'\nimport { FilterType } from '../../../../../components/_filters/filter-input/enum'\n\nconst setDashboardActions = (\n dashboardDefinition: components['schemas']['DashboardDefinition'],\n reportDefinition: components['schemas']['ReportDefinitionSummary'],\n requestData?: RequestedReport,\n) => {\n const reportName = reportDefinition.name\n const { name } = dashboardDefinition\n const actionsUrl = requestData?.url?.request?.fullUrl\n const executionId = requestData?.executionId\n\n let actions = {}\n if (actionsUrl) {\n actions = {\n share: {\n reportName,\n name,\n url: actionsUrl,\n },\n copy: {\n url: actionsUrl,\n },\n }\n if (executionId) {\n actions = {\n ...actions,\n refresh: {\n url: actionsUrl,\n executionId,\n },\n }\n }\n }\n\n return ReportActionsUtils.getActions(actions)\n}\n\nconst getDefinitionData = async ({\n req,\n res,\n services,\n queryData,\n}: {\n req: Request\n res: Response\n services: Services\n queryData?: Dict<string | string[]> | undefined\n}) => {\n const { token } = LocalsHelper.getValues(res)\n const { reportId, id } = req.params\n const dataProductDefinitionsPath = <string>req.query['dataProductDefinitionsPath']\n\n // Dashboard Definition,\n const dashboardDefinition = await services.dashboardService.getDefinition(\n token,\n reportId,\n id,\n dataProductDefinitionsPath,\n queryData,\n )\n\n // Report summary data\n const reportDefinition = await DefinitionUtils.getReportSummary(\n reportId,\n services.reportingService,\n token,\n <string>dataProductDefinitionsPath,\n )\n\n // Get the filters\n const filtersData = await FilterUtils.getFilters({\n fields: dashboardDefinition.filterFields || [],\n req,\n filtersType: FiltersType.INTERACTIVE,\n })\n\n const filtersQuery = FilterUtils.setRequestQueryFromFilterValues(filtersData.filters)\n\n // Create the query\n const query = new ReportQuery({\n fields: dashboardDefinition.filterFields || [],\n queryParams: filtersQuery,\n definitionsPath: <string>dataProductDefinitionsPath,\n reportType: ReportType.DASHBOARD,\n }).toRecordWithFilterPrefix(true)\n\n return {\n query,\n filters: filtersData,\n dashboardDefinition,\n reportDefinition,\n }\n}\n\nconst getSections = (\n dashboardDefinition: components['schemas']['DashboardDefinition'],\n dashboardData: DashboardDataResponse[],\n query: Record<string, string | string[]>,\n partialDate?: PartialDate,\n): DashboardSection[] => {\n return dashboardDefinition.sections.map((section: components['schemas']['DashboardSectionDefinition']) => {\n const { id, display: title, description } = section\n\n let hasScorecard = false\n const visualisations: DashboardVisualisation[] = section.visualisations.map(\n (visDefinition: components['schemas']['DashboardVisualisationDefinition']) => {\n const { type, display, description: visDescription, id: visId } = visDefinition\n\n let data: DashboardVisualisation['data'] | undefined\n\n switch (type) {\n case DashboardVisualisationType.LIST:\n data = DashboardListUtils.createList(visDefinition, dashboardData)\n break\n\n case DashboardVisualisationType.SCORECARD:\n hasScorecard = true\n data = new ScorecardVisualisation().withDefinition(visDefinition).withData(dashboardData).build()\n break\n\n case DashboardVisualisationType.SCORECARD_GROUP:\n data = new ScorecardGroupVisualisation().withDefinition(visDefinition).withData(dashboardData).build()\n break\n\n case DashboardVisualisationType.BAR:\n case DashboardVisualisationType.LINE:\n case DashboardVisualisationType.DONUT: {\n data = ChartUtils.createChart(visDefinition, dashboardData, type)\n break\n }\n case DashboardVisualisationType.MATRIX_TIMESERIES:\n case DashboardVisualisationType.BAR_TIMESERIES:\n case DashboardVisualisationType.LINE_TIMESERIES: {\n data = ChartUtils.createTimeseriesCharts(visDefinition, dashboardData, type, query, partialDate)\n break\n }\n default:\n break\n }\n\n return {\n id: visId,\n title: display || '',\n description: visDescription || '',\n type,\n data,\n }\n },\n )\n\n if (hasScorecard) ScorecardsUtils.mergeScorecardsIntoGroup(visualisations)\n\n return { id, title: title || '', description: description || '', visualisations }\n })\n}\n\nconst updateStore = async (\n services: Services,\n tableId: string,\n userId: string,\n sections: DashboardSection[],\n req: Request,\n filters: FilterValue[],\n): Promise<RequestedReport | undefined> => {\n const { requestedReportService } = services\n const dashboardRequestData = await requestedReportService.getReportByTableId(tableId, userId)\n\n // Add to recently viewed\n if (sections && sections.length && dashboardRequestData) {\n UserReportsUtils.updateLastViewed({\n services,\n reportStateData: dashboardRequestData,\n userId,\n req,\n filters,\n })\n }\n\n return dashboardRequestData\n}\n\nconst getPartialDate = (filters: FilterValue[]) => {\n let partialDate: PartialDate | undefined\n const granularDateRangeFilter = <GranularDateRangeFilterValue | undefined>(\n filters.find((f) => f.type === FilterType.granularDateRange.toLowerCase())\n )\n if (granularDateRangeFilter) {\n partialDate = granularDateRangeFilter.value.partialDate\n }\n return partialDate\n}\n\nexport const renderAsyncDashboard = async ({ req, res, services }: AsyncReportUtilsParams) => {\n const { token, csrfToken, dprUser, nestedBaseUrl } = LocalsHelper.getValues(res)\n const { reportId, id, tableId } = req.params\n const { bookmarkService, requestedReportService } = services\n const { id: userId } = dprUser\n\n let requestData: RequestedReport | undefined = await requestedReportService.getReportByTableId(tableId, userId)\n const queryData = requestData?.query?.data\n\n // Get the definition Data\n const { query, filters, reportDefinition, dashboardDefinition } = await getDefinitionData({\n req,\n res,\n services,\n queryData,\n })\n\n // Get the results data\n const dashboardData: DashboardDataResponse[][] = await services.dashboardService.getAsyncDashboard(\n token,\n id,\n reportId,\n tableId,\n query,\n )\n\n const flattenedData: DashboardDataResponse[] = dashboardData.flat()\n const partialDate = getPartialDate(filters.filters)\n\n // Get the dashboard parts\n const sections: DashboardSection[] = getSections(dashboardDefinition, flattenedData, query, partialDate)\n\n // Update the store\n if (requestedReportService) {\n requestData = await updateStore(services, tableId, dprUser.id, sections, req, filters.filters)\n }\n\n return {\n dashboardData: {\n token,\n id,\n reportId,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description,\n reportName: reportDefinition.name,\n bookmarked: await bookmarkService.isBookmarked(id, reportId, dprUser.id),\n nestedBaseUrl,\n csrfToken,\n sections,\n filters,\n type: ReportType.DASHBOARD,\n actions: setDashboardActions(dashboardDefinition, reportDefinition, requestData),\n },\n }\n}\n\nexport default {\n renderAsyncDashboard,\n getDefinitionData,\n getSections,\n setDashboardActions,\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Request, Response } from 'express'\nimport { Flag } from '@flipt-io/flipt'\nimport { Services } from '../../../../../types/Services'\nimport Dict = NodeJS.Dict\nimport {\n DashboardSection,\n DashboardVisualisation,\n DashboardVisualisationType,\n} from '../../../../../components/_dashboards/dashboard-visualisation/types'\nimport type { AsyncReportUtilsParams } from '../../../../../types/AsyncReportUtils'\n\nimport type { DashboardDataResponse } from '../../../../../types/Metrics'\nimport type { RequestedReport } from '../../../../../types/UserReports'\nimport { ReportType } from '../../../../../types/UserReports'\nimport type { components } from '../../../../../types/api'\n\nimport ChartUtils from '../../../../../components/_charts/utils'\nimport DefinitionUtils from '../../../../../utils/definitionUtils'\nimport UserReportsUtils from '../../../../../components/user-reports/utils'\nimport DashboardListUtils from '../../../../../components/_dashboards/dashboard-list/utils'\nimport FilterUtils from '../../../../../components/_filters/utils'\nimport ScorecardsUtils from '../../../../../components/_dashboards/scorecard/utils'\nimport ScorecardVisualisation from '../../../../../components/_dashboards/scorecard/Scorecard'\nimport ScorecardGroupVisualisation from '../../../../../components/_dashboards/scorecard-group/ScorecardGroup'\nimport ReportActionsUtils from '../../../../../components/_reports/report-heading/report-actions/utils'\nimport ReportQuery from '../../../../../types/ReportQuery'\nimport LocalsHelper from '../../../../../utils/localsHelper'\nimport { FilterValue, GranularDateRangeFilterValue, PartialDate } from '../../../../../components/_filters/types'\nimport { FiltersType } from '../../../../../components/_filters/filtersTypeEnum'\nimport { FilterType } from '../../../../../components/_filters/filter-input/enum'\n\nconst setDashboardActions = (\n dashboardDefinition: components['schemas']['DashboardDefinition'],\n reportDefinition: components['schemas']['ReportDefinitionSummary'],\n requestData?: RequestedReport,\n) => {\n const reportName = reportDefinition.name\n const { name } = dashboardDefinition\n const actionsUrl = requestData?.url?.request?.fullUrl\n const executionId = requestData?.executionId\n\n let actions = {}\n if (actionsUrl) {\n actions = {\n share: {\n reportName,\n name,\n url: actionsUrl,\n },\n copy: {\n url: actionsUrl,\n },\n }\n if (executionId) {\n actions = {\n ...actions,\n refresh: {\n url: actionsUrl,\n executionId,\n },\n }\n }\n }\n\n return ReportActionsUtils.getActions(actions)\n}\n\nconst getDefinitionData = async ({\n req,\n res,\n services,\n queryData,\n}: {\n req: Request\n res: Response\n services: Services\n queryData?: Dict<string | string[]> | undefined\n}) => {\n const { token } = LocalsHelper.getValues(res)\n const { reportId, id } = req.params\n const dataProductDefinitionsPath = <string>req.query['dataProductDefinitionsPath']\n\n // Dashboard Definition,\n const dashboardDefinition = await services.dashboardService.getDefinition(\n token,\n reportId,\n id,\n dataProductDefinitionsPath,\n queryData,\n )\n\n // Report summary data\n const reportDefinition = await DefinitionUtils.getReportSummary(\n reportId,\n services.reportingService,\n token,\n <string>dataProductDefinitionsPath,\n )\n\n // Get the filters\n const filtersData = await FilterUtils.getFilters({\n fields: dashboardDefinition.filterFields || [],\n req,\n filtersType: FiltersType.INTERACTIVE,\n })\n\n const filtersQuery = FilterUtils.setRequestQueryFromFilterValues(filtersData.filters)\n\n // Create the query\n const query = new ReportQuery({\n fields: dashboardDefinition.filterFields || [],\n queryParams: filtersQuery,\n definitionsPath: <string>dataProductDefinitionsPath,\n reportType: ReportType.DASHBOARD,\n }).toRecordWithFilterPrefix(true)\n\n return {\n query,\n filters: filtersData,\n dashboardDefinition,\n reportDefinition,\n }\n}\n\nconst getSections = (\n dashboardDefinition: components['schemas']['DashboardDefinition'],\n dashboardData: DashboardDataResponse[],\n query: Record<string, string | string[]>,\n dashboardFeatureFlags: Flag[],\n partialDate?: PartialDate,\n): DashboardSection[] => {\n return dashboardDefinition.sections.map((section: components['schemas']['DashboardSectionDefinition']) => {\n const { id, display: title, description } = section\n\n const featureFlagVisTypeMap = {\n [DashboardVisualisationType.LIST]: true,\n [DashboardVisualisationType.BAR]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'barChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.LINE]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'lineChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.DONUT]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'donutChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.SCORECARD]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'scorecardChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.SCORECARD_GROUP]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'scorecardgroupChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.MATRIX_TIMESERIES]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'matrixtimeseriesChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.BAR_TIMESERIES]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'bartimeseriesChartsEnabled' && flag.enabled),\n ),\n [DashboardVisualisationType.LINE_TIMESERIES]: Boolean(\n dashboardFeatureFlags.find((flag) => flag.key === 'linetimeseriesChartsEnabled' && flag.enabled),\n ),\n }\n\n let hasScorecard = false\n const visualisations: DashboardVisualisation[] = section.visualisations.map(\n (visDefinition: components['schemas']['DashboardVisualisationDefinition']) => {\n const { type, display, description: visDescription, id: visId } = visDefinition\n const isEnabled = featureFlagVisTypeMap[type]\n\n let data: DashboardVisualisation['data'] | undefined\n\n switch (type) {\n case DashboardVisualisationType.LIST:\n data = DashboardListUtils.createList(visDefinition, dashboardData)\n break\n\n case DashboardVisualisationType.SCORECARD:\n hasScorecard = true\n data = new ScorecardVisualisation().withDefinition(visDefinition).withData(dashboardData).build()\n break\n\n case DashboardVisualisationType.SCORECARD_GROUP:\n data = new ScorecardGroupVisualisation().withDefinition(visDefinition).withData(dashboardData).build()\n break\n\n case DashboardVisualisationType.BAR:\n case DashboardVisualisationType.LINE:\n case DashboardVisualisationType.DONUT: {\n data = ChartUtils.createChart(visDefinition, dashboardData, type)\n break\n }\n case DashboardVisualisationType.MATRIX_TIMESERIES:\n case DashboardVisualisationType.BAR_TIMESERIES:\n case DashboardVisualisationType.LINE_TIMESERIES: {\n data = ChartUtils.createTimeseriesCharts(visDefinition, dashboardData, type, query, partialDate)\n break\n }\n default:\n break\n }\n\n return {\n id: visId,\n title: display || '',\n description: visDescription || '',\n type,\n data,\n isEnabled: isEnabled ?? true,\n }\n },\n )\n\n if (hasScorecard)\n ScorecardsUtils.mergeScorecardsIntoGroup(\n visualisations,\n featureFlagVisTypeMap[DashboardVisualisationType.SCORECARD_GROUP],\n )\n\n return { id, title: title || '', description: description || '', visualisations }\n })\n}\n\nconst updateStore = async (\n services: Services,\n tableId: string,\n userId: string,\n sections: DashboardSection[],\n req: Request,\n filters: FilterValue[],\n): Promise<RequestedReport | undefined> => {\n const { requestedReportService } = services\n const dashboardRequestData = await requestedReportService.getReportByTableId(tableId, userId)\n\n // Add to recently viewed\n if (sections && sections.length && dashboardRequestData) {\n UserReportsUtils.updateLastViewed({\n services,\n reportStateData: dashboardRequestData,\n userId,\n req,\n filters,\n })\n }\n\n return dashboardRequestData\n}\n\nconst getPartialDate = (filters: FilterValue[]) => {\n let partialDate: PartialDate | undefined\n const granularDateRangeFilter = <GranularDateRangeFilterValue | undefined>(\n filters.find((f) => f.type === FilterType.granularDateRange.toLowerCase())\n )\n if (granularDateRangeFilter) {\n partialDate = granularDateRangeFilter.value.partialDate\n }\n return partialDate\n}\n\nexport const renderAsyncDashboard = async ({ req, res, services }: AsyncReportUtilsParams) => {\n const { token, csrfToken, dprUser, nestedBaseUrl } = LocalsHelper.getValues(res)\n const { reportId, id, tableId } = req.params\n const { bookmarkService, requestedReportService } = services\n const { id: userId } = dprUser\n\n let requestData: RequestedReport | undefined = await requestedReportService.getReportByTableId(tableId, userId)\n const queryData = requestData?.query?.data\n\n // Get the definition Data\n const { query, filters, reportDefinition, dashboardDefinition } = await getDefinitionData({\n req,\n res,\n services,\n queryData,\n })\n\n // Get the results data\n const dashboardData: DashboardDataResponse[][] = await services.dashboardService.getAsyncDashboard(\n token,\n id,\n reportId,\n tableId,\n query,\n )\n\n const flattenedData: DashboardDataResponse[] = dashboardData.flat()\n const partialDate = getPartialDate(filters.filters)\n\n // Get the dashboard parts\n const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(\n (flag) => flag.metadata['dashboardFeature'] === true,\n )\n const sections: DashboardSection[] = getSections(\n dashboardDefinition,\n flattenedData,\n query,\n dashboardFeatureFlags,\n partialDate,\n )\n\n // Update the store\n if (requestedReportService) {\n requestData = await updateStore(services, tableId, dprUser.id, sections, req, filters.filters)\n }\n\n return {\n dashboardData: {\n token,\n id,\n reportId,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description,\n reportName: reportDefinition.name,\n bookmarked: await bookmarkService.isBookmarked(id, reportId, dprUser.id),\n nestedBaseUrl,\n csrfToken,\n sections,\n filters,\n type: ReportType.DASHBOARD,\n actions: setDashboardActions(dashboardDefinition, reportDefinition, requestData),\n },\n }\n}\n\nexport default {\n renderAsyncDashboard,\n getDefinitionData,\n getSections,\n setDashboardActions,\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,mBAIO;AAKP,yBAA2B;AAG3B,mBAAuB;AACvB,6BAA4B;AAC5B,IAAAA,gBAA6B;AAC7B,IAAAA,gBAA+B;AAC/B,IAAAA,gBAAwB;AACxB,IAAAA,gBAA4B;AAC5B,uBAAmC;AACnC,4BAAwC;AACxC,IAAAA,gBAA+B;AAC/B,yBAAwB;AACxB,0BAAyB;AAEzB,6BAA4B;AAC5B,kBAA2B;AAE3B,MAAM,sBAAsB,CAC1B,qBACA,kBACA,gBACG;AACH,QAAM,aAAa,iBAAiB;AACpC,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,aAAa,aAAa,KAAK,SAAS;AAC9C,QAAM,cAAc,aAAa;AAEjC,MAAI,UAAU,CAAC;AACf,MAAI,YAAY;AACd,cAAU;AAAA,MACR,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACA,MAAM;AAAA,QACJ,KAAK;AAAA,MACP;AAAA,IACF;AACA,QAAI,aAAa;AACf,gBAAU;AAAA,QACR,GAAG;AAAA,QACH,SAAS;AAAA,UACP,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,cAAAC,QAAmB,WAAW,OAAO;AAC9C;AAEA,MAAM,oBAAoB,OAAO;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAKM;AACJ,QAAM,EAAE,MAAM,IAAI,oBAAAC,QAAa,UAAU,GAAG;AAC5C,QAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC7B,QAAM,6BAAqC,IAAI,MAAM,4BAA4B;AAGjF,QAAM,sBAAsB,MAAM,SAAS,iBAAiB;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,mBAAmB,MAAM,uBAAAC,QAAgB;AAAA,IAC7C;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACQ;AAAA,EACV;AAGA,QAAM,cAAc,MAAM,cAAAC,QAAY,WAAW;AAAA,IAC/C,QAAQ,oBAAoB,gBAAgB,CAAC;AAAA,IAC7C;AAAA,IACA,aAAa,mCAAY;AAAA,EAC3B,CAAC;AAED,QAAM,eAAe,cAAAA,QAAY,gCAAgC,YAAY,OAAO;AAGpF,QAAM,QAAQ,IAAI,mBAAAC,QAAY;AAAA,IAC5B,QAAQ,oBAAoB,gBAAgB,CAAC;AAAA,IAC7C,aAAa;AAAA,IACb,iBAAyB;AAAA,IACzB,YAAY,8BAAW;AAAA,EACzB,CAAC,EAAE,yBAAyB,IAAI;AAEhC,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAEA,MAAM,cAAc,CAClB,qBACA,eACA,OACA,uBACA,gBACuB;AACvB,SAAO,oBAAoB,SAAS,IAAI,CAAC,YAAiE;AACxG,UAAM,EAAE,IAAI,SAAS,OAAO,YAAY,IAAI;AAE5C,UAAM,wBAAwB;AAAA,MAC5B,CAAC,wCAA2B,IAAI,GAAG;AAAA,MACnC,CAAC,wCAA2B,GAAG,GAAG;AAAA,QAChC,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,sBAAsB,KAAK,OAAO;AAAA,MACtF;AAAA,MACA,CAAC,wCAA2B,IAAI,GAAG;AAAA,QACjC,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,uBAAuB,KAAK,OAAO;AAAA,MACvF;AAAA,MACA,CAAC,wCAA2B,KAAK,GAAG;AAAA,QAClC,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,wBAAwB,KAAK,OAAO;AAAA,MACxF;AAAA,MACA,CAAC,wCAA2B,SAAS,GAAG;AAAA,QACtC,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,4BAA4B,KAAK,OAAO;AAAA,MAC5F;AAAA,MACA,CAAC,wCAA2B,eAAe,GAAG;AAAA,QAC5C,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,iCAAiC,KAAK,OAAO;AAAA,MACjG;AAAA,MACA,CAAC,wCAA2B,iBAAiB,GAAG;AAAA,QAC9C,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,mCAAmC,KAAK,OAAO;AAAA,MACnG;AAAA,MACA,CAAC,wCAA2B,cAAc,GAAG;AAAA,QAC3C,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,gCAAgC,KAAK,OAAO;AAAA,MAChG;AAAA,MACA,CAAC,wCAA2B,eAAe,GAAG;AAAA,QAC5C,sBAAsB,KAAK,CAAC,SAAS,KAAK,QAAQ,iCAAiC,KAAK,OAAO;AAAA,MACjG;AAAA,IACF;AAEA,QAAI,eAAe;AACnB,UAAM,iBAA2C,QAAQ,eAAe;AAAA,MACtE,CAAC,kBAA6E;AAC5E,cAAM,EAAE,MAAM,SAAS,aAAa,gBAAgB,IAAI,MAAM,IAAI;AAClE,cAAM,YAAY,sBAAsB,IAAI;AAE5C,YAAI;AAEJ,gBAAQ,MAAM;AAAA,UACZ,KAAK,wCAA2B;AAC9B,mBAAO,cAAAC,QAAmB,WAAW,eAAe,aAAa;AACjE;AAAA,UAEF,KAAK,wCAA2B;AAC9B,2BAAe;AACf,mBAAO,IAAI,iBAAAC,QAAuB,EAAE,eAAe,aAAa,EAAE,SAAS,aAAa,EAAE,MAAM;AAChG;AAAA,UAEF,KAAK,wCAA2B;AAC9B,mBAAO,IAAI,sBAAAC,QAA4B,EAAE,eAAe,aAAa,EAAE,SAAS,aAAa,EAAE,MAAM;AACrG;AAAA,UAEF,KAAK,wCAA2B;AAAA,UAChC,KAAK,wCAA2B;AAAA,UAChC,KAAK,wCAA2B,OAAO;AACrC,mBAAO,aAAAC,QAAW,YAAY,eAAe,eAAe,IAAI;AAChE;AAAA,UACF;AAAA,UACA,KAAK,wCAA2B;AAAA,UAChC,KAAK,wCAA2B;AAAA,UAChC,KAAK,wCAA2B,iBAAiB;AAC/C,mBAAO,aAAAA,QAAW,uBAAuB,eAAe,eAAe,MAAM,OAAO,WAAW;AAC/F;AAAA,UACF;AAAA,UACA;AACE;AAAA,QACJ;AAEA,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,OAAO,WAAW;AAAA,UAClB,aAAa,kBAAkB;AAAA,UAC/B;AAAA,UACA;AAAA,UACA,WAAW,aAAa;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,oBAAAC,QAAgB;AAAA,QACd;AAAA,QACA,sBAAsB,wCAA2B,eAAe;AAAA,MAClE;AAEF,WAAO,EAAE,IAAI,OAAO,SAAS,IAAI,aAAa,eAAe,IAAI,eAAe;AAAA,EAClF,CAAC;AACH;AAEA,MAAM,cAAc,OAClB,UACA,SACA,QACA,UACA,KACA,YACyC;AACzC,QAAM,EAAE,uBAAuB,IAAI;AACnC,QAAM,uBAAuB,MAAM,uBAAuB,mBAAmB,SAAS,MAAM;AAG5F,MAAI,YAAY,SAAS,UAAU,sBAAsB;AACvD,kBAAAC,QAAiB,iBAAiB;AAAA,MAChC;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,MAAM,iBAAiB,CAAC,YAA2B;AACjD,MAAI;AACJ,QAAM,0BACJ,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,uBAAW,kBAAkB,YAAY,CAAC;AAE3E,MAAI,yBAAyB;AAC3B,kBAAc,wBAAwB,MAAM;AAAA,EAC9C;AACA,SAAO;AACT;AAEO,MAAM,uBAAuB,OAAO,EAAE,KAAK,KAAK,SAAS,MAA8B;AAC5F,QAAM,EAAE,OAAO,WAAW,SAAS,cAAc,IAAI,oBAAAT,QAAa,UAAU,GAAG;AAC/E,QAAM,EAAE,UAAU,IAAI,QAAQ,IAAI,IAAI;AACtC,QAAM,EAAE,iBAAiB,uBAAuB,IAAI;AACpD,QAAM,EAAE,IAAI,OAAO,IAAI;AAEvB,MAAI,cAA2C,MAAM,uBAAuB,mBAAmB,SAAS,MAAM;AAC9G,QAAM,YAAY,aAAa,OAAO;AAGtC,QAAM,EAAE,OAAO,SAAS,kBAAkB,oBAAoB,IAAI,MAAM,kBAAkB;AAAA,IACxF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,gBAA2C,MAAM,SAAS,iBAAiB;AAAA,IAC/E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,gBAAyC,cAAc,KAAK;AAClE,QAAM,cAAc,eAAe,QAAQ,OAAO;AAGlD,QAAM,wBAAwB,OAAO,OAAO,IAAI,IAAI,OAAO,aAAa,KAAK,EAAE;AAAA,IAC7E,CAAC,SAAS,KAAK,SAAS,kBAAkB,MAAM;AAAA,EAClD;AACA,QAAM,WAA+B;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,MAAI,wBAAwB;AAC1B,kBAAc,MAAM,YAAY,UAAU,SAAS,QAAQ,IAAI,UAAU,KAAK,QAAQ,OAAO;AAAA,EAC/F;AAEA,SAAO;AAAA,IACL,eAAe;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,oBAAoB;AAAA,MAC1B,aAAa,oBAAoB;AAAA,MACjC,YAAY,iBAAiB;AAAA,MAC7B,YAAY,MAAM,gBAAgB,aAAa,IAAI,UAAU,QAAQ,EAAE;AAAA,MACvE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,8BAAW;AAAA,MACjB,SAAS,oBAAoB,qBAAqB,kBAAkB,WAAW;AAAA,IACjF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": ["import_utils", "ReportActionsUtils", "LocalsHelper", "DefinitionUtils", "FilterUtils", "ReportQuery", "DashboardListUtils", "ScorecardVisualisation", "ScorecardGroupVisualisation", "ChartUtils", "ScorecardsUtils", "UserReportsUtils"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { Request, Response } from 'express'
2
+ import { Flag } from '@flipt-io/flipt'
2
3
  import { Services } from '../../../../../types/Services'
3
4
  import Dict = NodeJS.Dict
4
5
  import {
@@ -125,15 +126,45 @@ const getSections = (
125
126
  dashboardDefinition: components['schemas']['DashboardDefinition'],
126
127
  dashboardData: DashboardDataResponse[],
127
128
  query: Record<string, string | string[]>,
129
+ dashboardFeatureFlags: Flag[],
128
130
  partialDate?: PartialDate,
129
131
  ): DashboardSection[] => {
130
132
  return dashboardDefinition.sections.map((section: components['schemas']['DashboardSectionDefinition']) => {
131
133
  const { id, display: title, description } = section
132
134
 
135
+ const featureFlagVisTypeMap = {
136
+ [DashboardVisualisationType.LIST]: true,
137
+ [DashboardVisualisationType.BAR]: Boolean(
138
+ dashboardFeatureFlags.find((flag) => flag.key === 'barChartsEnabled' && flag.enabled),
139
+ ),
140
+ [DashboardVisualisationType.LINE]: Boolean(
141
+ dashboardFeatureFlags.find((flag) => flag.key === 'lineChartsEnabled' && flag.enabled),
142
+ ),
143
+ [DashboardVisualisationType.DONUT]: Boolean(
144
+ dashboardFeatureFlags.find((flag) => flag.key === 'donutChartsEnabled' && flag.enabled),
145
+ ),
146
+ [DashboardVisualisationType.SCORECARD]: Boolean(
147
+ dashboardFeatureFlags.find((flag) => flag.key === 'scorecardChartsEnabled' && flag.enabled),
148
+ ),
149
+ [DashboardVisualisationType.SCORECARD_GROUP]: Boolean(
150
+ dashboardFeatureFlags.find((flag) => flag.key === 'scorecardgroupChartsEnabled' && flag.enabled),
151
+ ),
152
+ [DashboardVisualisationType.MATRIX_TIMESERIES]: Boolean(
153
+ dashboardFeatureFlags.find((flag) => flag.key === 'matrixtimeseriesChartsEnabled' && flag.enabled),
154
+ ),
155
+ [DashboardVisualisationType.BAR_TIMESERIES]: Boolean(
156
+ dashboardFeatureFlags.find((flag) => flag.key === 'bartimeseriesChartsEnabled' && flag.enabled),
157
+ ),
158
+ [DashboardVisualisationType.LINE_TIMESERIES]: Boolean(
159
+ dashboardFeatureFlags.find((flag) => flag.key === 'linetimeseriesChartsEnabled' && flag.enabled),
160
+ ),
161
+ }
162
+
133
163
  let hasScorecard = false
134
164
  const visualisations: DashboardVisualisation[] = section.visualisations.map(
135
165
  (visDefinition: components['schemas']['DashboardVisualisationDefinition']) => {
136
166
  const { type, display, description: visDescription, id: visId } = visDefinition
167
+ const isEnabled = featureFlagVisTypeMap[type]
137
168
 
138
169
  let data: DashboardVisualisation['data'] | undefined
139
170
 
@@ -173,11 +204,16 @@ const getSections = (
173
204
  description: visDescription || '',
174
205
  type,
175
206
  data,
207
+ isEnabled: isEnabled ?? true,
176
208
  }
177
209
  },
178
210
  )
179
211
 
180
- if (hasScorecard) ScorecardsUtils.mergeScorecardsIntoGroup(visualisations)
212
+ if (hasScorecard)
213
+ ScorecardsUtils.mergeScorecardsIntoGroup(
214
+ visualisations,
215
+ featureFlagVisTypeMap[DashboardVisualisationType.SCORECARD_GROUP],
216
+ )
181
217
 
182
218
  return { id, title: title || '', description: description || '', visualisations }
183
219
  })
@@ -249,7 +285,16 @@ export const renderAsyncDashboard = async ({ req, res, services }: AsyncReportUt
249
285
  const partialDate = getPartialDate(filters.filters)
250
286
 
251
287
  // Get the dashboard parts
252
- const sections: DashboardSection[] = getSections(dashboardDefinition, flattenedData, query, partialDate)
288
+ const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(
289
+ (flag) => flag.metadata['dashboardFeature'] === true,
290
+ )
291
+ const sections: DashboardSection[] = getSections(
292
+ dashboardDefinition,
293
+ flattenedData,
294
+ query,
295
+ dashboardFeatureFlags,
296
+ partialDate,
297
+ )
253
298
 
254
299
  // Update the store
255
300
  if (requestedReportService) {
@@ -90,7 +90,15 @@ const renderSyncDashboard = async ({
90
90
  query
91
91
  );
92
92
  const flattenedData = dashboardData.flat();
93
- const sections = import_utils2.default.getSections(dashboardDefinition, flattenedData, query);
93
+ const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(
94
+ (flag) => flag.metadata["dashboardFeature"] === true
95
+ );
96
+ const sections = import_utils2.default.getSections(
97
+ dashboardDefinition,
98
+ flattenedData,
99
+ query,
100
+ dashboardFeatureFlags
101
+ );
94
102
  await setAsRecentlyViewed({
95
103
  req,
96
104
  services,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../dpr/routes/journeys/view-report/sync/dashboard/utils.ts"],
4
- "sourcesContent": ["import type { Request, Response } from 'express'\nimport Dict = NodeJS.Dict\n\nimport type { Services } from '../../../../../types/Services'\nimport { ReportType, RequestStatus } from '../../../../../types/UserReports'\nimport { FilterValue } from '../../../../../components/_filters/types'\nimport SelectedFiltersUtils from '../../../../../components/_filters/filters-selected/utils'\nimport LocalsHelper from '../../../../../utils/localsHelper'\nimport UserStoreItemBuilder from '../../../../../utils/UserStoreItemBuilder'\nimport { DashboardDataResponse } from '../../../../../types/Metrics'\nimport AsyncDashboardUtils from '../../async/dashboard/utils'\nimport { DashboardSection } from '../../../../../components/_dashboards/dashboard-visualisation/types'\nimport { components } from '../../../../../types/api'\nimport ReportActionsUtils from '../../../../../components/_reports/report-heading/report-actions/utils'\n\nconst setAsRecentlyViewed = async ({\n req,\n services,\n reportName,\n name,\n description,\n reportId,\n id,\n userId,\n filters,\n}: {\n req: Request\n services: Services\n reportName: string\n name: string\n description: string\n reportId: string\n id: string\n userId: string\n filters: FilterValue[]\n}) => {\n const stateData = {\n type: ReportType.DASHBOARD,\n reportId,\n id,\n reportName,\n description,\n name,\n }\n\n const interactiveQueryData: { query: Dict<string>; querySummary: Array<Dict<string>> } = {\n query: <Dict<string>>req.query,\n querySummary: SelectedFiltersUtils.getQuerySummary(<Dict<string>>req.query, filters),\n }\n\n const recentlyViewedData = new UserStoreItemBuilder(stateData)\n .addInteractiveQuery(interactiveQueryData)\n .addStatus(RequestStatus.READY)\n .addTimestamp()\n .addReportUrls(req)\n .build()\n\n await services.recentlyViewedService.setRecentlyViewed(recentlyViewedData, userId)\n}\n\nexport const renderSyncDashboard = async ({\n req,\n res,\n services,\n}: {\n req: Request\n res: Response\n services: Services\n}) => {\n const { token, csrfToken, dprUser, nestedBaseUrl } = LocalsHelper.getValues(res)\n const { reportId, id } = req.params\n const fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`\n\n const {\n query,\n filters: filterData,\n reportDefinition,\n dashboardDefinition,\n } = await AsyncDashboardUtils.getDefinitionData({\n req,\n res,\n services,\n })\n\n const dashboardData: DashboardDataResponse[][] = await services.dashboardService.getSyncDashboard(\n token,\n id,\n reportId,\n query,\n )\n const flattenedData: DashboardDataResponse[] = dashboardData.flat()\n\n // Get the dashboard parts\n const sections: DashboardSection[] = AsyncDashboardUtils.getSections(dashboardDefinition, flattenedData, query)\n\n await setAsRecentlyViewed({\n req,\n services,\n reportName: reportDefinition.name,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description || reportDefinition.description || '',\n reportId,\n id,\n userId: dprUser.id,\n filters: filterData.filters,\n })\n\n return {\n dashboardData: {\n token,\n id,\n reportId,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description,\n reportName: reportDefinition.name,\n bookmarked: await services.bookmarkService.isBookmarked(id, reportId, dprUser.id),\n nestedBaseUrl,\n csrfToken,\n sections,\n filters: filterData,\n type: ReportType.DASHBOARD,\n actions: setActions(dashboardDefinition, reportDefinition, fullUrl),\n },\n }\n}\n\nexport const setActions = (\n definition: components['schemas']['DashboardDefinition'],\n summaryDefinition: components['schemas']['ReportDefinitionSummary'],\n url: string,\n) => {\n const { name: reportName } = summaryDefinition\n const { name } = definition\n\n return ReportActionsUtils.getActions({\n share: {\n reportName,\n name,\n url,\n },\n copy: {\n url,\n },\n })\n}\n\nexport default {\n renderSyncDashboard,\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,yBAA0C;AAE1C,mBAAiC;AACjC,0BAAyB;AACzB,kCAAiC;AAEjC,IAAAA,gBAAgC;AAGhC,IAAAA,gBAA+B;AAE/B,MAAM,sBAAsB,OAAO;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAUM;AACJ,QAAM,YAAY;AAAA,IAChB,MAAM,8BAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,uBAAmF;AAAA,IACvF,OAAqB,IAAI;AAAA,IACzB,cAAc,aAAAC,QAAqB,gBAA8B,IAAI,OAAO,OAAO;AAAA,EACrF;AAEA,QAAM,qBAAqB,IAAI,4BAAAC,QAAqB,SAAS,EAC1D,oBAAoB,oBAAoB,EACxC,UAAU,iCAAc,KAAK,EAC7B,aAAa,EACb,cAAc,GAAG,EACjB,MAAM;AAET,QAAM,SAAS,sBAAsB,kBAAkB,oBAAoB,MAAM;AACnF;AAEO,MAAM,sBAAsB,OAAO;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,EAAE,OAAO,WAAW,SAAS,cAAc,IAAI,oBAAAC,QAAa,UAAU,GAAG;AAC/E,QAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC7B,QAAM,UAAU,GAAG,IAAI,QAAQ,MAAM,IAAI,IAAI,MAAM,CAAC,GAAG,IAAI,WAAW;AAEtE,QAAM;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF,IAAI,MAAM,cAAAC,QAAoB,kBAAkB;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,gBAA2C,MAAM,SAAS,iBAAiB;AAAA,IAC/E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,gBAAyC,cAAc,KAAK;AAGlE,QAAM,WAA+B,cAAAA,QAAoB,YAAY,qBAAqB,eAAe,KAAK;AAE9G,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,YAAY,iBAAiB;AAAA,IAC7B,MAAM,oBAAoB;AAAA,IAC1B,aAAa,oBAAoB,eAAe,iBAAiB,eAAe;AAAA,IAChF;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,SAAS,WAAW;AAAA,EACtB,CAAC;AAED,SAAO;AAAA,IACL,eAAe;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,oBAAoB;AAAA,MAC1B,aAAa,oBAAoB;AAAA,MACjC,YAAY,iBAAiB;AAAA,MAC7B,YAAY,MAAM,SAAS,gBAAgB,aAAa,IAAI,UAAU,QAAQ,EAAE;AAAA,MAChF;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,MAAM,8BAAW;AAAA,MACjB,SAAS,WAAW,qBAAqB,kBAAkB,OAAO;AAAA,IACpE;AAAA,EACF;AACF;AAEO,MAAM,aAAa,CACxB,YACA,mBACA,QACG;AACH,QAAM,EAAE,MAAM,WAAW,IAAI;AAC7B,QAAM,EAAE,KAAK,IAAI;AAEjB,SAAO,cAAAC,QAAmB,WAAW;AAAA,IACnC,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAO,gBAAQ;AAAA,EACb;AACF;",
4
+ "sourcesContent": ["import type { Request, Response } from 'express'\nimport Dict = NodeJS.Dict\n\nimport type { Services } from '../../../../../types/Services'\nimport { ReportType, RequestStatus } from '../../../../../types/UserReports'\nimport { FilterValue } from '../../../../../components/_filters/types'\nimport SelectedFiltersUtils from '../../../../../components/_filters/filters-selected/utils'\nimport LocalsHelper from '../../../../../utils/localsHelper'\nimport UserStoreItemBuilder from '../../../../../utils/UserStoreItemBuilder'\nimport { DashboardDataResponse } from '../../../../../types/Metrics'\nimport AsyncDashboardUtils from '../../async/dashboard/utils'\nimport { DashboardSection } from '../../../../../components/_dashboards/dashboard-visualisation/types'\nimport { components } from '../../../../../types/api'\nimport ReportActionsUtils from '../../../../../components/_reports/report-heading/report-actions/utils'\n\nconst setAsRecentlyViewed = async ({\n req,\n services,\n reportName,\n name,\n description,\n reportId,\n id,\n userId,\n filters,\n}: {\n req: Request\n services: Services\n reportName: string\n name: string\n description: string\n reportId: string\n id: string\n userId: string\n filters: FilterValue[]\n}) => {\n const stateData = {\n type: ReportType.DASHBOARD,\n reportId,\n id,\n reportName,\n description,\n name,\n }\n\n const interactiveQueryData: { query: Dict<string>; querySummary: Array<Dict<string>> } = {\n query: <Dict<string>>req.query,\n querySummary: SelectedFiltersUtils.getQuerySummary(<Dict<string>>req.query, filters),\n }\n\n const recentlyViewedData = new UserStoreItemBuilder(stateData)\n .addInteractiveQuery(interactiveQueryData)\n .addStatus(RequestStatus.READY)\n .addTimestamp()\n .addReportUrls(req)\n .build()\n\n await services.recentlyViewedService.setRecentlyViewed(recentlyViewedData, userId)\n}\n\nexport const renderSyncDashboard = async ({\n req,\n res,\n services,\n}: {\n req: Request\n res: Response\n services: Services\n}) => {\n const { token, csrfToken, dprUser, nestedBaseUrl } = LocalsHelper.getValues(res)\n const { reportId, id } = req.params\n const fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`\n\n const {\n query,\n filters: filterData,\n reportDefinition,\n dashboardDefinition,\n } = await AsyncDashboardUtils.getDefinitionData({\n req,\n res,\n services,\n })\n\n const dashboardData: DashboardDataResponse[][] = await services.dashboardService.getSyncDashboard(\n token,\n id,\n reportId,\n query,\n )\n const flattenedData: DashboardDataResponse[] = dashboardData.flat()\n\n // Get the dashboard parts\n const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(\n (flag) => flag.metadata['dashboardFeature'] === true,\n )\n const sections: DashboardSection[] = AsyncDashboardUtils.getSections(\n dashboardDefinition,\n flattenedData,\n query,\n dashboardFeatureFlags,\n )\n\n await setAsRecentlyViewed({\n req,\n services,\n reportName: reportDefinition.name,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description || reportDefinition.description || '',\n reportId,\n id,\n userId: dprUser.id,\n filters: filterData.filters,\n })\n\n return {\n dashboardData: {\n token,\n id,\n reportId,\n name: dashboardDefinition.name,\n description: dashboardDefinition.description,\n reportName: reportDefinition.name,\n bookmarked: await services.bookmarkService.isBookmarked(id, reportId, dprUser.id),\n nestedBaseUrl,\n csrfToken,\n sections,\n filters: filterData,\n type: ReportType.DASHBOARD,\n actions: setActions(dashboardDefinition, reportDefinition, fullUrl),\n },\n }\n}\n\nexport const setActions = (\n definition: components['schemas']['DashboardDefinition'],\n summaryDefinition: components['schemas']['ReportDefinitionSummary'],\n url: string,\n) => {\n const { name: reportName } = summaryDefinition\n const { name } = definition\n\n return ReportActionsUtils.getActions({\n share: {\n reportName,\n name,\n url,\n },\n copy: {\n url,\n },\n })\n}\n\nexport default {\n renderSyncDashboard,\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,yBAA0C;AAE1C,mBAAiC;AACjC,0BAAyB;AACzB,kCAAiC;AAEjC,IAAAA,gBAAgC;AAGhC,IAAAA,gBAA+B;AAE/B,MAAM,sBAAsB,OAAO;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAUM;AACJ,QAAM,YAAY;AAAA,IAChB,MAAM,8BAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,uBAAmF;AAAA,IACvF,OAAqB,IAAI;AAAA,IACzB,cAAc,aAAAC,QAAqB,gBAA8B,IAAI,OAAO,OAAO;AAAA,EACrF;AAEA,QAAM,qBAAqB,IAAI,4BAAAC,QAAqB,SAAS,EAC1D,oBAAoB,oBAAoB,EACxC,UAAU,iCAAc,KAAK,EAC7B,aAAa,EACb,cAAc,GAAG,EACjB,MAAM;AAET,QAAM,SAAS,sBAAsB,kBAAkB,oBAAoB,MAAM;AACnF;AAEO,MAAM,sBAAsB,OAAO;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,EAAE,OAAO,WAAW,SAAS,cAAc,IAAI,oBAAAC,QAAa,UAAU,GAAG;AAC/E,QAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC7B,QAAM,UAAU,GAAG,IAAI,QAAQ,MAAM,IAAI,IAAI,MAAM,CAAC,GAAG,IAAI,WAAW;AAEtE,QAAM;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF,IAAI,MAAM,cAAAC,QAAoB,kBAAkB;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,gBAA2C,MAAM,SAAS,iBAAiB;AAAA,IAC/E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,gBAAyC,cAAc,KAAK;AAGlE,QAAM,wBAAwB,OAAO,OAAO,IAAI,IAAI,OAAO,aAAa,KAAK,EAAE;AAAA,IAC7E,CAAC,SAAS,KAAK,SAAS,kBAAkB,MAAM;AAAA,EAClD;AACA,QAAM,WAA+B,cAAAA,QAAoB;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,YAAY,iBAAiB;AAAA,IAC7B,MAAM,oBAAoB;AAAA,IAC1B,aAAa,oBAAoB,eAAe,iBAAiB,eAAe;AAAA,IAChF;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,SAAS,WAAW;AAAA,EACtB,CAAC;AAED,SAAO;AAAA,IACL,eAAe;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,oBAAoB;AAAA,MAC1B,aAAa,oBAAoB;AAAA,MACjC,YAAY,iBAAiB;AAAA,MAC7B,YAAY,MAAM,SAAS,gBAAgB,aAAa,IAAI,UAAU,QAAQ,EAAE;AAAA,MAChF;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,MAAM,8BAAW;AAAA,MACjB,SAAS,WAAW,qBAAqB,kBAAkB,OAAO;AAAA,IACpE;AAAA,EACF;AACF;AAEO,MAAM,aAAa,CACxB,YACA,mBACA,QACG;AACH,QAAM,EAAE,MAAM,WAAW,IAAI;AAC7B,QAAM,EAAE,KAAK,IAAI;AAEjB,SAAO,cAAAC,QAAmB,WAAW;AAAA,IACnC,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAO,gBAAQ;AAAA,EACb;AACF;",
6
6
  "names": ["import_utils", "SelectedFiltersUtils", "UserStoreItemBuilder", "LocalsHelper", "AsyncDashboardUtils", "ReportActionsUtils"]
7
7
  }
@@ -91,7 +91,15 @@ export const renderSyncDashboard = async ({
91
91
  const flattenedData: DashboardDataResponse[] = dashboardData.flat()
92
92
 
93
93
  // Get the dashboard parts
94
- const sections: DashboardSection[] = AsyncDashboardUtils.getSections(dashboardDefinition, flattenedData, query)
94
+ const dashboardFeatureFlags = Object.values(res.app.locals.featureFlags.flags).filter(
95
+ (flag) => flag.metadata['dashboardFeature'] === true,
96
+ )
97
+ const sections: DashboardSection[] = AsyncDashboardUtils.getSections(
98
+ dashboardDefinition,
99
+ flattenedData,
100
+ query,
101
+ dashboardFeatureFlags,
102
+ )
95
103
 
96
104
  await setAsRecentlyViewed({
97
105
  req,
@@ -28,8 +28,8 @@ class FeatureFlagService {
28
28
  restClient;
29
29
  namespace;
30
30
  constructor(config = {}) {
31
- const { namespace, token, url } = config && config;
32
- if (Object.keys(config).length !== 3 || !namespace || !token || !url) {
31
+ const { token, url } = config && config;
32
+ if (Object.keys(config).length !== 2 || !token || !url) {
33
33
  return;
34
34
  }
35
35
  this.restClient = new import_flipt.FliptClient({
@@ -39,7 +39,7 @@ class FeatureFlagService {
39
39
  },
40
40
  url
41
41
  });
42
- this.namespace = namespace;
42
+ this.namespace = "hmpps-digital-prison-reporting";
43
43
  }
44
44
  async getFlags() {
45
45
  if (!this.restClient || !this.namespace) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../dpr/services/featureFlagService.ts"],
4
- "sourcesContent": ["import { FliptClient, ListFlagsResponse } from '@flipt-io/flipt'\nimport { Application } from 'express'\nimport { FeatureFlagConfig } from '../data/types'\n\nexport class FeatureFlagService {\n restClient: FliptClient | undefined\n\n namespace: string | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { namespace, token, url } = config && (config as FeatureFlagConfig)\n if (Object.keys(config).length !== 3 || !namespace || !token || !url) {\n return\n }\n this.restClient = new FliptClient({\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n url,\n })\n this.namespace = namespace\n }\n\n async getFlags(): Promise<ListFlagsResponse> {\n if (!this.restClient || !this.namespace) {\n return {\n flags: [],\n nextPageToken: '',\n totalCount: 0,\n }\n }\n return this.restClient.flags.listFlags(this.namespace)\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string) => {\n const flag = app.locals.featureFlags?.flags?.[flagName]\n if (flag && flag.type !== 'BOOLEAN_FLAG_TYPE') {\n throw Error('Tried to validate whether a non-boolean flag was enabled')\n }\n return flag\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n return !flag || flag.enabled\n}\n\nexport const isBooleanFlagExplicitlyEnabled = (flagName: string, app: Application): boolean => {\n return resolveFlag(app, flagName)?.enabled === true\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+C;AAIxC,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EAEA;AAAA,EAEA,YAAY,SAAsD,CAAC,GAAG;AACpE,UAAM,EAAE,WAAW,OAAO,IAAI,IAAI,UAAW;AAC7C,QAAI,OAAO,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK;AACpE;AAAA,IACF;AACA,SAAK,aAAa,IAAI,yBAAY;AAAA,MAChC,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,QAC9B,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,WAAuC;AAC3C,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,WAAW;AACvC,aAAO;AAAA,QACL,OAAO,CAAC;AAAA,QACR,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO,KAAK,WAAW,MAAM,UAAU,KAAK,SAAS;AAAA,EACvD;AACF;AAEA,MAAM,cAAc,CAAC,KAAkB,aAAqB;AAC1D,QAAM,OAAO,IAAI,OAAO,cAAc,QAAQ,QAAQ;AACtD,MAAI,QAAQ,KAAK,SAAS,qBAAqB;AAC7C,UAAM,MAAM,0DAA0D;AAAA,EACxE;AACA,SAAO;AACT;AAEO,MAAM,gCAAgC,CAAC,UAAkB,QAA8B;AAC5F,QAAM,OAAO,YAAY,KAAK,QAAQ;AACtC,SAAO,CAAC,QAAQ,KAAK;AACvB;AAEO,MAAM,iCAAiC,CAAC,UAAkB,QAA8B;AAC7F,SAAO,YAAY,KAAK,QAAQ,GAAG,YAAY;AACjD;",
4
+ "sourcesContent": ["import { FliptClient, ListFlagsResponse } from '@flipt-io/flipt'\nimport { Application } from 'express'\nimport { FeatureFlagConfig } from '../data/types'\n\n// Override this until types are fixed - metadata is returned, but not in the types\ndeclare module '@flipt-io/flipt' {\n interface Flag {\n metadata: Record<string, string | boolean | number>\n }\n}\n\nexport class FeatureFlagService {\n restClient: FliptClient | undefined\n\n namespace: string | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { token, url } = config && (config as FeatureFlagConfig)\n if (Object.keys(config).length !== 2 || !token || !url) {\n return\n }\n this.restClient = new FliptClient({\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n url,\n })\n this.namespace = 'hmpps-digital-prison-reporting'\n }\n\n async getFlags(): Promise<ListFlagsResponse> {\n if (!this.restClient || !this.namespace) {\n return {\n flags: [],\n nextPageToken: '',\n totalCount: 0,\n }\n }\n return this.restClient.flags.listFlags(this.namespace)\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string) => {\n const flag = app.locals.featureFlags?.flags?.[flagName]\n if (flag && flag.type !== 'BOOLEAN_FLAG_TYPE') {\n throw Error('Tried to validate whether a non-boolean flag was enabled')\n }\n return flag\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n return !flag || flag.enabled\n}\n\nexport const isBooleanFlagExplicitlyEnabled = (flagName: string, app: Application): boolean => {\n return resolveFlag(app, flagName)?.enabled === true\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+C;AAWxC,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EAEA;AAAA,EAEA,YAAY,SAAsD,CAAC,GAAG;AACpE,UAAM,EAAE,OAAO,IAAI,IAAI,UAAW;AAClC,QAAI,OAAO,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC,SAAS,CAAC,KAAK;AACtD;AAAA,IACF;AACA,SAAK,aAAa,IAAI,yBAAY;AAAA,MAChC,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,QAC9B,gBAAgB;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,WAAuC;AAC3C,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,WAAW;AACvC,aAAO;AAAA,QACL,OAAO,CAAC;AAAA,QACR,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO,KAAK,WAAW,MAAM,UAAU,KAAK,SAAS;AAAA,EACvD;AACF;AAEA,MAAM,cAAc,CAAC,KAAkB,aAAqB;AAC1D,QAAM,OAAO,IAAI,OAAO,cAAc,QAAQ,QAAQ;AACtD,MAAI,QAAQ,KAAK,SAAS,qBAAqB;AAC7C,UAAM,MAAM,0DAA0D;AAAA,EACxE;AACA,SAAO;AACT;AAEO,MAAM,gCAAgC,CAAC,UAAkB,QAA8B;AAC5F,QAAM,OAAO,YAAY,KAAK,QAAQ;AACtC,SAAO,CAAC,QAAQ,KAAK;AACvB;AAEO,MAAM,iCAAiC,CAAC,UAAkB,QAA8B;AAC7F,SAAO,YAAY,KAAK,QAAQ,GAAG,YAAY;AACjD;",
6
6
  "names": []
7
7
  }
@@ -2,14 +2,21 @@ import { FliptClient, ListFlagsResponse } from '@flipt-io/flipt'
2
2
  import { Application } from 'express'
3
3
  import { FeatureFlagConfig } from '../data/types'
4
4
 
5
+ // Override this until types are fixed - metadata is returned, but not in the types
6
+ declare module '@flipt-io/flipt' {
7
+ interface Flag {
8
+ metadata: Record<string, string | boolean | number>
9
+ }
10
+ }
11
+
5
12
  export class FeatureFlagService {
6
13
  restClient: FliptClient | undefined
7
14
 
8
15
  namespace: string | undefined
9
16
 
10
17
  constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {
11
- const { namespace, token, url } = config && (config as FeatureFlagConfig)
12
- if (Object.keys(config).length !== 3 || !namespace || !token || !url) {
18
+ const { token, url } = config && (config as FeatureFlagConfig)
19
+ if (Object.keys(config).length !== 2 || !token || !url) {
13
20
  return
14
21
  }
15
22
  this.restClient = new FliptClient({
@@ -19,7 +26,7 @@ export class FeatureFlagService {
19
26
  },
20
27
  url,
21
28
  })
22
- this.namespace = namespace
29
+ this.namespace = 'hmpps-digital-prison-reporting'
23
30
  }
24
31
 
25
32
  async getFlags(): Promise<ListFlagsResponse> {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ministryofjustice/hmpps-digital-prison-reporting-frontend",
3
3
  "description": "The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.",
4
- "version": "4.29.4",
4
+ "version": "4.30.1",
5
5
  "main": "dpr/all",
6
6
  "sass": "dpr/all.scss",
7
7
  "engines": {
@@ -194,7 +194,6 @@
194
194
  "@typescript-eslint/eslint-plugin": "^5.60.1",
195
195
  "@typescript-eslint/parser": "^5.62.0",
196
196
  "audit-ci": "^6.6.1",
197
- "autoprefixer": "^10.4.15",
198
197
  "axe-core": "^4.9.0",
199
198
  "cypress": "^14.5.4",
200
199
  "cypress-axe": "^1.6.0",