Skip to content

Update native progress bar and doughnut chart widget with new features #270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/jsActions/mobile-resources-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@
"rimraf": "^4.4.1",
"rollup": "^2.79.2"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

## [2.2.0] - 2025-5-16

### Changed

- We added the option to add spacing between slices.

## [2.1.1] - 2025-3-18

### Fixed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pie-doughnut-chart-native",
"widgetName": "PieDoughnutChart",
"version": "2.1.1",
"version": "2.2.0",
"license": "Apache-2.0",
"copyright": "© Mendix Technology BV 2022. All rights reserved.",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ChartStyle, defaultStyle } from "./ui/Styles";
import { useSeries } from "./utils/SeriesLoader";

export function PieDoughnutChart(props: PieDoughnutChartProps<ChartStyle>): ReactElement | null {
const { series: chartSeries, style, name, sortOrder, ...rest } = props;
const { series: chartSeries, style, name, sortOrder,slicespace, ...rest } = props;
const series = useSeries(chartSeries, name);

if (!series) {
Expand All @@ -17,6 +17,7 @@ export function PieDoughnutChart(props: PieDoughnutChartProps<ChartStyle>): Reac
return (
<PieDoughnutChartComponent
name={name}
slicespace = {slicespace}
series={series
.flatMap(_series => _series.slices)
.sort((a, b) => (sortOrder === "ascending" ? a.y - b.y : b.y - a.y))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<widget id="com.mendix.widget.native.piedoughnutchart.PieDoughnutChart" supportedPlatform="Native" offlineCapable="true"
pluginWidget="true" xmlns="http://www.mendix.com/widget/1.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../../../../node_modules/mendix/custom_widget.xsd">
<widget id="com.mendix.widget.native.piedoughnutchart.PieDoughnutChart" supportedPlatform="Native" offlineCapable="true" pluginWidget="true" xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../../../../node_modules/mendix/custom_widget.xsd">
<name>Pie Doughnut Chart</name>
<description>Render a series of data in a Pie or Doughnut chart.</description>
<studioProCategory>Charts</studioProCategory>
Expand All @@ -12,7 +9,7 @@
<propertyGroup caption="Presentation">
<property key="presentation" type="enumeration" defaultValue="pie">
<caption>Presentation</caption>
<description/>
<description />
<enumerationValues>
<enumerationValue key="pie">Pie</enumerationValue>
<enumerationValue key="doughnut">Doughnut</enumerationValue>
Expand All @@ -29,34 +26,31 @@
<caption>Data source</caption>
<description>Data points for individual series.</description>
</property>
<property key="XAttribute" type="attribute"
dataSource="dataSource">
<property key="XAttribute" type="attribute" dataSource="dataSource">
<caption>X attribute</caption>
<description/>
<description />
<attributeTypes>
<attributeType name="DateTime"/>
<attributeType name="String"/>
<attributeType name="Enum"/>
<attributeType name="DateTime" />
<attributeType name="String" />
<attributeType name="Enum" />
</attributeTypes>
</property>
<property key="YAttribute" type="attribute"
dataSource="dataSource">
<property key="YAttribute" type="attribute" dataSource="dataSource">
<caption>Y attribute</caption>
<description/>
<description />
<attributeTypes>
<attributeType name="Decimal"/>
<attributeType name="Integer"/>
<attributeType name="Long"/>
<attributeType name="Decimal" />
<attributeType name="Integer" />
<attributeType name="Long" />
</attributeTypes>
</property>
<property key="sliceStylingKey" type="attribute" dataSource="dataSource" required="false">
<caption>Dynamic styling key</caption>
<description>Configure which attribute is used as the key that matches with styling defined in Atlas.</description>
<attributeTypes>
<attributeType name="String"/>
<attributeType name="Enum"/>
<attributeType name="String" />
<attributeType name="Enum" />
</attributeTypes>

</property>
</propertyGroup>
</properties>
Expand All @@ -73,12 +67,16 @@
<propertyGroup caption="Chart settings">
<property key="showLabels" type="boolean" defaultValue="true">
<caption>Show labels</caption>
<description/>
<description />
</property>
<property key="slicespace" type="integer" defaultValue="0">
<caption>Space between slices</caption>
<description />
</property>
</propertyGroup>
<propertyGroup caption="Common">
<systemProperty key="Name"/>
<systemProperty key="Visibility"/>
<systemProperty key="Name" />
<systemProperty key="Visibility" />
</propertyGroup>
</propertyGroup>
</properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface ChartProps {
style: ChartStyle;
presentation: string;
showLabels: boolean;
slicespace: number;
}

export type DataPoints = Array<Slice<string, number>>;
Expand All @@ -26,7 +27,7 @@ export interface Slice<X extends string, Y extends number> {
stylingKey: Option<string>;
}

export function PieDoughnutChart({ name, presentation, series, style, showLabels }: ChartProps): ReactElement | null {
export function PieDoughnutChart({ name, presentation, series, style, showLabels,slicespace }: ChartProps): ReactElement | null {
// due to the nature of the chart type, we only reply on the width, as the chart is always a square
const [chartDimensions, setChartDimensions] = useState<{ width?: number }>();
// Chart user-styling may be missing for certain slices. A palette is passed, any missing colours
Expand Down Expand Up @@ -94,6 +95,7 @@ export function PieDoughnutChart({ name, presentation, series, style, showLabels
: undefined
}
colorScale={normalizedSliceColors}
padAngle={slicespace}
/>
) : null}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface PieDoughnutChartProps<Style> {
series: SeriesType[];
sortOrder: SortOrderEnum;
showLabels: boolean;
slicespace: number;
}

export interface PieDoughnutChartPreviewProps {
Expand All @@ -48,4 +49,5 @@ export interface PieDoughnutChartPreviewProps {
series: SeriesPreviewType[];
sortOrder: SortOrderEnum;
showLabels: boolean;
slicespace: number | null;
}
6 changes: 6 additions & 0 deletions packages/pluggableWidgets/progress-bar-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

## [4.4.0] - 2025-5-16

### Changed

- We added the option to add caption to the progress bar showing the percentage of competition with the ability to customize the filled and unfilled bar color.

## [4.3.1] - 2025-2-7

- Bumped the version of the react-native-progress to fix black background issues.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "progress-bar-native",
"widgetName": "ProgressBar",
"version": "4.3.1",
"version": "4.4.0",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { flattenStyles } from "@mendix/piw-native-utils-internal";
import { isAvailable } from "@mendix/piw-utils-internal";
import { createElement } from "react";
import { Text, View } from "react-native";
import { createElement,useState } from "react";
import { Text, View,I18nManager,ViewStyle } from "react-native";
import { Bar } from "react-native-progress";

import { ProgressBarProps } from "../typings/ProgressBarProps";
Expand All @@ -11,7 +11,7 @@ export type Props = ProgressBarProps<ProgressBarStyle>;

export function ProgressBar(props: ProgressBarProps<ProgressBarStyle>): JSX.Element {
const styles = flattenStyles(defaultProgressBarStyle, props.style);

const [barWidth, setBarWidth] = useState(0);
const validate = (): string[] => {
const messages: string[] = [];
const { minimumValue, maximumValue, progressValue } = props;
Expand All @@ -27,7 +27,36 @@ export function ProgressBar(props: ProgressBarProps<ProgressBarStyle>): JSX.Elem
}
return messages;
};
// const screenWidth = Dimensions.get("window").width;


const getCaptionStyle = (progress: number, barWidth: number): ViewStyle => {
const labelWidth = 50; // estimate or measure dynamically
const progressX = barWidth * progress;
//const clampedLTR = Math.max(0, Math.min(progressX, barWidth - labelWidth));
// const clampedRTL = Math.max(0, Math.min(barWidth - progressX, barWidth - labelWidth));

// Center the label over the progress position
const centeredX = progressX - labelWidth / 2;

// Clamp to keep the label within bounds
const clampedLTR = Math.max(0, Math.min(centeredX, barWidth - labelWidth));
const clampedRTL = Math.max(0, Math.min(barWidth - progressX - labelWidth / 2, barWidth - labelWidth));

return I18nManager.isRTL
? {
position: "absolute" as const,
right: clampedRTL,
top: -6,
transform: [{ translateX: 0 }]
}
: {
position: "absolute" as const,
left: clampedLTR,
top: -6,
transform: [{ translateX: 0 }]
};
};
const calculateProgress = (): number => {
const { minimumValue, maximumValue, progressValue } = props;

Expand All @@ -52,21 +81,50 @@ export function ProgressBar(props: ProgressBarProps<ProgressBarStyle>): JSX.Elem

const validationMessages = validate();
const progress = calculateProgress();

const { showProgressCaption, showDefaultProgressCaption,progressCaption,useDefaulMendixColor,customColor,customUnfilledColor} = props;
return (
<View style={styles.container}>
<View
style={styles.container}
onLayout={event => {
const width = event.nativeEvent.layout.width;
setBarWidth(width);
}}
>

<Bar
testID={props.name}
height={Number(styles.bar.height)}
width={null}
progress={progress}
color={styles.fill.backgroundColor}
color={useDefaulMendixColor ? styles.fill.backgroundColor : customColor}
unfilledColor={useDefaulMendixColor ? "#fff" : customUnfilledColor}
borderWidth={styles.bar.borderWidth}
style={styles.bar}
//style={styles.bar}
/>
{showProgressCaption && (
<View style={getCaptionStyle(progress, barWidth)}>
<View
style={{
backgroundColor: useDefaulMendixColor ? styles.fill.backgroundColor : customColor, // blue
borderRadius: 5,
paddingHorizontal: 8,
paddingVertical: 2,
minWidth: 40,
alignItems: "center",
justifyContent: "center"
}}
>
<Text style={{
color: "#fff", // White caption text
fontWeight:"bold"
}}>
{ showDefaultProgressCaption ? parseFloat((progress * 100).toFixed(2))+'%' :progressCaption?.value}
</Text>
</View>
{validationMessages.length > 0 && (
<Text style={styles.validationMessage}>{validationMessages.join("\n")}</Text>
)}
</View> )}
</View>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<widget id="com.mendix.widget.native.progressbar.ProgressBar" supportedPlatform="Native" needsEntityContext="true" offlineCapable="true" pluginWidget="true" xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../../../node_modules/mendix/custom_widget.xsd">
<name>Progress bar</name>
<description>Display progress in a horizontal bar.</description>
Expand All @@ -7,24 +7,49 @@
<properties>
<propertyGroup caption="General">
<propertyGroup caption="Data source">
<property key="progressValue" type="expression" defaultValue="0">
<caption>Current value</caption>
<description>The current progress value.</description>
<returnType type="Decimal"/>
</property>
<property key="minimumValue" type="expression" defaultValue="0">
<caption>Minimum value</caption>
<description>The lowest possible progress value. If current value is lower than this value, progress will be still minimum value</description>
<returnType type="Decimal"/>
<returnType type="Decimal" />
</property>
<property key="maximumValue" type="expression" defaultValue="100">
<caption>Maximum value</caption>
<description>The highest possible progress value. If current value is higher than this value, progress will be still maximum value</description>
<returnType type="Decimal"/>
<returnType type="Decimal" />
</property>
<property key="progressValue" type="expression" defaultValue="0">
<caption>Current value</caption>
<description>The current progress value.</description>
<returnType type="Decimal" />
</property>
<property key="showProgressCaption" type="boolean" defaultValue="true">
<caption>Show Progress Caption</caption>
<description />
</property>
<property key="showDefaultProgressCaption" type="boolean" defaultValue="true">
<caption>Show Default Caption</caption>
<description>e.g 70%</description>
</property>
<property key="progressCaption" type="textTemplate" required="false">
<caption>Custom progress caption</caption>
<description />
</property>
<property key="useDefaulMendixColor" type="boolean" defaultValue="true">
<caption>Default Color</caption>
<description>Use mendix default progress color</description>
</property>
<property key="customColor" type="string" required="false">
<caption>Filled Color Code</caption>
<description>HEX code e.g. #ff5733</description>
</property>
<property key="customUnfilledColor" type="string" required="false">
<caption>UnFilled Color Code</caption>
<description>HEX code e.g. #ff5733</description>
</property>
</propertyGroup>

<propertyGroup caption="Common">
<systemProperty key="Name"/>
<systemProperty key="Name" />
</propertyGroup>
</propertyGroup>
</properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ import { Big } from "big.js";
export interface ProgressBarProps<Style> {
name: string;
style: Style[];
progressValue: DynamicValue<Big>;
minimumValue: DynamicValue<Big>;
maximumValue: DynamicValue<Big>;
progressValue: DynamicValue<Big>;
showProgressCaption: boolean;
showDefaultProgressCaption: boolean;
progressCaption?: DynamicValue<string>;
useDefaulMendixColor: boolean;
customColor: string;
customUnfilledColor: string;
}

export interface ProgressBarPreviewProps {
Expand All @@ -25,7 +31,13 @@ export interface ProgressBarPreviewProps {
styleObject?: CSSProperties;
readOnly: boolean;
renderMode?: "design" | "xray" | "structure";
progressValue: string;
minimumValue: string;
maximumValue: string;
progressValue: string;
showProgressCaption: boolean;
showDefaultProgressCaption: boolean;
progressCaption: string;
useDefaulMendixColor: boolean;
customColor: string;
customUnfilledColor: string;
}
Loading