@bygd/nc-report-ui 0.1.29 → 0.1.30

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.
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import React__default, { useEffect, useMemo, useState, useRef, createContext, useContext } from 'react';
2
+ import React__default, { useEffect, useMemo, useState, useRef, useContext, createContext } from 'react';
3
3
  import Paper from '@material-ui/core/Paper';
4
4
  import { makeStyles } from '@material-ui/core/styles';
5
5
  import { CircularProgress } from '@material-ui/core';
@@ -43,6 +43,9 @@ import CheckIcon from '@mui/icons-material/Check';
43
43
  import CloseIcon from '@mui/icons-material/Close';
44
44
  import RestartAltIcon from '@mui/icons-material/RestartAlt';
45
45
  import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
46
+ import StorageIcon from '@mui/icons-material/Storage';
47
+ import TrendingUpIcon from '@mui/icons-material/TrendingUp';
48
+ import BoltIcon from '@mui/icons-material/Bolt';
46
49
  import FilterAltIcon from '@mui/icons-material/FilterAlt';
47
50
  import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
48
51
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
@@ -876,7 +879,8 @@ function SingleSelect({
876
879
  const {
877
880
  key,
878
881
  value,
879
- disabled
882
+ disabled,
883
+ icon
880
884
  } = itm;
881
885
  return /*#__PURE__*/React__default.createElement(MenuItem, {
882
886
  key: key,
@@ -884,9 +888,18 @@ function SingleSelect({
884
888
  disabled: disabled,
885
889
  sx: {
886
890
  fontFamily: "system-ui",
887
- minHeight: "36px"
891
+ minHeight: "36px",
892
+ display: "flex",
893
+ alignItems: "center",
894
+ gap: "6px"
895
+ }
896
+ }, icon && /*#__PURE__*/React__default.createElement(Box, {
897
+ component: "span",
898
+ sx: {
899
+ display: "inline-flex",
900
+ alignItems: "center"
888
901
  }
889
- }, formatLabel(value));
902
+ }, icon), formatLabel(value));
890
903
  }))));
891
904
  }
892
905
 
@@ -2888,6 +2901,51 @@ const Dimensions = ({
2888
2901
  })))))));
2889
2902
  };
2890
2903
 
2904
+ const MetricSourceIcon = ({
2905
+ source
2906
+ }) => {
2907
+ const iconSx = {
2908
+ fontSize: '15px'
2909
+ };
2910
+ if (source === 'kpi') {
2911
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
2912
+ title: "KPI Metric",
2913
+ arrow: true,
2914
+ placement: "top"
2915
+ }, /*#__PURE__*/React__default.createElement(TrendingUpIcon, {
2916
+ sx: {
2917
+ ...iconSx,
2918
+ color: 'rgb(70, 134, 128)'
2919
+ }
2920
+ }));
2921
+ }
2922
+ if (source === 'dynamic') {
2923
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
2924
+ title: "Dynamic Metric",
2925
+ arrow: true,
2926
+ placement: "top"
2927
+ }, /*#__PURE__*/React__default.createElement(BoltIcon, {
2928
+ sx: {
2929
+ ...iconSx,
2930
+ color: '#e65100'
2931
+ }
2932
+ }));
2933
+ }
2934
+ if (source === 'provider') {
2935
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
2936
+ title: "Provider Metric",
2937
+ arrow: true,
2938
+ placement: "top"
2939
+ }, /*#__PURE__*/React__default.createElement(StorageIcon, {
2940
+ sx: {
2941
+ ...iconSx,
2942
+ color: '#546e7a'
2943
+ }
2944
+ }));
2945
+ }
2946
+ return null;
2947
+ };
2948
+
2891
2949
  // Sortable Chip Component
