@bygd/nc-report-ui 0.1.40 → 0.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/esm/index.js +309 -227
- package/dist/default/cjs/index.cjs +308 -226
- package/dist/default/esm/index.js +308 -226
- package/package.json +1 -1
|
@@ -1653,6 +1653,39 @@ const ReportingProvider = ({
|
|
|
1653
1653
|
}, children);
|
|
1654
1654
|
};
|
|
1655
1655
|
|
|
1656
|
+
/**
|
|
1657
|
+
* useReportingContext - Hook to access reporting context
|
|
1658
|
+
*
|
|
1659
|
+
* @returns {Object} Context value with parameters, api, and setter functions
|
|
1660
|
+
* @returns {Object} return.parameters - Current parameters object
|
|
1661
|
+
* @returns {Function} return.setParameters - Function to update parameters
|
|
1662
|
+
* @returns {Object} return.api - Current API configuration
|
|
1663
|
+
* @returns {Function} return.setApi - Function to update API configuration
|
|
1664
|
+
* @returns {Function} return.setReportingContext - Function to update both parameters and api
|
|
1665
|
+
*
|
|
1666
|
+
* @example
|
|
1667
|
+
* const { parameters, setParameters, api, setApi, setReportingContext } = useReportingContext();
|
|
1668
|
+
*
|
|
1669
|
+
* // Update parameters only
|
|
1670
|
+
* setParameters({ base_currency: 'USD', merchants: [...] });
|
|
1671
|
+
*
|
|
1672
|
+
* // Update API only
|
|
1673
|
+
* setApi({ token: 'new-token', base_url: 'https://api.example.com' });
|
|
1674
|
+
*
|
|
1675
|
+
* // Update both at once
|
|
1676
|
+
* setReportingContext({
|
|
1677
|
+
* parameters: { base_currency: 'EUR' },
|
|
1678
|
+
* api: { token: 'token', base_url: 'https://api.example.com' }
|
|
1679
|
+
* });
|
|
1680
|
+
*/
|
|
1681
|
+
const useReportingContext = () => {
|
|
1682
|
+
const context = React.useContext(ReportingContext);
|
|
1683
|
+
if (context === undefined) {
|
|
1684
|
+
throw new Error('useReportingContext must be used within a ReportingProvider');
|
|
1685
|
+
}
|
|
1686
|
+
return context;
|
|
1687
|
+
};
|
|
1688
|
+
|
|
1656
1689
|
/**
|
|
1657
1690
|
* useReportingContextOptional - Hook to optionally access reporting context
|
|
1658
1691
|
* Returns null if used outside of ReportingProvider (useful for optional fallback)
|
|
@@ -2896,7 +2929,6 @@ const SortableChip$1 = ({
|
|
|
2896
2929
|
// the top-of-page Add form, so it stays visible regardless of scroll position.
|
|
2897
2930
|
const SortableComputedChip = ({
|
|
2898
2931
|
id,
|
|
2899
|
-
index,
|
|
2900
2932
|
name,
|
|
2901
2933
|
value,
|
|
2902
2934
|
onDelete,
|
|
@@ -2949,13 +2981,13 @@ const SortableComputedChip = ({
|
|
|
2949
2981
|
setEditValue(value);
|
|
2950
2982
|
setIsEditing(true);
|
|
2951
2983
|
};
|
|
2952
|
-
const nameError = editName.trim() !== "" && isNameTaken(editName.trim(),
|
|
2984
|
+
const nameError = editName.trim() !== "" && isNameTaken(editName.trim(), name);
|
|
2953
2985
|
const handleSave = () => {
|
|
2954
2986
|
const trimmedName = editName.trim();
|
|
2955
2987
|
const trimmedValue = editValue.trim();
|
|
2956
2988
|
if (!trimmedName || !trimmedValue) return;
|
|
2957
|
-
if (isNameTaken(trimmedName,
|
|
2958
|
-
onUpdate(
|
|
2989
|
+
if (isNameTaken(trimmedName, name)) return;
|
|
2990
|
+
onUpdate(name, {
|
|
2959
2991
|
name: trimmedName,
|
|
2960
2992
|
value: trimmedValue
|
|
2961
2993
|
});
|
|
@@ -3153,7 +3185,7 @@ const Dimensions = ({
|
|
|
3153
3185
|
savedDimensions = [],
|
|
3154
3186
|
onSaveDimension,
|
|
3155
3187
|
onRemoveDimension,
|
|
3156
|
-
|
|
3188
|
+
onUpdateDimensionSortOrder,
|
|
3157
3189
|
titleOverrides = {},
|
|
3158
3190
|
onUpdateTitle,
|
|
3159
3191
|
onResetTitle,
|
|
@@ -3163,7 +3195,8 @@ const Dimensions = ({
|
|
|
3163
3195
|
onSaveComputedDimension,
|
|
3164
3196
|
onUpdateComputedDimension,
|
|
3165
3197
|
onRemoveComputedDimension,
|
|
3166
|
-
|
|
3198
|
+
dimensionOrder = [],
|
|
3199
|
+
onReorderDimensionItems
|
|
3167
3200
|
}) => {
|
|
3168
3201
|
const reportingContext = useReportingContextOptional();
|
|
3169
3202
|
const parameters = reportingContext?.parameters;
|
|
@@ -3179,49 +3212,56 @@ const Dimensions = ({
|
|
|
3179
3212
|
coordinateGetter: sortable.sortableKeyboardCoordinates
|
|
3180
3213
|
}));
|
|
3181
3214
|
|
|
3182
|
-
//
|
|
3215
|
+
// Resolve the unified dimensionOrder into the actual dimension / computed
|
|
3216
|
+
// dimension objects, so dimensions and computed dimensions can be shown
|
|
3217
|
+
// (and dragged) as a single list while staying stored in their own arrays.
|
|
3218
|
+
const dimensionByFullPath = Object.fromEntries(savedDimensions.map(d => [d.fullPath, d]));
|
|
3219
|
+
const computedDimensionByName = Object.fromEntries(savedComputedDimensions.map(cd => [cd.name, cd]));
|
|
3220
|
+
const orderedItems = dimensionOrder.map(entry => entry.type === "dimension" ? {
|
|
3221
|
+
kind: "dimension",
|
|
3222
|
+
key: entry.key,
|
|
3223
|
+
data: dimensionByFullPath[entry.key]
|
|
3224
|
+
} : {
|
|
3225
|
+
kind: "computed",
|
|
3226
|
+
key: entry.key,
|
|
3227
|
+
data: computedDimensionByName[entry.key]
|
|
3228
|
+
}).filter(item => item.data);
|
|
3229
|
+
|
|
3230
|
+
// Handle drag end for the unified list
|
|
3183
3231
|
const handleDragEnd = event => {
|
|
3184
3232
|
const {
|
|
3185
3233
|
active,
|
|
3186
3234
|
over
|
|
3187
3235
|
} = event;
|
|
3188
3236
|
if (over && active.id !== over.id) {
|
|
3189
|
-
const oldIndex =
|
|
3190
|
-
const newIndex =
|
|
3191
|
-
|
|
3192
|
-
onReorderDimensions(newOrder);
|
|
3237
|
+
const oldIndex = dimensionOrder.findIndex((_, i) => i === active.id);
|
|
3238
|
+
const newIndex = dimensionOrder.findIndex((_, i) => i === over.id);
|
|
3239
|
+
onReorderDimensionItems(sortable.arrayMove(dimensionOrder, oldIndex, newIndex));
|
|
3193
3240
|
}
|
|
3194
3241
|
};
|
|
3195
3242
|
|
|
3196
3243
|
// Handle move up
|
|
3197
3244
|
const handleMoveUp = index => {
|
|
3198
3245
|
if (index > 0) {
|
|
3199
|
-
|
|
3200
|
-
onReorderDimensions(newOrder);
|
|
3246
|
+
onReorderDimensionItems(sortable.arrayMove(dimensionOrder, index, index - 1));
|
|
3201
3247
|
}
|
|
3202
3248
|
};
|
|
3203
3249
|
|
|
3204
3250
|
// Handle move down
|
|
3205
3251
|
const handleMoveDown = index => {
|
|
3206
|
-
if (index <
|
|
3207
|
-
|
|
3208
|
-
onReorderDimensions(newOrder);
|
|
3252
|
+
if (index < dimensionOrder.length - 1) {
|
|
3253
|
+
onReorderDimensionItems(sortable.arrayMove(dimensionOrder, index, index + 1));
|
|
3209
3254
|
}
|
|
3210
3255
|
};
|
|
3211
3256
|
|
|
3212
|
-
// Handle sort order change
|
|
3213
|
-
const handleSortOrderChange = (
|
|
3214
|
-
|
|
3215
|
-
newDimensions[index] = {
|
|
3216
|
-
...newDimensions[index],
|
|
3217
|
-
sortOrder
|
|
3218
|
-
};
|
|
3219
|
-
onReorderDimensions(newDimensions);
|
|
3257
|
+
// Handle sort order change (dimensions only - computed dimensions have no order_by)
|
|
3258
|
+
const handleSortOrderChange = (fullPath, sortOrder) => {
|
|
3259
|
+
onUpdateDimensionSortOrder(fullPath, sortOrder);
|
|
3220
3260
|
};
|
|
3221
3261
|
|
|
3222
3262
|
// Computed Dimensions: { name, value } pairs independent of any provider.
|
|
3223
3263
|
// Their `value` is a raw SQL literal/expression sent to the API as-is.
|
|
3224
|
-
const isComputedNameTaken = (name,
|
|
3264
|
+
const isComputedNameTaken = (name, excludeName = null) => savedComputedDimensions.some(cd => cd.name === name) && name !== excludeName;
|
|
3225
3265
|
const computedNameError = computedName.trim() !== "" && isComputedNameTaken(computedName.trim());
|
|
3226
3266
|
const handleAddComputedClick = () => {
|
|
3227
3267
|
setIsAddingComputed(true);
|
|
@@ -3245,27 +3285,6 @@ const Dimensions = ({
|
|
|
3245
3285
|
});
|
|
3246
3286
|
handleCancelComputed();
|
|
3247
3287
|
};
|
|
3248
|
-
const handleComputedDragEnd = event => {
|
|
3249
|
-
const {
|
|
3250
|
-
active,
|
|
3251
|
-
over
|
|
3252
|
-
} = event;
|
|
3253
|
-
if (over && active.id !== over.id) {
|
|
3254
|
-
const oldIndex = savedComputedDimensions.findIndex((_, i) => i === active.id);
|
|
3255
|
-
const newIndex = savedComputedDimensions.findIndex((_, i) => i === over.id);
|
|
3256
|
-
onReorderComputedDimensions(sortable.arrayMove(savedComputedDimensions, oldIndex, newIndex));
|
|
3257
|
-
}
|
|
3258
|
-
};
|
|
3259
|
-
const handleMoveComputedUp = index => {
|
|
3260
|
-
if (index > 0) {
|
|
3261
|
-
onReorderComputedDimensions(sortable.arrayMove(savedComputedDimensions, index, index - 1));
|
|
3262
|
-
}
|
|
3263
|
-
};
|
|
3264
|
-
const handleMoveComputedDown = index => {
|
|
3265
|
-
if (index < savedComputedDimensions.length - 1) {
|
|
3266
|
-
onReorderComputedDimensions(sortable.arrayMove(savedComputedDimensions, index, index + 1));
|
|
3267
|
-
}
|
|
3268
|
-
};
|
|
3269
3288
|
|
|
3270
3289
|
// Get the current provider based on selection chain
|
|
3271
3290
|
const getCurrentProvider = () => {
|
|
@@ -3708,7 +3727,7 @@ const Dimensions = ({
|
|
|
3708
3727
|
boxShadow: "none"
|
|
3709
3728
|
}
|
|
3710
3729
|
}
|
|
3711
|
-
}, "Save Dimension"))),
|
|
3730
|
+
}, "Save Dimension"))), orderedItems.length > 0 && /*#__PURE__*/React__namespace.default.createElement(material.Box, {
|
|
3712
3731
|
sx: {
|
|
3713
3732
|
marginTop: 0
|
|
3714
3733
|
}
|
|
@@ -3731,7 +3750,7 @@ const Dimensions = ({
|
|
|
3731
3750
|
collisionDetection: core.closestCenter,
|
|
3732
3751
|
onDragEnd: handleDragEnd
|
|
3733
3752
|
}, /*#__PURE__*/React__namespace.default.createElement(sortable.SortableContext, {
|
|
3734
|
-
items:
|
|
3753
|
+
items: orderedItems.map((_, index) => index),
|
|
3735
3754
|
strategy: sortable.verticalListSortingStrategy
|
|
3736
3755
|
}, /*#__PURE__*/React__namespace.default.createElement(material.Box, {
|
|
3737
3756
|
sx: {
|
|
@@ -3739,67 +3758,35 @@ const Dimensions = ({
|
|
|
3739
3758
|
flexDirection: "column",
|
|
3740
3759
|
gap: 1
|
|
3741
3760
|
}
|
|
3742
|
-
},
|
|
3743
|
-
key:
|
|
3761
|
+
}, orderedItems.map((item, index) => item.kind === "dimension" ? /*#__PURE__*/React__namespace.default.createElement(SortableChip$1, {
|
|
3762
|
+
key: `dim-${item.key}`,
|
|
3744
3763
|
id: index,
|
|
3745
|
-
label:
|
|
3746
|
-
fullLabel: `${formatProviderPath(
|
|
3747
|
-
onDelete: () => onRemoveDimension(
|
|
3764
|
+
label: item.data.dimensionTitle,
|
|
3765
|
+
fullLabel: `${formatProviderPath(item.data)} → ${item.data.dimensionTitle} (${item.data.fullPath})`,
|
|
3766
|
+
onDelete: () => onRemoveDimension(item.key),
|
|
3748
3767
|
onMoveUp: () => handleMoveUp(index),
|
|
3749
3768
|
onMoveDown: () => handleMoveDown(index),
|
|
3750
3769
|
isFirst: index === 0,
|
|
3751
|
-
isLast: index ===
|
|
3752
|
-
sortOrder:
|
|
3753
|
-
onSortOrderChange: sortOrder => handleSortOrderChange(
|
|
3754
|
-
fullPath:
|
|
3755
|
-
defaultTitle:
|
|
3756
|
-
customTitle: titleOverrides[
|
|
3770
|
+
isLast: index === orderedItems.length - 1,
|
|
3771
|
+
sortOrder: item.data.sortOrder || null,
|
|
3772
|
+
onSortOrderChange: sortOrder => handleSortOrderChange(item.key, sortOrder),
|
|
3773
|
+
fullPath: item.data.fullPath,
|
|
3774
|
+
defaultTitle: item.data.dimensionTitle,
|
|
3775
|
+
customTitle: titleOverrides[item.data.fullPath],
|
|
3757
3776
|
onUpdateTitle: onUpdateTitle,
|
|
3758
3777
|
onResetTitle: onResetTitle
|
|
3759
|
-
})
|
|
3760
|
-
|
|
3761
|
-
marginTop: 2
|
|
3762
|
-
}
|
|
3763
|
-
}, /*#__PURE__*/React__namespace.default.createElement(material.Typography, {
|
|
3764
|
-
variant: "h6",
|
|
3765
|
-
sx: {
|
|
3766
|
-
fontSize: "16px",
|
|
3767
|
-
fontWeight: 600,
|
|
3768
|
-
marginTop: 2,
|
|
3769
|
-
color: "rgb(37, 37, 37)"
|
|
3770
|
-
}
|
|
3771
|
-
}, "Saved Computed Dimensions"), /*#__PURE__*/React__namespace.default.createElement(material.Typography, {
|
|
3772
|
-
sx: {
|
|
3773
|
-
fontSize: "13px",
|
|
3774
|
-
color: "#666",
|
|
3775
|
-
marginBottom: 2
|
|
3776
|
-
}
|
|
3777
|
-
}, "Drag to reorder or use arrows"), /*#__PURE__*/React__namespace.default.createElement(core.DndContext, {
|
|
3778
|
-
sensors: sensors,
|
|
3779
|
-
collisionDetection: core.closestCenter,
|
|
3780
|
-
onDragEnd: handleComputedDragEnd
|
|
3781
|
-
}, /*#__PURE__*/React__namespace.default.createElement(sortable.SortableContext, {
|
|
3782
|
-
items: savedComputedDimensions.map((_, index) => index),
|
|
3783
|
-
strategy: sortable.verticalListSortingStrategy
|
|
3784
|
-
}, /*#__PURE__*/React__namespace.default.createElement(material.Box, {
|
|
3785
|
-
sx: {
|
|
3786
|
-
display: "flex",
|
|
3787
|
-
flexDirection: "column",
|
|
3788
|
-
gap: 1
|
|
3789
|
-
}
|
|
3790
|
-
}, savedComputedDimensions.map((cd, index) => /*#__PURE__*/React__namespace.default.createElement(SortableComputedChip, {
|
|
3791
|
-
key: index,
|
|
3778
|
+
}) : /*#__PURE__*/React__namespace.default.createElement(SortableComputedChip, {
|
|
3779
|
+
key: `comp-${item.key}`,
|
|
3792
3780
|
id: index,
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
value: cd.value,
|
|
3781
|
+
name: item.data.name,
|
|
3782
|
+
value: item.data.value,
|
|
3796
3783
|
onUpdate: onUpdateComputedDimension,
|
|
3797
3784
|
isNameTaken: isComputedNameTaken,
|
|
3798
|
-
onDelete: () => onRemoveComputedDimension(
|
|
3799
|
-
onMoveUp: () =>
|
|
3800
|
-
onMoveDown: () =>
|
|
3785
|
+
onDelete: () => onRemoveComputedDimension(item.key),
|
|
3786
|
+
onMoveUp: () => handleMoveUp(index),
|
|
3787
|
+
onMoveDown: () => handleMoveDown(index),
|
|
3801
3788
|
isFirst: index === 0,
|
|
3802
|
-
isLast: index ===
|
|
3789
|
+
isLast: index === orderedItems.length - 1
|
|
3803
3790
|
})))))));
|
|
3804
3791
|
};
|
|
3805
3792
|
|
|
@@ -5782,9 +5769,8 @@ const formatValue = (value, def) => {
|
|
|
5782
5769
|
const isNumericType = type => type === 'integer' || type === 'currency';
|
|
5783
5770
|
const ReportDataGrid = ({
|
|
5784
5771
|
reportData,
|
|
5785
|
-
|
|
5772
|
+
orderedDimensionItems = [],
|
|
5786
5773
|
metrics,
|
|
5787
|
-
computedDimensions = [],
|
|
5788
5774
|
loading,
|
|
5789
5775
|
onPageChange,
|
|
5790
5776
|
totalRows = 0,
|
|
@@ -5804,11 +5790,26 @@ const ReportDataGrid = ({
|
|
|
5804
5790
|
const columns = React__namespace.default.useMemo(() => {
|
|
5805
5791
|
const cols = [];
|
|
5806
5792
|
|
|
5807
|
-
// Add dimension columns
|
|
5808
|
-
//
|
|
5793
|
+
// Add dimension + computed-dimension columns, in the single unified
|
|
5794
|
+
// order the user arranged them in on the Dimensions tab.
|
|
5795
|
+
// Field naming logic (dimensions):
|
|
5809
5796
|
// - If from base provider: baseAlias.field -> baseAlias_field
|
|
5810
5797
|
// - If from nested provider: baseAlias_rel1_rel2.field -> rel1_rel2_field (drops base alias)
|
|
5811
|
-
dimensions
|
|
5798
|
+
// Computed dimensions have no provider/relations chain, so the API
|
|
5799
|
+
// returns each row keyed by the computed dimension's own `name`.
|
|
5800
|
+
orderedDimensionItems.forEach(item => {
|
|
5801
|
+
if (item.kind === 'computed') {
|
|
5802
|
+
const cd = item.data;
|
|
5803
|
+
cols.push({
|
|
5804
|
+
field: cd.name,
|
|
5805
|
+
headerName: cd.name,
|
|
5806
|
+
flex: 1,
|
|
5807
|
+
minWidth: 150,
|
|
5808
|
+
type: 'string'
|
|
5809
|
+
});
|
|
5810
|
+
return;
|
|
5811
|
+
}
|
|
5812
|
+
const dim = item.data;
|
|
5812
5813
|
let fieldName;
|
|
5813
5814
|
let headerName;
|
|
5814
5815
|
|
|
@@ -5846,18 +5847,6 @@ const ReportDataGrid = ({
|
|
|
5846
5847
|
});
|
|
5847
5848
|
});
|
|
5848
5849
|
|
|
5849
|
-
// Add computed dimension columns. These have no provider/relations chain,
|
|
5850
|
-
// so the API returns each row keyed by the computed dimension's own `name`.
|
|
5851
|
-
computedDimensions.forEach(cd => {
|
|
5852
|
-
cols.push({
|
|
5853
|
-
field: cd.name,
|
|
5854
|
-
headerName: cd.name,
|
|
5855
|
-
flex: 1,
|
|
5856
|
-
minWidth: 150,
|
|
5857
|
-
type: 'string'
|
|
5858
|
-
});
|
|
5859
|
-
});
|
|
5860
|
-
|
|
5861
5850
|
// Add metric columns
|
|
5862
5851
|
// The API returns metric keys in two different forms depending on the path depth:
|
|
5863
5852
|
//
|
|
@@ -5917,7 +5906,7 @@ const ReportDataGrid = ({
|
|
|
5917
5906
|
});
|
|
5918
5907
|
});
|
|
5919
5908
|
return cols;
|
|
5920
|
-
}, [
|
|
5909
|
+
}, [orderedDimensionItems, metrics, titleOverrides, parameters]);
|
|
5921
5910
|
|
|
5922
5911
|
// Transform report data to rows with unique IDs.
|
|
5923
5912
|
// Keys are normalised by replacing dots with underscores so that MUI DataGrid
|
|
@@ -6024,7 +6013,10 @@ const ReportBuilder = ({
|
|
|
6024
6013
|
dimensions: [],
|
|
6025
6014
|
metrics: [],
|
|
6026
6015
|
filters: {},
|
|
6027
|
-
computedDimensions: []
|
|
6016
|
+
computedDimensions: [],
|
|
6017
|
+
// Unified display/execution order across dimensions + computedDimensions.
|
|
6018
|
+
// Entries: { type: 'dimension', key: fullPath } | { type: 'computed', key: name }
|
|
6019
|
+
dimensionOrder: []
|
|
6028
6020
|
});
|
|
6029
6021
|
const [titleOverrides, setTitleOverrides] = React.useState({
|
|
6030
6022
|
dimensions: {},
|
|
@@ -6070,6 +6062,16 @@ const ReportBuilder = ({
|
|
|
6070
6062
|
}
|
|
6071
6063
|
}, [autoRun, reportLoaded]);
|
|
6072
6064
|
|
|
6065
|
+
// Re-run the currently displayed report when base_currency changes in context
|
|
6066
|
+
const currentBaseCurrency = reportingContext?.parameters?.base_currency;
|
|
6067
|
+
const prevBaseCurrencyRef = React.useRef(currentBaseCurrency);
|
|
6068
|
+
React.useEffect(() => {
|
|
6069
|
+
if (reportData && prevBaseCurrencyRef.current !== undefined && prevBaseCurrencyRef.current !== currentBaseCurrency) {
|
|
6070
|
+
runReportWithPagination(currentPage, pageSize);
|
|
6071
|
+
}
|
|
6072
|
+
prevBaseCurrencyRef.current = currentBaseCurrency;
|
|
6073
|
+
}, [currentBaseCurrency]);
|
|
6074
|
+
|
|
6073
6075
|
// Utility function to reconstruct dimension object from fullPath
|
|
6074
6076
|
const reconstructDimensionFromPath = (fullPath, providersData, rootProvider) => {
|
|
6075
6077
|
try {
|
|
@@ -6199,6 +6201,52 @@ const ReportBuilder = ({
|
|
|
6199
6201
|
return null;
|
|
6200
6202
|
}
|
|
6201
6203
|
};
|
|
6204
|
+
|
|
6205
|
+
// Build the unified display/execution order for dimensions + computed
|
|
6206
|
+
// dimensions. Prefers the persisted `ordered_dimensions` field; falls back
|
|
6207
|
+
// to "dimensions first, then computed dimensions" for report definitions
|
|
6208
|
+
// saved before this field existed.
|
|
6209
|
+
const buildDimensionOrder = (rawOrderedDimensions, dimensions, computedDimensions) => {
|
|
6210
|
+
const dimensionOrder = [];
|
|
6211
|
+
const seenDimensionKeys = new Set();
|
|
6212
|
+
const seenComputedKeys = new Set();
|
|
6213
|
+
if (Array.isArray(rawOrderedDimensions)) {
|
|
6214
|
+
rawOrderedDimensions.forEach(entry => {
|
|
6215
|
+
if (entry.type === "dimension" && dimensions.some(d => d.fullPath === entry.ref)) {
|
|
6216
|
+
dimensionOrder.push({
|
|
6217
|
+
type: "dimension",
|
|
6218
|
+
key: entry.ref
|
|
6219
|
+
});
|
|
6220
|
+
seenDimensionKeys.add(entry.ref);
|
|
6221
|
+
} else if (entry.type === "computed" && computedDimensions.some(cd => cd.name === entry.ref)) {
|
|
6222
|
+
dimensionOrder.push({
|
|
6223
|
+
type: "computed",
|
|
6224
|
+
key: entry.ref
|
|
6225
|
+
});
|
|
6226
|
+
seenComputedKeys.add(entry.ref);
|
|
6227
|
+
}
|
|
6228
|
+
});
|
|
6229
|
+
}
|
|
6230
|
+
|
|
6231
|
+
// Append anything not covered by ordered_dimensions (older reports, or drift)
|
|
6232
|
+
dimensions.forEach(d => {
|
|
6233
|
+
if (!seenDimensionKeys.has(d.fullPath)) {
|
|
6234
|
+
dimensionOrder.push({
|
|
6235
|
+
type: "dimension",
|
|
6236
|
+
key: d.fullPath
|
|
6237
|
+
});
|
|
6238
|
+
}
|
|
6239
|
+
});
|
|
6240
|
+
computedDimensions.forEach(cd => {
|
|
6241
|
+
if (!seenComputedKeys.has(cd.name)) {
|
|
6242
|
+
dimensionOrder.push({
|
|
6243
|
+
type: "computed",
|
|
6244
|
+
key: cd.name
|
|
6245
|
+
});
|
|
6246
|
+
}
|
|
6247
|
+
});
|
|
6248
|
+
return dimensionOrder;
|
|
6249
|
+
};
|
|
6202
6250
|
const loadReportDefinition = async id => {
|
|
6203
6251
|
try {
|
|
6204
6252
|
console.log("Loading report definition:", id);
|
|
@@ -6294,13 +6342,15 @@ const ReportBuilder = ({
|
|
|
6294
6342
|
// Computed dimensions are self-contained { name, value } pairs with no
|
|
6295
6343
|
// provider/relation chain, so they're loaded as-is (no reconstruction needed)
|
|
6296
6344
|
const computedDimensions = reportDef.definition?.doc?.query?.computed_dimensions || [];
|
|
6345
|
+
const dimensionOrder = buildDimensionOrder(reportDef.definition?.doc?.query?.ordered_dimensions, reconstructedDimensions, computedDimensions);
|
|
6297
6346
|
|
|
6298
6347
|
// Set the report state
|
|
6299
6348
|
setReport({
|
|
6300
6349
|
dimensions: reconstructedDimensions,
|
|
6301
6350
|
metrics: reconstructedMetrics,
|
|
6302
6351
|
filters: loadedFilters,
|
|
6303
|
-
computedDimensions
|
|
6352
|
+
computedDimensions,
|
|
6353
|
+
dimensionOrder
|
|
6304
6354
|
});
|
|
6305
6355
|
|
|
6306
6356
|
// Set title overrides
|
|
@@ -6409,13 +6459,15 @@ const ReportBuilder = ({
|
|
|
6409
6459
|
// Computed dimensions are self-contained { name, value } pairs with no
|
|
6410
6460
|
// provider/relation chain, so they're loaded as-is (no reconstruction needed)
|
|
6411
6461
|
const computedDimensions = reportDef.definition?.doc?.query?.computed_dimensions || [];
|
|
6462
|
+
const dimensionOrder = buildDimensionOrder(reportDef.definition?.doc?.query?.ordered_dimensions, reconstructedDimensions, computedDimensions);
|
|
6412
6463
|
|
|
6413
6464
|
// Set the report state
|
|
6414
6465
|
setReport({
|
|
6415
6466
|
dimensions: reconstructedDimensions,
|
|
6416
6467
|
metrics: reconstructedMetrics,
|
|
6417
6468
|
filters: loadedFilters,
|
|
6418
|
-
computedDimensions
|
|
6469
|
+
computedDimensions,
|
|
6470
|
+
dimensionOrder
|
|
6419
6471
|
});
|
|
6420
6472
|
|
|
6421
6473
|
// Set title overrides
|
|
@@ -6448,7 +6500,8 @@ const ReportBuilder = ({
|
|
|
6448
6500
|
dimensions: [],
|
|
6449
6501
|
metrics: [],
|
|
6450
6502
|
filters: {},
|
|
6451
|
-
computedDimensions: []
|
|
6503
|
+
computedDimensions: [],
|
|
6504
|
+
dimensionOrder: []
|
|
6452
6505
|
});
|
|
6453
6506
|
// Reset title overrides
|
|
6454
6507
|
setTitleOverrides({
|
|
@@ -6525,51 +6578,68 @@ const ReportBuilder = ({
|
|
|
6525
6578
|
setReport(prev => {
|
|
6526
6579
|
const newReport = {
|
|
6527
6580
|
...prev,
|
|
6528
|
-
dimensions: [...prev.dimensions, dimensionData]
|
|
6581
|
+
dimensions: [...prev.dimensions, dimensionData],
|
|
6582
|
+
dimensionOrder: [...prev.dimensionOrder, {
|
|
6583
|
+
type: "dimension",
|
|
6584
|
+
key: dimensionData.fullPath
|
|
6585
|
+
}]
|
|
6529
6586
|
};
|
|
6530
6587
|
console.log("Dimension saved:", dimensionData);
|
|
6531
6588
|
console.log("Complete report:", newReport);
|
|
6532
6589
|
return newReport;
|
|
6533
6590
|
});
|
|
6534
6591
|
};
|
|
6535
|
-
const handleRemoveDimension =
|
|
6592
|
+
const handleRemoveDimension = fullPath => {
|
|
6536
6593
|
setReport(prev => ({
|
|
6537
6594
|
...prev,
|
|
6538
|
-
dimensions: prev.dimensions.filter(
|
|
6595
|
+
dimensions: prev.dimensions.filter(d => d.fullPath !== fullPath),
|
|
6596
|
+
dimensionOrder: prev.dimensionOrder.filter(entry => !(entry.type === "dimension" && entry.key === fullPath))
|
|
6539
6597
|
}));
|
|
6540
6598
|
};
|
|
6541
|
-
const
|
|
6599
|
+
const handleUpdateDimensionSortOrder = (fullPath, sortOrder) => {
|
|
6542
6600
|
setReport(prev => ({
|
|
6543
6601
|
...prev,
|
|
6544
|
-
dimensions:
|
|
6602
|
+
dimensions: prev.dimensions.map(d => d.fullPath === fullPath ? {
|
|
6603
|
+
...d,
|
|
6604
|
+
sortOrder
|
|
6605
|
+
} : d)
|
|
6545
6606
|
}));
|
|
6546
6607
|
};
|
|
6547
|
-
|
|
6608
|
+
|
|
6609
|
+
// Reorders the single unified dimensions + computed-dimensions list;
|
|
6610
|
+
// `dimensions`/`computedDimensions` arrays themselves are unordered from
|
|
6611
|
+
// this perspective, so only `dimensionOrder` needs to change.
|
|
6612
|
+
const handleReorderDimensionItems = newDimensionOrder => {
|
|
6548
6613
|
setReport(prev => ({
|
|
6549
6614
|
...prev,
|
|
6550
|
-
|
|
6615
|
+
dimensionOrder: newDimensionOrder
|
|
6551
6616
|
}));
|
|
6552
6617
|
};
|
|
6553
|
-
const
|
|
6554
|
-
setReport(prev => {
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
}
|
|
6561
|
-
});
|
|
6618
|
+
const handleSaveComputedDimension = computedDimensionData => {
|
|
6619
|
+
setReport(prev => ({
|
|
6620
|
+
...prev,
|
|
6621
|
+
computedDimensions: [...prev.computedDimensions, computedDimensionData],
|
|
6622
|
+
dimensionOrder: [...prev.dimensionOrder, {
|
|
6623
|
+
type: "computed",
|
|
6624
|
+
key: computedDimensionData.name
|
|
6625
|
+
}]
|
|
6626
|
+
}));
|
|
6562
6627
|
};
|
|
6563
|
-
const
|
|
6628
|
+
const handleUpdateComputedDimension = (name, computedDimensionData) => {
|
|
6564
6629
|
setReport(prev => ({
|
|
6565
6630
|
...prev,
|
|
6566
|
-
computedDimensions: prev.computedDimensions.
|
|
6631
|
+
computedDimensions: prev.computedDimensions.map(cd => cd.name === name ? computedDimensionData : cd),
|
|
6632
|
+
dimensionOrder: prev.dimensionOrder.map(entry => entry.type === "computed" && entry.key === name ? {
|
|
6633
|
+
...entry,
|
|
6634
|
+
key: computedDimensionData.name
|
|
6635
|
+
} : entry)
|
|
6567
6636
|
}));
|
|
6568
6637
|
};
|
|
6569
|
-
const
|
|
6638
|
+
const handleRemoveComputedDimension = name => {
|
|
6570
6639
|
setReport(prev => ({
|
|
6571
6640
|
...prev,
|
|
6572
|
-
computedDimensions:
|
|
6641
|
+
computedDimensions: prev.computedDimensions.filter(cd => cd.name !== name),
|
|
6642
|
+
dimensionOrder: prev.dimensionOrder.filter(entry => !(entry.type === "computed" && entry.key === name))
|
|
6573
6643
|
}));
|
|
6574
6644
|
};
|
|
6575
6645
|
const handleSaveMetric = metricData => {
|
|
@@ -6625,10 +6695,20 @@ const ReportBuilder = ({
|
|
|
6625
6695
|
});
|
|
6626
6696
|
};
|
|
6627
6697
|
|
|
6628
|
-
//
|
|
6629
|
-
|
|
6698
|
+
// Builds the query object shared between running (paginated) and saving
|
|
6699
|
+
// (unpaginated) a report. Dimension and computed-dimension order both
|
|
6700
|
+
// derive from the single unified `report.dimensionOrder` list, so the
|
|
6701
|
+
// saved `dimensions`/`computed_dimensions` arrays, `order_by`, and the
|
|
6702
|
+
// persisted `ordered_dimensions` field all stay consistent with whatever
|
|
6703
|
+
// order the user arranged on screen.
|
|
6704
|
+
const buildQueryObject = () => {
|
|
6705
|
+
const dimensionByPath = Object.fromEntries(report.dimensions.map(d => [d.fullPath, d]));
|
|
6706
|
+
const computedByName = Object.fromEntries(report.computedDimensions.map(cd => [cd.name, cd]));
|
|
6707
|
+
const orderedDimensionsOnly = report.dimensionOrder.filter(entry => entry.type === "dimension").map(entry => dimensionByPath[entry.key]).filter(Boolean);
|
|
6708
|
+
const orderedComputedOnly = report.dimensionOrder.filter(entry => entry.type === "computed").map(entry => computedByName[entry.key]).filter(Boolean);
|
|
6709
|
+
|
|
6630
6710
|
// Build order_by array - include all dimensions, add desc property only when needed
|
|
6631
|
-
const orderBy =
|
|
6711
|
+
const orderBy = orderedDimensionsOnly.map(dim => {
|
|
6632
6712
|
const orderItem = {
|
|
6633
6713
|
name: dim.fullPath
|
|
6634
6714
|
};
|
|
@@ -6684,21 +6764,29 @@ const ReportBuilder = ({
|
|
|
6684
6764
|
titles.filters = titleOverrides.filters;
|
|
6685
6765
|
}
|
|
6686
6766
|
const queryObj = {
|
|
6687
|
-
dimensions:
|
|
6767
|
+
dimensions: orderedDimensionsOnly.map(dim => dim.fullPath),
|
|
6688
6768
|
metrics: report.metrics.map(metric => metric.fullPath),
|
|
6689
|
-
order_by: orderBy
|
|
6690
|
-
limit: size,
|
|
6691
|
-
offset: page * size
|
|
6769
|
+
order_by: orderBy
|
|
6692
6770
|
};
|
|
6693
6771
|
|
|
6694
6772
|
// Only add computed_dimensions if there are any
|
|
6695
|
-
if (
|
|
6696
|
-
queryObj.computed_dimensions =
|
|
6773
|
+
if (orderedComputedOnly.length > 0) {
|
|
6774
|
+
queryObj.computed_dimensions = orderedComputedOnly.map(cd => ({
|
|
6697
6775
|
name: cd.name,
|
|
6698
6776
|
value: cd.value
|
|
6699
6777
|
}));
|
|
6700
6778
|
}
|
|
6701
6779
|
|
|
6780
|
+
// Persist the unified dimension + computed-dimension order so it can be
|
|
6781
|
+
// reconstructed on reload and so executed reports render columns in the
|
|
6782
|
+
// same order they were arranged in the builder.
|
|
6783
|
+
if (report.dimensionOrder.length > 0) {
|
|
6784
|
+
queryObj.ordered_dimensions = report.dimensionOrder.map(entry => ({
|
|
6785
|
+
type: entry.type,
|
|
6786
|
+
ref: entry.key
|
|
6787
|
+
}));
|
|
6788
|
+
}
|
|
6789
|
+
|
|
6702
6790
|
// Only add titles if there are any overrides
|
|
6703
6791
|
if (Object.keys(titles).length > 0) {
|
|
6704
6792
|
queryObj.titles = titles;
|
|
@@ -6708,6 +6796,14 @@ const ReportBuilder = ({
|
|
|
6708
6796
|
if (filter) {
|
|
6709
6797
|
queryObj.filter = filter;
|
|
6710
6798
|
}
|
|
6799
|
+
return queryObj;
|
|
6800
|
+
};
|
|
6801
|
+
|
|
6802
|
+
// Convert internal report structure to API format
|
|
6803
|
+
const convertReportToApiFormat = (page = 0, size = 50) => {
|
|
6804
|
+
const queryObj = buildQueryObject();
|
|
6805
|
+
queryObj.limit = size;
|
|
6806
|
+
queryObj.offset = page * size;
|
|
6711
6807
|
|
|
6712
6808
|
// Get parameters from context if available, otherwise use default
|
|
6713
6809
|
const parameters = reportingContext?.parameters || {
|
|
@@ -6801,77 +6897,7 @@ const ReportBuilder = ({
|
|
|
6801
6897
|
}
|
|
6802
6898
|
try {
|
|
6803
6899
|
setSaving(true);
|
|
6804
|
-
|
|
6805
|
-
// Build order_by array - include all dimensions, add desc property only when needed
|
|
6806
|
-
const orderBy = report.dimensions.map(dim => {
|
|
6807
|
-
const orderItem = {
|
|
6808
|
-
name: dim.fullPath
|
|
6809
|
-
};
|
|
6810
|
-
if (dim.sortOrder === "desc") {
|
|
6811
|
-
orderItem.desc = true;
|
|
6812
|
-
}
|
|
6813
|
-
// For 'asc' or null, just include { name: fullPath } without desc property
|
|
6814
|
-
return orderItem;
|
|
6815
|
-
});
|
|
6816
|
-
|
|
6817
|
-
// Build titles object - only include overridden titles
|
|
6818
|
-
const titles = {};
|
|
6819
|
-
if (Object.keys(titleOverrides.dimensions).length > 0) {
|
|
6820
|
-
titles.dimensions = titleOverrides.dimensions;
|
|
6821
|
-
}
|
|
6822
|
-
if (Object.keys(titleOverrides.metrics).length > 0) {
|
|
6823
|
-
titles.metrics = titleOverrides.metrics;
|
|
6824
|
-
}
|
|
6825
|
-
if (Object.keys(titleOverrides.filters).length > 0) {
|
|
6826
|
-
titles.filters = titleOverrides.filters;
|
|
6827
|
-
}
|
|
6828
|
-
const queryObj = {
|
|
6829
|
-
dimensions: report.dimensions.map(dim => dim.fullPath),
|
|
6830
|
-
metrics: report.metrics.map(metric => metric.fullPath),
|
|
6831
|
-
order_by: orderBy
|
|
6832
|
-
};
|
|
6833
|
-
|
|
6834
|
-
// Only add computed_dimensions if there are any
|
|
6835
|
-
if (report.computedDimensions && report.computedDimensions.length > 0) {
|
|
6836
|
-
queryObj.computed_dimensions = report.computedDimensions.map(cd => ({
|
|
6837
|
-
name: cd.name,
|
|
6838
|
-
value: cd.value
|
|
6839
|
-
}));
|
|
6840
|
-
}
|
|
6841
|
-
|
|
6842
|
-
// Only add titles if there are any overrides
|
|
6843
|
-
if (Object.keys(titles).length > 0) {
|
|
6844
|
-
queryObj.titles = titles;
|
|
6845
|
-
}
|
|
6846
|
-
|
|
6847
|
-
// Add filter if there are any - NEW API format with top-level 'and' operator
|
|
6848
|
-
// NEW format: { and: [ { "ft.currency": ["USD", "EUR"] }, { "ft_ba.created_at": {gte: "2025-05-01", lte: "2025-12-31"} } ] }
|
|
6849
|
-
if (Object.keys(report.filters).length > 0) {
|
|
6850
|
-
const conditions = [];
|
|
6851
|
-
Object.entries(report.filters).forEach(([fullPath, filterData]) => {
|
|
6852
|
-
if (filterData.values) {
|
|
6853
|
-
// Check if values is an object (date range) or array (regular filter)
|
|
6854
|
-
if (Array.isArray(filterData.values)) {
|
|
6855
|
-
// Regular filter - only add if array has values
|
|
6856
|
-
if (filterData.values.length > 0) {
|
|
6857
|
-
conditions.push({
|
|
6858
|
-
[fullPath]: filterData.values
|
|
6859
|
-
});
|
|
6860
|
-
}
|
|
6861
|
-
} else if (typeof filterData.values === "object") {
|
|
6862
|
-
// Date range filter - add the object as-is
|
|
6863
|
-
conditions.push({
|
|
6864
|
-
[fullPath]: filterData.values
|
|
6865
|
-
});
|
|
6866
|
-
}
|
|
6867
|
-
}
|
|
6868
|
-
});
|
|
6869
|
-
if (conditions.length > 0) {
|
|
6870
|
-
queryObj.filter = {
|
|
6871
|
-
and: conditions
|
|
6872
|
-
};
|
|
6873
|
-
}
|
|
6874
|
-
}
|
|
6900
|
+
const queryObj = buildQueryObject();
|
|
6875
6901
|
|
|
6876
6902
|
// Build the doc object
|
|
6877
6903
|
const docObj = {
|
|
@@ -6916,6 +6942,18 @@ const ReportBuilder = ({
|
|
|
6916
6942
|
}
|
|
6917
6943
|
};
|
|
6918
6944
|
const canSaveReport = selectedProvider && reportTitle.trim() && (report.dimensions.length > 0 || report.metrics.length > 0 || report.computedDimensions.length > 0);
|
|
6945
|
+
|
|
6946
|
+
// Resolve the unified dimensionOrder into actual dimension/computed-dimension
|
|
6947
|
+
// objects so the results grid can render columns in that same order.
|
|
6948
|
+
const dimensionByFullPath = Object.fromEntries(report.dimensions.map(d => [d.fullPath, d]));
|
|
6949
|
+
const computedDimensionByName = Object.fromEntries(report.computedDimensions.map(cd => [cd.name, cd]));
|
|
6950
|
+
const orderedDimensionItems = report.dimensionOrder.map(entry => entry.type === "dimension" ? {
|
|
6951
|
+
kind: "dimension",
|
|
6952
|
+
data: dimensionByFullPath[entry.key]
|
|
6953
|
+
} : {
|
|
6954
|
+
kind: "computed",
|
|
6955
|
+
data: computedDimensionByName[entry.key]
|
|
6956
|
+
}).filter(item => item.data);
|
|
6919
6957
|
return /*#__PURE__*/React__namespace.default.createElement(material.Box, {
|
|
6920
6958
|
sx: {
|
|
6921
6959
|
p: 3,
|
|
@@ -7194,7 +7232,7 @@ const ReportBuilder = ({
|
|
|
7194
7232
|
savedDimensions: report.dimensions,
|
|
7195
7233
|
onSaveDimension: handleSaveDimension,
|
|
7196
7234
|
onRemoveDimension: handleRemoveDimension,
|
|
7197
|
-
|
|
7235
|
+
onUpdateDimensionSortOrder: handleUpdateDimensionSortOrder,
|
|
7198
7236
|
titleOverrides: titleOverrides.dimensions,
|
|
7199
7237
|
onUpdateTitle: handleUpdateDimensionTitle,
|
|
7200
7238
|
onResetTitle: handleResetDimensionTitle,
|
|
@@ -7204,7 +7242,8 @@ const ReportBuilder = ({
|
|
|
7204
7242
|
onSaveComputedDimension: handleSaveComputedDimension,
|
|
7205
7243
|
onUpdateComputedDimension: handleUpdateComputedDimension,
|
|
7206
7244
|
onRemoveComputedDimension: handleRemoveComputedDimension,
|
|
7207
|
-
|
|
7245
|
+
dimensionOrder: report.dimensionOrder,
|
|
7246
|
+
onReorderDimensionItems: handleReorderDimensionItems
|
|
7208
7247
|
})), /*#__PURE__*/React__namespace.default.createElement(TabPanel, {
|
|
7209
7248
|
value: activeTab,
|
|
7210
7249
|
index: 1
|
|
@@ -7240,9 +7279,8 @@ const ReportBuilder = ({
|
|
|
7240
7279
|
index: 3
|
|
7241
7280
|
}, reportData && /*#__PURE__*/React__namespace.default.createElement(ReportDataGrid, {
|
|
7242
7281
|
reportData: reportData,
|
|
7243
|
-
|
|
7282
|
+
orderedDimensionItems: orderedDimensionItems,
|
|
7244
7283
|
metrics: report.metrics,
|
|
7245
|
-
computedDimensions: report.computedDimensions,
|
|
7246
7284
|
loading: loading,
|
|
7247
7285
|
onPageChange: handlePageChange,
|
|
7248
7286
|
totalRows: totalRows,
|
|
@@ -7305,6 +7343,44 @@ const ReportDefinitionsManager = () => {
|
|
|
7305
7343
|
});
|
|
7306
7344
|
};
|
|
7307
7345
|
|
|
7346
|
+
// TODO: replace with currencies fetched from the API once that's available.
|
|
7347
|
+
const CURRENCY_OPTIONS = [{
|
|
7348
|
+
key: "USD",
|
|
7349
|
+
value: "USD"
|
|
7350
|
+
}, {
|
|
7351
|
+
key: "EUR",
|
|
7352
|
+
value: "EUR"
|
|
7353
|
+
}, {
|
|
7354
|
+
key: "SEK",
|
|
7355
|
+
value: "SEK"
|
|
7356
|
+
}, {
|
|
7357
|
+
key: "GBP",
|
|
7358
|
+
value: "GBP"
|
|
7359
|
+
}, {
|
|
7360
|
+
key: "DKK",
|
|
7361
|
+
value: "DKK"
|
|
7362
|
+
}, {
|
|
7363
|
+
key: "NOK",
|
|
7364
|
+
value: "NOK"
|
|
7365
|
+
}];
|
|
7366
|
+
const CurrencySelector = () => {
|
|
7367
|
+
const {
|
|
7368
|
+
parameters,
|
|
7369
|
+
setParameters
|
|
7370
|
+
} = useReportingContext();
|
|
7371
|
+
return /*#__PURE__*/React__namespace.default.createElement(SingleSelect, {
|
|
7372
|
+
items: CURRENCY_OPTIONS,
|
|
7373
|
+
value: parameters.base_currency,
|
|
7374
|
+
label: "Currency",
|
|
7375
|
+
onChange: e => setParameters({
|
|
7376
|
+
...parameters,
|
|
7377
|
+
base_currency: e.target.value
|
|
7378
|
+
}),
|
|
7379
|
+
sx: {
|
|
7380
|
+
width: 110
|
|
7381
|
+
}
|
|
7382
|
+
});
|
|
7383
|
+
};
|
|
7308
7384
|
const ReportApp = ({
|
|
7309
7385
|
params,
|
|
7310
7386
|
api
|
|
@@ -7371,7 +7447,13 @@ const ReportApp = ({
|
|
|
7371
7447
|
}
|
|
7372
7448
|
}
|
|
7373
7449
|
})
|
|
7374
|
-
}, /*#__PURE__*/React__namespace.default.createElement(
|
|
7450
|
+
}, /*#__PURE__*/React__namespace.default.createElement(Box__default.default, {
|
|
7451
|
+
sx: {
|
|
7452
|
+
display: "flex",
|
|
7453
|
+
justifyContent: "flex-end",
|
|
7454
|
+
p: 1
|
|
7455
|
+
}
|
|
7456
|
+
}, /*#__PURE__*/React__namespace.default.createElement(CurrencySelector, null)), /*#__PURE__*/React__namespace.default.createElement(ReportDefinitionsManager, null))));
|
|
7375
7457
|
};
|
|
7376
7458
|
|
|
7377
7459
|
var index = {
|