Skip to content

Commit

Permalink
feat: add percentFormatter prop to PieWidgetUI (#844)
Browse files Browse the repository at this point in the history
* feat: add percentFormatter prop to PieWidgetUI

* chore: add changelog registry

* fix: include percentFormatter PieWidgetUI in types.d.ts
  • Loading branch information
jantolg committed Mar 5, 2024
1 parent 23d543a commit 50e81b8
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CHANGELOG

## Not released
- Add percentFormatter prop in PieWidgetUI, allowing to format percent values [#844](https://github.com/CartoDB/carto-react/pull/844)
- Fix Snowflake spatial index detection [#845](https://github.com/CartoDB/carto-react/pull/845)
- Fix TimeSeriesWidgetUI check undefined echart.getInstance().getDom() [#842](https://github.com/CartoDB/carto-react/pull/842)
- Update MultipleSelectField placeholder text color [#846](https://github.com/CartoDB/carto-react/pull/846)
Expand Down
1 change: 1 addition & 0 deletions packages/react-ui/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export type PieWidgetUI = {
data: PieWidgetUIData;
formatter?: Function;
tooltipFormatter?: Function;
percentFormatter?: Function;
height?: string;
colors?: string[];
selectedCategories?: string[];
Expand Down
26 changes: 20 additions & 6 deletions packages/react-ui/src/widgets/PieWidgetUI/PieWidgetUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function PieWidgetUI({
data = [],
formatter,
tooltipFormatter,
percentFormatter,
height,
width,
labels,
Expand All @@ -67,7 +68,12 @@ function PieWidgetUI({
const { showSkeleton } = useSkeleton(isLoading);
const intl = useIntl();
const intlConfig = useImperativeIntl(intl);

const _percentFormatter = useMemo(
() =>
percentFormatter ||
((v) => `${intl.formatNumber(v, { maximumFractionDigits: 2 })}%`),
[intl, percentFormatter]
);
// Tooltip
const tooltipOptions = useMemo(
() => ({
Expand All @@ -77,14 +83,17 @@ function PieWidgetUI({
textStyle: { color: theme.palette.common.white },
confine: true,
formatter:
!!tooltipFormatter && ((params) => tooltipFormatter({ ...params, formatter }))
!!tooltipFormatter &&
((params) =>
tooltipFormatter({ ...params, formatter, percentFormatter: _percentFormatter }))
}),
[
theme.spacingValue,
theme.palette.black,
theme.palette.common.white,
tooltipFormatter,
formatter
formatter,
_percentFormatter
]
);

Expand Down Expand Up @@ -233,7 +242,11 @@ function PieWidgetUI({
)}

<ChartContent height={height} width={width}>
<PieCentralText data={processedData} selectedCategories={selectedCategories} />
<PieCentralText
data={processedData}
selectedCategories={selectedCategories}
formatter={_percentFormatter}
/>

<Chart
option={options}
Expand Down Expand Up @@ -281,6 +294,7 @@ PieWidgetUI.propTypes = {
colors: PropTypes.array,
formatter: PropTypes.func,
tooltipFormatter: PropTypes.func,
percentFormatter: PropTypes.func,
height: PropTypes.string,
width: PropTypes.string,
animation: PropTypes.bool,
Expand All @@ -297,12 +311,12 @@ export default PieWidgetUI;
// Aux
function tooltipFormatter(params) {
const value = processFormatterRes(params.formatter(params.value));

const percentage = params?.percentFormatter(params.percent) || `${params.percent}%`;
const markerColor = params.data.color || params.textStyle.color;
const markerStyle = `display:inline-block;border-radius:4px;width:8px;height:8px;background-color:${markerColor}`;

return `
<div style="white-space:normal;"><p style="max-width:${CHART_SIZE};font-size:11px;font-weight:500;line-height:1.454;text-transform:uppercase;margin:0 0 4px 0;">${params.name}</p>
<p style="display:flex;align-items:center;font-size: 11px;font-weight:500;line-height:1.454;margin:0;"><span style="${markerStyle}"></span> <span style="margin:0 4px;font-weight:400;">${value}</span> (${params.percent}%)</p></div>
<p style="display:flex;align-items:center;font-size: 11px;font-weight:500;line-height:1.454;margin:0;"><span style="${markerStyle}"></span> <span style="margin:0 4px;font-weight:400;">${value}</span> (${percentage})</p></div>
`.trim();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const MarkerColor = styled(Box)(({ theme }) => ({
height: theme.spacing(1)
}));

function PieCentralText({ data, selectedCategories }) {
function PieCentralText({ data, selectedCategories, formatter }) {
const [selectedItem, setSelectedItem] = useState({});

// Select the largest category to display in CentralText and calculate its percentage from the total
Expand Down Expand Up @@ -57,11 +57,11 @@ function PieCentralText({ data, selectedCategories }) {
sumValue += category.value;
}

const percentage = calculatePercentage(category.value, sumValue);
const percentage = calculatePercentage(category.value, sumValue, formatter);
category.percentage = percentage;

return category;
}, [data, selectedCategories]);
}, [data, selectedCategories, formatter]);

useEffect(() => {
if (topSelectedCategory) {
Expand Down Expand Up @@ -96,7 +96,8 @@ PieCentralText.propTypes = {
color: PropTypes.string
})
),
selectedCategories: PropTypes.array
selectedCategories: PropTypes.array,
formatter: PropTypes.func
};

export default PieCentralText;
11 changes: 6 additions & 5 deletions packages/react-ui/src/widgets/utils/chartUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ export function findLargestCategory(array) {
}

// Calculate the percentage of a value in relation to a total
export function calculatePercentage(value, total) {
if (total === 0) {
return '0.00%'; // Avoid division by zero
export function calculatePercentage(value, total, formatter) {
let percentage = 0;

if (total !== 0) {
percentage = (value / total) * 100;
}

const percentage = ((value / total) * 100).toFixed(2); // Limit to two decimals
return `${percentage}%`;
return formatter ? formatter(percentage) : `${percentage}%`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,15 @@ CollapseMoreThan12Categories.args = CollapseCategoriesProps;
export const Loading = LoadingTemplate.bind({});
const LoadingProps = { data: dataDefault, isLoading: true };
Loading.args = LoadingProps;

export const CustomPercentFormatter = Template.bind({});
const CustomPercentFormatterProps = {
data: dataDefault,
formatter: (v) => `${v} units`,
percentFormatter: (v) =>
`${Intl.NumberFormat('en', {
maximumFractionDigits: 3,
minimumFractionDigits: 3
}).format(v)}%`
};
CustomPercentFormatter.args = CustomPercentFormatterProps;

0 comments on commit 50e81b8

Please sign in to comment.