2892
2950
  const SortableChip = ({
2893
2951
  id,
@@ -2902,7 +2960,8 @@ const SortableChip = ({
2902
2960
  defaultTitle,
2903
2961
  customTitle,
2904
2962
  onUpdateTitle,
2905
- onResetTitle
2963
+ onResetTitle,
2964
+ source
2906
2965
  }) => {
2907
2966
  const [isEditing, setIsEditing] = useState(false);
2908
2967
  const [editValue, setEditValue] = useState('');
@@ -3015,7 +3074,15 @@ const SortableChip = ({
3015
3074
  cursor: "grab",
3016
3075
  color: "rgba(110, 110, 110, 0.62)"
3017
3076
  }
3018
- })), !isEditing ? /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box$1, {
3077
+ })), !isEditing ? /*#__PURE__*/React__default.createElement(React__default.Fragment, null, source && /*#__PURE__*/React__default.createElement(Box$1, {
3078
+ sx: {
3079
+ display: 'flex',
3080
+ alignItems: 'center',
3081
+ flexShrink: 0
3082
+ }
3083
+ }, /*#__PURE__*/React__default.createElement(MetricSourceIcon, {
3084
+ source: source
3085
+ })), /*#__PURE__*/React__default.createElement(Box$1, {
3019
3086
  sx: {
3020
3087
  minWidth: 0
3021
3088
  }
@@ -3247,7 +3314,10 @@ const Metrics = ({
3247
3314
  value: metric.title || metric.name,
3248
3315
  metricName: metric.name,
3249
3316
  metric: metric,
3250
- disabled: isAlreadySelected
3317
+ disabled: isAlreadySelected,
3318
+ icon: metric.source ? /*#__PURE__*/React__default.createElement(MetricSourceIcon, {
3319
+ source: metric.source
3320
+ }) : undefined
3251
3321
  };
3252
3322
  });
3253
3323
  return items;
@@ -3556,7 +3626,8 @@ const Metrics = ({
3556
3626
  defaultTitle: metric.metricTitle,
3557
3627
  customTitle: titleOverrides[metric.fullPath],
3558
3628
  onUpdateTitle: onUpdateTitle,
3559
- onResetTitle: onResetTitle
3629
+ onResetTitle: onResetTitle,
3630
+ source: metric.metric?.source
3560
3631
  })))))));
3561
3632
  };
3562
3633
 
@@ -4838,31 +4909,39 @@ const ReportDataGrid = ({
4838
4909
  });
4839
4910
 
4840
4911
  // Add metric columns
