display all data in statistics & analysis and hide percentages with values below zero
This commit is contained in:
@@ -13,8 +13,9 @@ export interface CommonPieChartDataItem {
|
||||
name: string;
|
||||
displayName: string;
|
||||
value: number;
|
||||
actualValue: number;
|
||||
percent: number;
|
||||
actualPercent: number;
|
||||
paintPercent: number;
|
||||
color: ColorStyleValue;
|
||||
sourceItem: Record<string, unknown>;
|
||||
displayPercent?: string;
|
||||
@@ -30,7 +31,6 @@ export interface CommonPieChartProps {
|
||||
percentField?: string;
|
||||
colorField?: string;
|
||||
hiddenField?: string;
|
||||
minValidPercent?: number;
|
||||
amountValue?: boolean;
|
||||
defaultCurrency?: string;
|
||||
showValue?: boolean;
|
||||
@@ -55,32 +55,38 @@ export function usePieChartBase(props: CommonPieChartProps) {
|
||||
}
|
||||
|
||||
const validItems: CommonPieChartDataItem[] = [];
|
||||
let accumulatedPaintPercent: number = 0;
|
||||
|
||||
for (const item of props.items) {
|
||||
const value = item[props.valueField];
|
||||
const percent = props.percentField ? item[props.percentField] : -1;
|
||||
|
||||
if (isNumber(value) && value > 0 &&
|
||||
(!props.hiddenField || !item[props.hiddenField]) &&
|
||||
(!props.minValidPercent || value / totalValidValue > props.minValidPercent)) {
|
||||
if (isNumber(value) &&
|
||||
(!props.hiddenField || !item[props.hiddenField])) {
|
||||
const finalItem: CommonPieChartDataItem = {
|
||||
id: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string,
|
||||
name: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string,
|
||||
displayName: item[props.nameField] as string,
|
||||
value: value,
|
||||
percent: (isNumber(percent) && percent >= 0) ? percent : (value / totalValidValue * 100),
|
||||
actualPercent: value / totalValidValue,
|
||||
value: value > 0 ? value : 0,
|
||||
actualValue: value,
|
||||
percent: (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0),
|
||||
paintPercent: value > 0 ? value / totalValidValue : 0,
|
||||
color: getDisplayColor((props.colorField && item[props.colorField]) ? item[props.colorField] as ColorValue : DEFAULT_CHART_COLORS[validItems.length % DEFAULT_CHART_COLORS.length]),
|
||||
sourceItem: item
|
||||
};
|
||||
|
||||
finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01');
|
||||
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(finalItem.value, props.defaultCurrency) : finalItem.value.toString();
|
||||
accumulatedPaintPercent += finalItem.paintPercent;
|
||||
finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01');
|
||||
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString();
|
||||
|
||||
validItems.push(finalItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (validItems.length > 0) {
|
||||
validItems[validItems.length - 1]!.paintPercent += 1 - accumulatedPaintPercent;
|
||||
}
|
||||
|
||||
return validItems;
|
||||
});
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ const chartOptions = computed<object>(() => {
|
||||
}
|
||||
|
||||
if (isNumber(dataItem.percent) && dataItem.percent > 0) {
|
||||
const displayPercent = formatPercentToLocalizedNumerals(dataItem.percent, 2, '<0.01');
|
||||
const displayPercent = formatPercentToLocalizedNumerals(dataItem.percent, 2, '<0.01');
|
||||
tooltip += `<span class="ms-1" style="float: inline-end">(${displayPercent})</span>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -396,7 +396,7 @@ function getItemName(name: string): string {
|
||||
|
||||
function getDisplayValue(value: number): string {
|
||||
if (props.oneHundredPercentStacked) {
|
||||
return formatPercentToLocalizedNumerals(value, 2, '<0.01');
|
||||
return formatPercentToLocalizedNumerals(value, 2, '<0.01');
|
||||
}
|
||||
|
||||
if (props.amountValue) {
|
||||
|
||||
@@ -142,11 +142,14 @@ const chartOptions = computed<object>(() => {
|
||||
tooltip += `<div class="d-inline-flex">${name}</div><br/>`;
|
||||
}
|
||||
|
||||
if (props.showValue && props.showPercent) {
|
||||
const showValue = props.showValue;
|
||||
const showPercent = props.showPercent && params.value && (params.value as number) > 0;
|
||||
|
||||
if (showValue && showPercent) {
|
||||
tooltip += `<div class="d-inline-flex"><span>${value}</span><span class="ms-1">(${percent})</span></div>`;
|
||||
} else if (props.showValue && !props.showPercent) {
|
||||
} else if (showValue && !showPercent) {
|
||||
tooltip += `<div class="d-inline-flex">${value}</div>`;
|
||||
} else if (!props.showValue && props.showPercent) {
|
||||
} else if (!showValue && showPercent) {
|
||||
tooltip += `<div class="d-inline-flex">${percent}</div>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ const props = defineProps<{
|
||||
percentField?: string;
|
||||
colorField?: string;
|
||||
hiddenField?: string;
|
||||
minValidPercent?: number;
|
||||
amountValue?: boolean;
|
||||
defaultCurrency?: string;
|
||||
showValue?: boolean;
|
||||
@@ -74,14 +73,13 @@ const radarData = computed<RadarChartData>(() => {
|
||||
const value = item[props.valueField];
|
||||
const percent = props.percentField ? item[props.percentField] : -1;
|
||||
|
||||
if (isNumber(value) && value > 0 &&
|
||||
(!props.hiddenField || !item[props.hiddenField]) &&
|
||||
(!props.minValidPercent || value / totalValidValue > props.minValidPercent)) {
|
||||
if (isNumber(value) &&
|
||||
(!props.hiddenField || !item[props.hiddenField])) {
|
||||
const name = item[props.nameField] as string;
|
||||
const color = getDisplayColor((props.colorField && item[props.colorField]) ? item[props.colorField] as ColorValue : DEFAULT_CHART_COLORS[indicators.length % DEFAULT_CHART_COLORS.length]);
|
||||
|
||||
const finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value / totalValidValue * 100);
|
||||
const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01');
|
||||
const finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0);
|
||||
const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01');
|
||||
const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString();
|
||||
|
||||
indicators.push({
|
||||
@@ -90,16 +88,19 @@ const radarData = computed<RadarChartData>(() => {
|
||||
color: isDarkMode.value ? '#ccc' : '#333'
|
||||
});
|
||||
|
||||
values.push(value);
|
||||
values.push(value > 0 ? value : 0);
|
||||
|
||||
tooltip += '<div><span class="chart-pointer" style="background-color: ' + color + '"></span>';
|
||||
tooltip += `<span>${name}</span>`;
|
||||
|
||||
if (props.showValue && props.showPercent) {
|
||||
const showValue = props.showValue;
|
||||
const showPercent = props.showPercent && value > 0;
|
||||
|
||||
if (showValue && showPercent) {
|
||||
tooltip += `<span class="ms-1" style="float: inline-end">(${displayPercent})</span><span class="ms-5" style="float: inline-end">${displayValue}</span>`;
|
||||
} else if (props.showValue && !props.showPercent) {
|
||||
} else if (showValue && !showPercent) {
|
||||
tooltip += `<span class="ms-5" style="float: inline-end">${displayValue}</span>`;
|
||||
} else if (!props.showValue && props.showPercent) {
|
||||
} else if (!showValue && showPercent) {
|
||||
tooltip += `<span class="ms-5" style="float: inline-end">${displayPercent}</span>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,19 @@
|
||||
<svg class="pie-chart" :viewBox="`${-diameter} ${-diameter} ${diameter * 2} ${diameter * 2}`">
|
||||
<circle class="pie-chart-background" cx="0" cy="0" :r="diameter"></circle>
|
||||
|
||||
<circle class="pie-chart-item"
|
||||
fill="transparent"
|
||||
cx="0" cy="0"
|
||||
:r="diameter / 2"
|
||||
:stroke="item.color"
|
||||
:stroke-width="diameter"
|
||||
:stroke-dasharray="getItemStrokeDash(item)"
|
||||
:stroke-dashoffset="getItemDashOffset(item, validItems, itemCommonDashOffset)"
|
||||
:key="idx"
|
||||
v-for="(item, idx) in validItems"
|
||||
@click="switchSelectedIndex(idx)">
|
||||
</circle>
|
||||
<template :key="idx" v-for="(item, idx) in validItems">
|
||||
<circle class="pie-chart-item"
|
||||
fill="transparent"
|
||||
cx="0" cy="0"
|
||||
:r="diameter / 2"
|
||||
:stroke="item.color"
|
||||
:stroke-width="diameter"
|
||||
:stroke-dasharray="getItemStrokeDash(item)"
|
||||
:stroke-dashoffset="getItemDashOffset(item, validItems, itemCommonDashOffset)"
|
||||
@click="switchSelectedIndex(idx)"
|
||||
v-if="item.actualValue > 0 && item.paintPercent > minPaintPercent">
|
||||
</circle>
|
||||
</template>
|
||||
|
||||
<circle class="pie-chart-text-background"
|
||||
cx="0" cy="0"
|
||||
@@ -44,7 +45,7 @@
|
||||
</f7-link>
|
||||
|
||||
<div class="pie-chart-toolbox-info">
|
||||
<p v-if="showPercent && selectedItem">
|
||||
<p v-if="showPercent && selectedItem && selectedItem.actualValue >= 0">
|
||||
<f7-chip class="chip-placeholder" outline v-if="skeleton">
|
||||
<span class="skeleton-text">Percent</span>
|
||||
</f7-chip>
|
||||
@@ -53,7 +54,7 @@
|
||||
:style="getColorStyle(selectedItem?.color, '--f7-chip-outline-border-color')"
|
||||
v-else-if="!skeleton"></f7-chip>
|
||||
</p>
|
||||
<p v-else-if="showPercent && (!validItems || !validItems.length)">
|
||||
<p v-else-if="showPercent && (!validItems || !validItems.length || !selectedItem || selectedItem.actualValue < 0)">
|
||||
<f7-chip outline text="---"></f7-chip>
|
||||
</p>
|
||||
<f7-link class="pie-chart-selected-item-info" :no-link-class="!enableClickItem" v-if="selectedItem" @click="clickItem(selectedItem)">
|
||||
@@ -99,6 +100,7 @@ const emit = defineEmits<{
|
||||
const { tt } = useI18n();
|
||||
const { selectedIndex, validItems } = usePieChartBase(props);
|
||||
|
||||
const minPaintPercent = 0.0001; // 0.01%
|
||||
const diameter: number = 100;
|
||||
const circumference: number = diameter * Math.PI;
|
||||
|
||||
@@ -106,7 +108,9 @@ const totalValidValue = computed<number>(() => {
|
||||
let totalValidValue = 0;
|
||||
|
||||
for (const item of validItems.value) {
|
||||
totalValidValue += item.value;
|
||||
if (item.actualValue > 0 && item.paintPercent > minPaintPercent) {
|
||||
totalValidValue += item.value;
|
||||
}
|
||||
}
|
||||
|
||||
return totalValidValue;
|
||||
@@ -122,11 +126,17 @@ const itemCommonDashOffset = computed<number>(() => {
|
||||
for (let i = 0; i < Math.min(selectedIndex.value + 1, validItems.value.length); i++) {
|
||||
const item = validItems.value[i] as CommonPieChartDataItem;
|
||||
|
||||
if (item.actualPercent > 0) {
|
||||
if (item.actualValue > 0 && item.paintPercent > minPaintPercent) {
|
||||
if (i === selectedIndex.value) {
|
||||
offset += -circumference * (1 - item.actualPercent) / 2;
|
||||
offset += -circumference * (1 - item.paintPercent) / 2;
|
||||
} else {
|
||||
offset += -circumference * (1 - item.actualPercent);
|
||||
offset += -circumference * (1 - item.paintPercent);
|
||||
}
|
||||
} else {
|
||||
if (i === selectedIndex.value) {
|
||||
offset += -circumference / 2;
|
||||
} else {
|
||||
offset += -circumference;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +157,7 @@ function getColorStyle(color: ColorStyleValue, additionalFieldName?: string): Re
|
||||
}
|
||||
|
||||
function getItemStrokeDash(item: CommonPieChartDataItem): string {
|
||||
const length = item.actualPercent * circumference;
|
||||
const length = item.paintPercent * circumference;
|
||||
return `${length} ${circumference - length}`;
|
||||
}
|
||||
|
||||
@@ -159,7 +169,7 @@ function getItemDashOffset(item: CommonPieChartDataItem, items: CommonPieChartDa
|
||||
break;
|
||||
}
|
||||
|
||||
allPreviousPercent += curItem.actualPercent;
|
||||
allPreviousPercent += curItem.paintPercent > 0 ? curItem.paintPercent : 0;
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
|
||||
Reference in New Issue
Block a user