4841
- // Metric field naming logic:
4842
- // - If from base provider: baseAlias.metric -> metric (no prefix at all)
4843
- // - If from nested provider: baseAlias_rel1_rel2.metric -> rel1_rel2_metric (drops base alias)
4912
+ // The API returns metric keys in two different forms depending on the path depth:
4913
+ //
4914
+ // 2-part path "mc.record_count" → API key: "record_count"
4915
+ // • 2-part path "mc_fa.total_amount" (nested) → API key: "fa_total_amount"
4916
+ // • 3+-part path "mc.dkpi.activeAgreementsCount"→ API key: "mc.dkpi.activeAgreementsCount" (dots)
4917
+ //
4918
+ // For 3+-part paths the API key contains dots. MUI DataGrid interprets dots
4919
+ // in field names as nested-object accessors, so the rows useMemo normalises
4920
+ // those keys (dots → underscores). The column field must match that normalised key.
4844
4921
  metrics.forEach(metric => {
4845
4922
  const metricDef = metric.metric;
4846
4923
  let fieldName;
4847
4924
  let headerName;
4848
-
4849
- // Check if there are relations (nested providers)
4850
- if (metric.relations && metric.relations.length > 0) {
4851
- // From nested provider: drop the base provider alias
4852
- // Example: ft_fa.total_amount -> fa_total_amount
4925
+ const dotCount = (metric.fullPath.match(/\./g) || []).length;
4926
+ if (dotCount >= 2) {
4927
+ // 3+-part namespaced path: API returns the full dotted path as the key.
4928
+ // Normalise dots to underscores to match the row key normalisation below.
4929
+ // Example: "mc.dkpi.activeAgreementsCount" -> "mc_dkpi_activeAgreementsCount"
4930
+ fieldName = metric.fullPath.replace(/\./g, '_');
4931
+ } else if (metric.relations && metric.relations.length > 0) {
4932
+ // 2-part path from a nested provider: API drops the base provider alias.
4933
+ // Example: "mc_fa.total_amount" -> "fa_total_amount"
4853
4934
  const parts = metric.fullPath.split('.');
4854
- const pathWithoutField = parts[0]; // e.g., "ft_fa"
4935
+ const pathWithoutField = parts[0]; // e.g., "mc_fa"
4855
4936
  const field = parts[1]; // e.g., "total_amount"
4856
4937
 
4857
- // Remove the base provider alias (first part before first underscore)
4858
4938
  const pathParts = pathWithoutField.split('_');
4859
- pathParts.shift(); // Remove base provider alias
4860
- const pathWithoutBase = pathParts.join('_'); // e.g., "fa"
4861
-
4939
+ pathParts.shift(); // remove base provider alias
4940
+ const pathWithoutBase = pathParts.join('_');
4862
4941
  fieldName = pathWithoutBase ? `${pathWithoutBase}_${field}` : field;
4863
4942
  } else {
4864
- // From base provider: no prefix at all, just the metric name
4865
- // Example: fo.total_amount -> total_amount
4943
+ // 2-part path from the base provider: API returns just the metric name.
4944
+ // Example: "mc.record_count" -> "record_count"
4866
4945
  fieldName = metric.metricName;
4867
4946
  }
4868
4947
 
@@ -4874,6 +4953,15 @@ const ReportDataGrid = ({
4874
4953
  flex: 1,
4875
4954
  minWidth: 150,
4876
4955
  type: metricDef?.type === 'integer' || metricDef?.type === 'currency' ? 'number' : 'string',
4956
+ renderHeader: () => /*#__PURE__*/React__default.createElement(Box$1, {
4957
+ sx: {
4958
+ display: 'flex',
4959
+ alignItems: 'center',
4960
+ gap: 0.5
4961
+ }
4962
+ }, /*#__PURE__*/React__default.createElement(MetricSourceIcon, {
4963
+ source: metricDef?.source
4964
+ }), /*#__PURE__*/React__default.createElement("span", null, headerName)),
4877
4965
  valueFormatter: value => {
4878
4966
  if (value == null) return '';
4879
4967
 
@@ -4892,14 +4980,22 @@ const ReportDataGrid = ({
4892
4980
  return cols;
4893
4981
  }, [dimensions, metrics, titleOverrides]);
4894
4982
 
4895
- // Transform report data to rows with unique IDs
4983
+ // Transform report data to rows with unique IDs.
4984
+ // Keys are normalised by replacing dots with underscores so that MUI DataGrid
4985
+ // does not misinterpret dotted keys (e.g. "mc.dkpi.exposure") as nested
4986
+ // object paths. Dimension keys returned by the API are already underscore-
4987
+ // based, so normalisation is a no-op for them.
4896
4988
  const rows = React__default.useMemo(() => {
4897
4989
  if (!reportData || !Array.isArray(reportData)) return [];
4898
- return reportData.map((row, index) => ({
4899
- id: index,
4900
- // DataGrid requires unique id for each row
4901
- ...row
4902
- }));
4990
+ return reportData.map((row, index) => {
4991
+ const normalizedRow = {
4992
+ id: index
4993
+ };
4994
+ Object.entries(row).forEach(([key, value]) => {
4995
+ normalizedRow[key.replace(/\./g, '_')] = value;
4996
+ });
4997
+ return normalizedRow;
4998
+ });
4903
4999
  }, [reportData]);
4904
5000
 
4905
5001
  // Handle pagination change
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bygd/nc-report-ui",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "fnet/input.yaml",